算法
图像清晰度参考 https://blog.youkuaiyun.com/dcrmg/article/details/53543341
在实际应用中,清晰度随着对焦点的移动,呈以下图像的趋势。说白了就是有一个波峰,我们进行对焦的时候会经过这个波峰,那怎么知道这个波峰在哪呢?
步骤
1、首先我们一开始是不知道图像是否在对焦点的,因为清晰度这玩意儿,变化非常大,分辨率,亮度等都会影响,所以是没办法定一个死的峰值来判断,这就需要我们随机往一个方向进行对焦(这里我用的是垂直电机对焦)。
2、第二张图你就会知道,清晰度是增加了,还是减少了,就可以知道我们应该往哪个方向进行对焦。当然这一步也有可能因为步幅太大,直接越过波峰和同等清晰度的点,但是实际应用中这种情况比较少见,因为我们可以手动修改步幅,尽可能避免这种情况。
3、知道方向之后我们一直运动清晰度是一直增加的,跑到越过波峰的时候,我们的清晰度会比前一次的低。这时候我们可以判断我们越过了波峰。
4‘、这时候我们可以往反方向进行小步幅进行精对焦,知道第二次越过波峰(这里我们可以进行第三次更小步幅对焦,但是清晰度这东西很玄学,这么小的步幅很有可能会出现清晰度理应增加的方向,清晰度降低了,自行判断即可,实际应用中两轮就可以了,如果是合适的步幅运动一轮也已经可以达到不错的效果)。
注意:不能用全图进行对焦,所以ROI很重要。
代码
public void AutoFocus()
{
label:
List<double> focusL = new List<double>();
int Round=2;
int T=1;
while (true)
{
//获取当前清晰度
Bitmap currentBmp=GetImage(); //这里是获取相机的图片,每个人都有自己的方法,这里不详说,懂意思就行
Rectangle Roi=new Rectangle(); //需要对焦的区域
double currentArticulation = GetArticulation(currentBmp,roi); //这里参考上面的连接,
focusL.Add(currentArticulation);
if (focusL.Count == 1) //这里是第一次运动
{
RunPulse(pulse); //对焦的运动方法,自己换成自己的
continue;
}
//前两张确认调焦方向
if (focusL.Count == 2)
{
if (currentArticulation > focusL[focusL.Count - 2]) //判断是否跑对方向
{
pulse *= 1; //对的方向
RunPulse(pulse);
}
else
{
pulse *= -1; //不对的方向我们相反就可以了
RunPulse(pulse*1.5); //这里不是跑回原来的位置,而是更过去一些,节约时间
}
continue;
}
//清晰度大于前一张图
if (currentArticulation > focusL[focusL.Count - 2])
{
RunPulse(pulse);
}
else
{
返回峰值,跳出循环
if(T==Round)
{
break; //两轮结束了,跳出循环
}
goto label;
}
}
}
后记
这里只提供思路。用什么语言都无所谓的。我这用的是C井