對於模糊人臉圖片和原圖的清晰度評估——sobel運算元
阿新 • • 發佈:2019-01-08
評估影象清晰度是一個常見的問題。寫了c和matlab兩個版本的簡單程式碼,日後可以拿來就用。
模糊的圖片一般可以分為兩種,動態模糊或者對焦模糊。顧名思義,動態模糊就相當於一個頭在你面前晃啊晃的看不清,對焦模糊就是你離遠點把眼睛摘了看人(視力好的人請按alt+f4)。
上面三個,中間是原圖,左邊是動態模糊,右邊是對焦模糊。
質量評價也簡單,你只要給清晰的圖片打分高於模糊圖片,只要分差明顯,隨便用點數學公式就可以換算到任何評分標準體系了。
處理這種問題其實很簡單。就是sobel運算元的一個應用問題。因為模糊的圖片必然比清晰的原圖具有更加不清楚的邊緣。所以你提取不出來啊,做個邊緣提取之後,原圖肯定留下更多的1,所以這個時候再算個平均值,就搞定了。
別廢話上程式碼:
這個c的函式,就是輸入一個灰度值陣列,和圖片長寬,返回一個評價值。
float estimate(unsigned char *pData, int width, int height) { int i = 0, j = 0; unsigned char *pixel; int *image0,*image90,*image45,*image135; int a1,a2,a3,b1,b2,b3,c1,c2,c3; int threshold = 100; float *image; float sum=0.0; pixel = (unsigned char*)malloc(sizeof(unsigned char)*(width*height)); image0 = (int*)malloc(sizeof(int)*(width*height)); image45 = (int*)malloc(sizeof(int)*(width*height)); image90 = (int*)malloc(sizeof(int)*(width*height)); image135 = (int*)malloc(sizeof(int)*(width*height)); image = (float*)malloc(sizeof(float)*(width*height)); //inite for(i=0; i < height; i++) for(j = 0; j <width; j++){ pixel[i*width+j] = pData[i*width+j]; } // a1 a2 a3 // b1 b2 b3 // c1 c2 c3 // replicate for the bounds, the nearest one for(i = 0; i < height; i++) for(j = 0; j< width; j++){ if(i == 0){//upper line, left-up and right-up corners if(j == 0){//left-up corner a1 = pixel[0]; a2 = pixel[0]; a3 = pixel[1]; b1 = pixel[0]; b2 = pixel[0]; b3 = pixel[1]; c1 = pixel[width]; c2 = pixel[width]; c3 = pixel[width+1]; } else if(j == (width-1)){//left-right corner a1 = pixel[width-2]; a2 = pixel[width-1]; a3 = pixel[width-1]; b1 = pixel[width-2]; b2 = pixel[width-1]; b3 = pixel[width]-1; c1 = pixel[2*width-2]; c2 = pixel[2*width-1]; c3 = pixel[2*width-1]; } else{ a1 = pixel[j-1]; a2 = pixel[j]; a3 = pixel[j+1]; b1 = a1; b2 = a2; b3 = a3; c1 = pixel[width+j-1]; c2 = pixel[width+j]; c3 = pixel[width+j+1]; } } else if(j == 0){//left row and left-down corner if(i == (height-1)){//left-down corner a1 = pixel[(i-1)*width]; a2 = a1; a3 = pixel[(i-1)*width + 1]; b1 = pixel[i*width]; b2 = b1; b3 = pixel[i*width + 1]; c1 = b2; c2 = b2; c3 = b3; } else{ a1 = pixel[(i-1)*width]; a2 = a1; a3 = pixel[(i-1)*width + 1]; b1 = pixel[i*width]; b2 = b1; b3 = pixel[i*width + 1]; c1 = pixel[(i+1)*width]; c2 = c1; c3 = pixel[(i+1)*width + 1]; } } else if(i == (height-1)){//down line and down-right corner if(j == (width-1)){//down-right corner a1 = pixel[(i-1)*width + j-1]; a2 = pixel[(i-1)*width + j]; a3 = a2; b1 = pixel[i*width + j-1]; b2 = pixel[i*width + j]; b3 = b2; c1 = b1; c2 = b2; c3 = b2; } else{ a1 = pixel[(i-1)*width + j-1]; a2 = pixel[(i-1)*width + j]; a3 = pixel[(i-1)*width + j+1]; b1 = pixel[i*width + j-1]; b2 = pixel[i*width + j]; b3 = pixel[i*width + j+1]; c1 = b1; c2 = b2; c3 = b3; } } else if(j == (width-1)){//right row a1 = pixel[(i-1)*width + j-1]; a2 = pixel[(i-1)*width + j]; a3 = a2; b1 = pixel[i*width + j-1]; b2 = pixel[i*width + j]; b3 = b2; c1 = pixel[(i+1)*width-1]; c2 = pixel[(i+1)*width-1]; c3 = c2; } else{ a1 = pixel[(i-1)*width + j-1]; a2 = pixel[(i-1)*width + j]; a3 = pixel[(i-1)*width + j+1]; b1 = pixel[i*width + j-1]; b2 = pixel[i*width + j]; b3 = pixel[i*width + j+1]; c1 = pixel[(i+1)*width+ j-1]; c2 = pixel[(i+1)*width+ j]; c3 = pixel[(i+1)*width+ j+1]; } //corr // 0:-1 0 1 45:-2 -1 0 90:1 2 1 135:0 -1 -2 // -2 0 2 -1 0 1 0 0 0 1 0 -1 // -1 0 1 0 1 2 -1 -2 -1 2 1 0 image0[i*width+j] = -a1 + a3 -2*b1 + 2*b3 -c1 + c3; if (image0[i*width+j] < 100) image0[i*width+j] = 0; else image0[i*width+j] = 1; image45[i*width+j] = -2*a1 - a2 - b1 + b3 + c2 + 2*c3; if (image45[i*width+j] < 100) image45[i*width+j] = 0; else image45[i*width+j] = 1; image90[i*width+j] = a1 + 2*a2 + a3 - c1 - 2*c2 - c3; if (image90[i*width+j] < 100) image90[i*width+j] = 0; else image90[i*width+j] = 1; image135[i*width+j] = -a2 - 2*a3 + b1 - b3 + 2*c1 + c2; if (image135[i*width+j] < 100) image135[i*width+j] = 0; else image135[i*width+j] = 1; } //combination for(i=0; i <height-1; i++) for(j=0; j < width-1; j++) image[i*width+j] = (float)(image0[i*width+j]+image45[i*width+j]+image90[i*width+j]+image135[i*width+j])/4; //return the average gary value for(i=0; i <height-1; i++) for(j=0; j < width-1; j++) sum = (float)sum + image[i*width+j]; sum =(float) sum/(height*width); return sum; }
matlab的程式碼同時讀兩個圖片,編號0是原圖,編號1是模糊圖。最後兩個圖的值同時給出來。有一些冗餘程式碼,別介意。
%45°和135°角邊緣檢測;用於那些邊界不明顯的圖片 sobel45=[-2 -1 0; -1 0 1; 0 1 2]; sobel135=[0 -1 -2; 1 0 -1; 2 1 0]; sobel0=[-1 0 1; -2 0 2; -1 0 1]; sobel90=[1 2 1; 0 0 0; -1 -2 -1]; SourcePic1 = imread('/home/ydt/桌面/m22.jpg'); SourcePic0 = imread('/home/ydt/桌面/m21.jpg'); subplot(6, 2, 1); imshow(SourcePic0),title('origin'); %subplot(211); subplot(6,2,2); imshow(SourcePic1),title('dynamic'); grayPic0 = rgb2gray(SourcePic0); grayPic1 = rgb2gray(SourcePic1); %grayPic0 = im2double(grayPic0); %grayPic1 = im2double(grayPic1); subplot(6, 2, 3); imshow(grayPic0),title('origin-gray'); subplot(6, 2, 4); imshow(grayPic1),title('dynamic-gray'); Threshold1 = 100; SFST45 = imfilter(grayPic0,sobel45,'replicate'); SFST45=SFST45>=Threshold1; I01 = SFST45; subplot(625); imshow(SFST45),title('45') ; SFST45=imfilter(grayPic1,sobel45,'replicate'); SFST45=SFST45>=Threshold1; I11 = SFST45; subplot(626); imshow(SFST45),title('45') ; Threshold2 = 100; SFST135 = imfilter(grayPic0,sobel135,'replicate'); SFST135=SFST135>=Threshold2; I02 = SFST135; subplot(627); imshow(SFST135),title('135') ; SFST135 = imfilter(grayPic1,sobel135,'replicate'); SFST135=SFST135>=Threshold2; I12 = SFST135; subplot(628); imshow(SFST135),title('135') ; Threshold3 = 100; SFST0 = imfilter(grayPic0,sobel0,'replicate'); SFST0=SFST0>=Threshold3; I03 = SFST0; subplot(629); imshow(SFST0),title('90') ; SFST0 = imfilter(grayPic1,sobel0,'replicate'); SFST0=SFST0>=Threshold3; I13 = SFST0; subplot(6,2,10); imshow(SFST0),title('90') ; Threshold4 = 100; SFST90 = imfilter(grayPic0,sobel90,'replicate'); SFST90=SFST90>=Threshold4; I04 = SFST90; subplot(6,2,11); imshow(SFST90),title('0') ; SFST90 = imfilter(grayPic1,sobel90,'replicate'); SFST90=SFST90>=Threshold4; I14 = SFST90; subplot(6,2,12); imshow(SFST90),title('0') ; I0 = (I01 + I02 + I03 + I04)/4; I1 = (I11 + I12 + I13 + I14)/4; subplot(2,1,1); imshow(I0),title('origin') ; subplot(2,1,2); imshow(I1),title('motion') ; [M0,N0] = size(I0); [M1,N1] = size(I1); %I = (I0 + I1)/2; % subplot(111); % imshow(I),title('sobel') ; % sum = 0; % for i=1:M0*N0 % sum = I(i)+sum; % end % m=sum/M0/N0; sum = 0; for i=1:M0*N0 sum = I0(i)+sum; end sum1 = sum/(M0*N0); %c0 = 1- abs(sum1-m); sum = 0; for i=1:M1*N1 sum = I1(i)+sum; end sum2 = sum/(M1*N1); %c1 = 1- abs(sum2-m); fprintf('Average gray value after sobel detecting, Origin: %12.6f\n', sum1); fprintf('Average gray value after sobel detecting, Motion: %12.6f\n', sum2);
總的來說,有一個侷限性。就是隻能保證同一個人的圖片,清晰的比模糊的強。這只是一個相對的結果,自行設定模糊與清晰的分界線,但是並不是說在絕對的情況下,任何低於這個值的都是模糊。非常簡單的一個演算法。