對於模糊人臉圖片和原圖的清晰度評估——sobel算子

評估圖像清晰度是一個常見的問題。寫了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);


總的來說,有一個侷限性。就是隻能保證同一個人的圖片,清晰的比模糊的強。這只是一個相對的結果,自行設定模糊與清晰的分界線,但是並不是說在絕對的情況下,任何低於這個值的都是模糊。非常簡單的一個算法。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章