• 正文
  • 相关推荐
申请入驻 产业图谱

智能相机自动对焦功能的工作原理与代码

08/26 09:40
1247
加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论

介绍

虽然相机作为捕捉图像的工具已经存在了 150 多年,但智能手机的出现极大地改变了相机的用途,并将其与软件编程集成在一起。如今,相机不再完成“简单”的任务,例如拍摄静态照片或拍摄视频,它们实际上复制了人眼执行的大部分复杂任务。

事实上,计算机视觉中使用的大多数算法和公式都是基于人眼的感知。例如,对 RGB 图像进行灰度化,即通过对 R、B、G 像素值进行平均,将图像的通道减少到 1 个通道,计算公式如下:Gray ← 0.299?R+0.587?G+0.114 ?B。注意:这显然与对R、G、B像素值进行平均不同,如公式所示:Gray←0.33?R+0.33?G+0.33?B。

但为什么?其原因是因为与色度相比,我们的眼睛对亮度/明度更敏感。对图像进行灰度化时使用的实际公式与计算给定像素处的亮度/明度值相同。注意:明度值是 YUV 和 YCrCb 颜色空间中的 Y 值 。

自动对焦是相机的一个有趣的功能。它实际上可以复制我们眼睛的聚焦能力。为了更好地可视化,请在不同平面上描绘两个物体(水瓶和插座),如左图所示。现在将目光集中在水瓶上。不知不觉中你的眼睛模糊了后面的墙壁插座。对墙壁插座重复同样的操作,我们的眼睛会自动模糊水瓶。现在在家中复制类似的设置并打开手机的相机应用程序。通过点击您想要聚焦的区域,相机会自动模糊其他物体,就像我们的眼睛一样。这就是相机自动对焦的神奇之处。如今,相机使用多种算法来聚焦图像。我将重点介绍一种基本的自动对焦算法:基于对比度的自动对焦。

基于对比度的自动对焦如何在高水平上发挥作用?

基于对比度的自动对焦基本上测量不同相机镜头位置的对比度。相机镜头将继续移动,直到达到其定义的具有最大对比度的点。我们可以将对比度定义为图像的清晰度程度。为了更好地可视化,这里是不同相机镜头位置的虚拟图像(比较黑色方块的边缘):

图2

为了概括对比度,我们可以为每个图像分配 0 到 1 之间的任意对比度值,其中 0 指未聚焦/低对比度图像,1 指聚焦/高对比度图像。

图3

现在,相机循环遍历不同的相机镜头位置,计算图像内的对比度,然后比较并选择具有最高对比度值的相机镜头位置。

我们如何定义对比度?

有许多不同的方法来定义对比度。事实上,算法的复杂度是根据定义对比度的方法来确定的。今天我将介绍一种非常基本的方法,它不需要传感器等额外的硬件。请注意,公司通常会利用手机内置的额外硬件组件来提高算法的复杂性。

为图像分配对比度值的一种基本方法是Canny 边缘检测。事实上,这就是 OpenCV 计算自动对焦的最佳相机镜头位置的方式。对于每个镜头位置,我们绘制图像的边缘并根据边缘的清晰度分配对比度值。例如,以下图像序列显示了执行 Canny 边缘检测算法后的输出:

图4

正如您所看到的,图像的聚焦度越低,边缘就越不清晰。事实上,在为 Canny 边缘检测算法设置默认设置后,您会注意到它无法检测左侧两个逐渐失焦的图像的边缘。显然,通过降低算法的最小阈值,我们将能够看到边缘。但为了自动对焦,我们可以丢弃没有检测到边缘的相机镜头位置。

如果您想进一步探索 OpenCV 的自动对焦算法,请查看他们的代码:源代码链接。

https://github.com/opencv/opencv/blob/master/samples/cpp/autofocus.cpp

结论

基于对比度的自动对焦算法需要许多计算 -> L * O(对比度),其中 L 是可能的相机镜头位置的数量,O(对比度)是用于确定图像内对比度的算法的复杂性。在上面的示例中,确定边缘是否锐利的复杂性将需要超过 O(m*n),其中 m 和 n 是帧的尺寸。由于这种高度复杂性,许多创建相机驱动程序的公司(高通、苹果等)都在研究新的、更有效的方法来确定图像是否聚焦。其他一些常见的算法包括 PDAF、激光等。事实上,作为一个附带实验,您可以通过比较苹果和三星手机(三星手机使用高通芯片组)。

延伸

作为扩展,我决定使用基于机器学习的方法来定义对比度。由于计算每一帧的边缘计算量很大,因此我决定设计一个神经网络,以降低基于对比度的自动对焦算法的复杂性。

由于我对机器学习的理论知识有限,因此我决定尝试前馈神经网络和卷积神经网络

我首先尝试使用前馈神经网络,因为这更容易实现。我创建了一个 4 层的小型神经网络。在此神经网络中,我为大小为 224 x 224 像素的 3 通道图像添加了一个输入层。然后我继续将维度展平为单一维度,并添加了 1024 个神经元的隐藏层。我决定添加另一个包含 128 个神经元的隐藏层,而不是直接跳到最后一层。最后,我完成了具有 2 个神经元输出层的神经网络,以指示聚焦或未聚焦。

在我开始训练这个前馈神经网络后,我发现模型的验证准确性和损失在每个时期都不再提高。

这促使我尝试使用卷积神经网络 (CNN),因为它们似乎可以为目标检测提供更好的结果。Keras有许多预训练的 CNN 模型,我选择针对给定的问题微调vgg16模型。我采用了 vgg16 模型的 5 个卷积块,然后添加了全局平均池化层,将维度减少到 1,同时也有效减少了可训练参数的数量。最后,我添加了 2 个神经元的输出层来表示聚焦或不聚焦的置信度。

与前馈神经网络相比,该模型的准确性要好得多,我完成了 25 个 epoch,验证准确性为 0.76,验证损失为 0.49。虽然这些数字并不是很好,但我认为这些数字反映了训练数据的缺乏。我只使用了 1400 张训练图像,并且感觉如果将其增加到大约 6000-7000 张图像,我的准确性将会显着提高。我在图 2 所示的 6 个图像上测试了我的模型。该模型正确地将每个图像标记为聚焦或未聚焦。有关更多信息,请通过此GitHub 链接查看源代码。

https://github.com/sedara0218/camera_autofocus

—THE END—

相关推荐