評估圖像清晰度是一個常見的問題。寫了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);
總的來說,有一個侷限性。就是隻能保證同一個人的圖片,清晰的比模糊的強。這只是一個相對的結果,自行設定模糊與清晰的分界線,但是並不是說在絕對的情況下,任何低於這個值的都是模糊。非常簡單的一個算法。