要从一个视野的不同高度拍的一组图片中选出最清晰的一张,看了论文《基于边缘特征的光学图像清晰度判定》,试了下,好像比之前的效果好。
int AutoFocus::gradientdimg(Mat &grayimg)
{
if(!grayimg.data)
{
cout<<"error:invalid image..."<<endl;
return -1;
}
for(int r=0;r!=mysize_.height-2;r++)
{
for(int c=0;c!=mysize_.width-2;c++)
{
gradient_dimg.ptr<float>(r)[c]=sqrt(
( (int(grayimg.ptr<uchar>(r)[c])-int(grayimg.ptr<uchar>(r)[c+2])) * (int(grayimg.ptr<uchar>(r)[c])-int(grayimg.ptr<uchar>(r)[c+2])) )
+ ( (int(grayimg.ptr<uchar>(r)[c])-int(grayimg.ptr<uchar>(r+2)[c])) * (int(grayimg.ptr<uchar>(r)[c])-int(grayimg.ptr<uchar>(r+2)[c])))
);
}
}
return 0;
}
int AutoFocus::directiongradient()
{
float direction_s[4]={0};
float d1=0,d2=0,d3=0,d4=0,m1=0,m3=0;
int gray_divide=0;
int edges=0;
int clears=0;
float m1sum=0,m3sum=0,gray_dividesum=0;
for(int r=3;r<mysize_.height-3;r+=10)
{
for(int c=3;c<mysize_.width-3;c+=10)
{
//angle :0
direction_s[0]=gradient_dimg.ptr<float>(r)[c]+gradient_dimg.ptr<float>(r)[c-1]+gradient_dimg.ptr<float>(r)[c-2]+
gradient_dimg.ptr<float>(r)[c+1]+gradient_dimg.ptr<float>(r)[c+2];
//angle:45
direction_s[1]=gradient_dimg.ptr<float>(r)[c]+gradient_dimg.ptr<float>(r-1)[c+1]+gradient_dimg.ptr<float>(r-2)[c+2]+
gradient_dimg.ptr<float>(r+1)[c-1]+gradient_dimg.ptr<float>(r+2)[c-2];
//angle:90
direction_s[2]=gradient_dimg.ptr<float>(r)[c]+gradient_dimg.ptr<float>(r-1)[c]+gradient_dimg.ptr<float>(r-2)[c]+
gradient_dimg.ptr<float>(r+1)[c]+gradient_dimg.ptr<float>(r+2)[c];
//angle:135
direction_s[3]=gradient_dimg.ptr<float>(r)[c]+gradient_dimg.ptr<float>(r-1)[c-1]+gradient_dimg.ptr<float>(r-2)[c-2]+
gradient_dimg.ptr<float>(r+1)[c+1]+gradient_dimg.ptr<float>(r+2)[c+2];
//最大梯度边缘 以及法向量方向
//angle 0
if(direction_s[0]>direction_s[1] && direction_s[0]>direction_s[2] && direction_s[0]>direction_s[3])
{
uchar gray_max=srcimg_gray_.ptr<uchar>(r-3)[c];
uchar gray_min=srcimg_gray_.ptr<uchar>(r-3)[c];
for(short num=1;num<7;num++)
{
uchar gray_current=srcimg_gray_.ptr<uchar>(r-3+num)[c];
if(gray_max<gray_current)
{
gray_max=gray_current;
}
if(gray_min>gray_current)
{
gray_min=gray_current;
}
}
gray_divide=int(gray_max-gray_min);
//if this is the true edge
if(gray_divide>gray_thresh)
{
++edges;
//judge if the true edge is clear or not...
d1=abs(srcimg_gray_.ptr<uchar>(r-1)[c]-srcimg_gray_.ptr<uchar>(r-2)[c]);
d2=abs(srcimg_gray_.ptr<uchar>(r)[c]-srcimg_gray_.ptr<uchar>(r-1)[c]);
d3=abs(srcimg_gray_.ptr<uchar>(r+1)[c]-srcimg_gray_.ptr<uchar>(r)[c]);
d4=abs(srcimg_gray_.ptr<uchar>(r+2)[c]-srcimg_gray_.ptr<uchar>(r+1)[c]);
m1=std::max(std::max(d1,d2),std::max(d3,d4))/2/gray_divide;
m3=std::max(d1+d2+d3,d2+d3+d4)/2/gray_divide;
if(m1>m1_thresh && m3>m3_thresh)
{
//it is clear
++clears;
}
}
}
//angle 90
if(direction_s[2]>direction_s[0] && direction_s[2]>direction_s[1] && direction_s[2]>direction_s[3])
{
uchar gray_max=srcimg_gray_.ptr<uchar>(r)[c-3];
uchar gray_min=srcimg_gray_.ptr<uchar>(r)[c-3];
for(short num=1;num<7;num++)
{
uchar gray_current=srcimg_gray_.ptr<uchar>(r)[c-3+num];
if(gray_max<gray_current)
{
gray_max=gray_current;
}
if(gray_min>gray_current)
{
gray_min=gray_current;
}
}
gray_divide=int(gray_max-gray_min);
//if this is the true edge
if(gray_divide>gray_thresh)
{
++edges;
//judge if the true edge is clear or not...
d1=abs(srcimg_gray_.ptr<uchar>(r)[c-1]-srcimg_gray_.ptr<uchar>(r)[c-2]);
d2=abs(srcimg_gray_.ptr<uchar>(r)[c]-srcimg_gray_.ptr<uchar>(r)[c-1]);
d3=abs(srcimg_gray_.ptr<uchar>(r)[c+1]-srcimg_gray_.ptr<uchar>(r)[c]);
d4=abs(srcimg_gray_.ptr<uchar>(r)[c+2]-srcimg_gray_.ptr<uchar>(r)[c+1]);
m1=std::max(std::max(d1,d2),std::max(d3,d4))/2/gray_divide;
m3=std::max(d1+d2+d3,d2+d3+d4)/2/gray_divide;
if(m1>m1_thresh && m3>m3_thresh)
{
//it is clear
++clears;
}
}
}
//angle 45
if(direction_s[1]>direction_s[0] && direction_s[1]>direction_s[2] && direction_s[1]>direction_s[3])
{
uchar gray_max=srcimg_gray_.ptr<uchar>(r-3)[c-3];
uchar gray_min=srcimg_gray_.ptr<uchar>(r-3)[c-3];
for(short num=1;num<7;num++)
{
uchar gray_current=srcimg_gray_.ptr<uchar>(r-3+num)[c-3+num];
if(gray_max<gray_current)
{
gray_max=gray_current;
}
if(gray_min>gray_current)
{
gray_min=gray_current;
}
}
gray_divide=int(gray_max-gray_min);
//if this is the true edge
if(gray_divide>gray_thresh)
{
++edges;
//judge if the true edge is clear or not...
d1=abs(srcimg_gray_.ptr<uchar>(r-1)[c-1]-srcimg_gray_.ptr<uchar>(r-2)[c-2]);
d2=abs(srcimg_gray_.ptr<uchar>(r)[c]-srcimg_gray_.ptr<uchar>(r-1)[c-1]);
d3=abs(srcimg_gray_.ptr<uchar>(r+1)[c+1]-srcimg_gray_.ptr<uchar>(r)[c]);
d4=abs(srcimg_gray_.ptr<uchar>(r+2)[c+2]-srcimg_gray_.ptr<uchar>(r+1)[c+1]);
m1=std::max(std::max(d1,d2),std::max(d3,d4))/2/gray_divide;
m3=std::max(d1+d2+d3,d2+d3+d4)/2/gray_divide;
if(m1>m1_thresh && m3>m3_thresh)
{
//it is clear
++clears;
}
}
}
//angle 135
if(direction_s[3]>direction_s[0] && direction_s[3]>direction_s[2] && direction_s[3]>direction_s[1])
{
uchar gray_max=srcimg_gray_.ptr<uchar>(r+3)[c-3];
uchar gray_min=srcimg_gray_.ptr<uchar>(r+3)[c-3];
for(short num=1;num<7;num++)
{
uchar gray_current=srcimg_gray_.ptr<uchar>(r+3-num)[c-3+num];
if(gray_max<gray_current)
{
gray_max=gray_current;
}
if(gray_min>gray_current)
{
gray_min=gray_current;
}
}
gray_divide=int(gray_max-gray_min);
//if this is the true edge
if(gray_divide>gray_thresh)
{
++edges;
//judge if the true edge is clear or not...
d1=abs(srcimg_gray_.ptr<uchar>(r+1)[c-1]-srcimg_gray_.ptr<uchar>(r+2)[c-2]);
d2=abs(srcimg_gray_.ptr<uchar>(r)[c]-srcimg_gray_.ptr<uchar>(r+1)[c-1]);
d3=abs(srcimg_gray_.ptr<uchar>(r-1)[c+1]-srcimg_gray_.ptr<uchar>(r)[c]);
d4=abs(srcimg_gray_.ptr<uchar>(r-2)[c+2]-srcimg_gray_.ptr<uchar>(r-1)[c+1]);
m1=std::max(std::max(d1,d2),std::max(d3,d4))/2/gray_divide;
m3=std::max(d1+d2+d3,d2+d3+d4)/2/gray_divide;
if(m1>m1_thresh && m3>m3_thresh)
{
//it is clear
++clears;
}
}
}
m1sum+=m1;
}
}
float average_m1=m1sum/edges;
float clear_ratio=float(clears)/edges;
standard_value[0]=clear_ratio;
standard_value[1]=average_m1;
return 0;
}
int AutoFocus::judgeMaxLaplace(bool down_up)
{
float maxLaplace,sec_max;
int max_ind,sec_ind;
if(imgs_clear_one_view_[0]>=imgs_clear_one_view_[1])
{
maxLaplace=imgs_clear_one_view_[0];
max_ind=0;
sec_max=imgs_clear_one_view_[1];
sec_ind=1;
}
else
{
maxLaplace=imgs_clear_one_view_[1];
max_ind=1;
sec_max=imgs_clear_one_view_[0];
sec_ind=0;
}
bool useless_max=false;
for (int j = 2; j != cImgsNumber1View_; j++)
{
if (imgs_clear_one_view_[j] > maxLaplace)
{
if(useless_max==true)
{
sec_max=maxLaplace;
sec_ind=max_ind;
}
maxLaplace = imgs_clear_one_view_[j];
max_ind = j;
useless_max=true;
}
if (imgs_clear_one_view_[j] > sec_max && imgs_clear_one_view_[j]<maxLaplace)
{
sec_max = imgs_clear_one_view_[j];
sec_ind = j;
}
}
if(imgs_m1_one_view_[max_ind]<imgs_m1_one_view_[sec_ind])
{
return sec_ind;
}
else
{
return max_ind;
}
}
目前测了大概一千多组图,效果还行。像这种复杂的也还行。
但随着测试复杂程度增加,估计会出现找不准的情况,还要改善,让其更具有鲁棒性。或者要换一种更加好的算法?!