若干年前做的自动聚焦算法,现在的产品一直在使用, 效果还行,后来其他项目的原因,也没有再改进过,但 个人觉得有改进的空间,这里依靠之前的笔记,做一个记录。

图像清晰度评估

聚焦即把镜头焦距聚到正确的距离上,使图像的画面清晰不虚。所以算法需要知道图像清晰度的估算值, 根据这个值,通过改变镜头电机的位置,比对清晰度,才能找到最清晰的位置。 实际上,网上有很多清晰度评估算法,在我们的产品SDK中,已经有现成的,通过DSP计算得到的图像清晰度评估值,所以就不再使用CPU软件算法实现。

无论用什么方法计算,图像清晰度值曲线是一个具有单峰特性的曲线,也就是说,当该值是峰值时,图像是最清晰的。

自动聚焦

自动对焦就是控制电机,找到这个峰值所在的位置。算法好坏决定了对焦准确度和速度。 网上的算法论文很多,比较经典的是爬山算法,我这个也是基于这个算法,针对电机特性做了一些修改。

对焦速度:

最早的版本是拉到头,然后再往回拉,判断峰值,这样速度就很慢;改进版本先往一个方向拉,然后判断值,如果发现数据变小了,则反向,直到找到峰值,这样就加快了对焦速度。

对焦准确度:

爬山算法大意是先以大步距控制电机,快速找到峰值,找到峰值后,下一次的总步数范围应在该峰值的上一站和下一个站之间;然后以小步距走,再次寻找峰值,同样按上述设置下一次走的总部数,逐渐逼近山峰,直到步距为最小步距时,所寻找到的峰值为最清晰的一个点。

优化

速度

从大步距迭代到小步距,频繁的来回通过峰值,会造成过多的图像从”模糊”->“清晰”,造成感觉不适。所以在一开始的时候,可以通过小步距判断下降或者上升的斜率,确定当前的大概位置,然后智能选用不同的步距向峰值靠近,加快对焦速度。

峰值判断,如何判断峰值,如何抗干扰

网络上有个论文,判断峰值用数据连续下降2次的方法,一般是可行的. 但是在晚上图像噪声干扰或者有运动物体干扰时,该峰值就有可能不是真正的峰值了。个人觉得比较可行的是,数据连续2次下降一定范围。

电机步距,上一站和下一站的取值

这个要根据电机特性进行尝试,取的好的话,事半功倍。 由于目前手头的电机不是太理想,怕有失步和越步(没有用电机控制芯片,直接CPU控制电机相位),所以站取值范围大一点,目前对焦一般在1.2s以内,电机可靠的话,相信可以做到0.7s以内。

目前的问题

尽管在大部分场景下工作还挺可靠,速度也还凑活。但是还是有些问题还没解决的:

抗干扰

图像清晰度评估值是针对同样的场景,不同的聚焦距离得到的数值曲线。如果场景发生了改变,即图像内容发生变化,此评估值和改变前评估值是没有比较意义的,因为这里有了2个变量,一个是聚焦本身的变量,另一个就是场景的变量了。有个简单的方法,就是如果图像有发生改变,则重新启动聚焦算法。但是由于项目的原因,也没有再深入解决这个问题了。