对于与UVC兼容的USB 网络摄像头(与大多数兼容),有一个合理的机会可以使用相机的自动对焦然后将其锁定。为了弄清楚照相机是否允许此通过UVC,在Linux可以使用v4l2-ctl,这是在包装v4l-utils。 v4l2-ctl -l列出所有可用的控件,v4l2-ctl -c设置控件的值并v4l2-ctl -C获取该值。
例如,以下命令在运行一个简单的 Python OpenCV 程序以显示当前帧的 Ubuntu 16.04 机器上为 Microsoft LifeCam Cinema 提供了技巧:
> v4l2-ctl -d 0 -c focus_auto=1
> v4l2-ctl -d 0 -C focus_absolute
focus_absolute: 12
Run Code Online (Sandbox Code Playgroud)
将物体移近相机后,焦点发生了变化,我得到了不同的值focus_absolute:(因此 UVC 可以访问自动对焦选择的值。)
> v4l2-ctl -d 0 -C focus_absolute
focus_absolute: 17
Run Code Online (Sandbox Code Playgroud)
然后我改为手动对焦,这锁定了自动对焦选择的值:
> v4l2-ctl -d 0 -c focus_auto=0
> v4l2-ctl -d 0 -C focus_absolute
focus_absolute: 17
Run Code Online (Sandbox Code Playgroud)
因此,对于 LifeCam Cinema,代码唯一需要做的就是将focus_auto控件最初更改为自动 ( 1),然后在锁定焦点后更改为手动。
在 Python 中,我通常v4l2-ctl只需使用subprocess.check_output(). 我记得看到过用于 UVC 的 Windows 库,但从未使用过它们。
您可以在校准阶段(当您找到最佳焦点时)检测图像何时聚焦并保存该配置(焦距)。然后将焦点设置为保存的值并在捕获阶段之前禁用自动对焦。要找到最佳焦距,您可以从最近(微距)焦距开始,然后逐渐将其提高到最大,测量图像的聚焦程度。
This SO question有一个答案,描述了如何测量图像是否聚焦。您可以使用OpenCV Laplacian() ( Emgu.CV ) 来实现这一点。
关键是对焦图像具有更强的梯度和清晰的特征。所以我的建议是应用高斯拉普拉斯滤波器,然后查看结果的像素值分布。对焦的具有更高的值(因为图像具有更锐利的梯度)。
本文描述了另一种确定最佳焦点的有趣方法。该技术用于 NASA 好奇号火星探测器。这个想法是对帧进行 JPEG 压缩并使用 jpeg 的大小作为焦点的度量。
自动对焦命令指示相机移动到指定的起始电机计数位置并收集图像,移动指定的步数并收集另一张图像,并继续这样做直到达到命令的图像总数,每个图像由指定的电机分隔计数增量。这些图像中的每一个都经过 JPEG 压缩(联合图像专家组;参见 CCITT (1993))并应用相同的压缩质量因子。每个压缩图像的文件大小是对场景细节的衡量,而后者又是焦点的函数(与同一场景的模糊、失焦视图相比,对焦图像显示更多细节)。
OpenCV imencode() ( Emgu.CV ) 可用于压缩 JPEG 格式的图像。
如果您想聚焦于某个特定的稳定物体或区域并且您能够计算/识别其固定位置,您应该只处理该区域以确定最佳聚焦。在第一种方法中,Laplacian如果您知道对象的形状,您可以应用于裁剪的矩形区域,甚至可以使用非矩形蒙版进行结果“焦点值”计算。第二种方法也是如此 - 仅压缩您想要关注的感兴趣区域。如果您希望它处理非矩形区域并知道该区域的形状,请首先将所有未覆盖您关注的区域的像素设置为相同的颜色。这将使算法不考虑您不需要关注的区域。