采用 TinyML 和 OpenMV 实现机器视觉 - 第 1 部分

机器学习和 tinyML 可以为嵌入式系统工程师解决许多应用问题。有一个很难从头开始编码的独特问题,那就是图像中物体的检测和识别。恰好,物体的检测和识别是 tinyML 的一个完美应用。然而,启动 tinyML 和机器视觉 (MV) 项目可能会很复杂。在接下来的几篇文章中,我们将探讨如何使用 OpenMV 摄像头启动 MV。

介绍 OpenMV Cam H7

假设你对使用微控制器的低功率应用 MV 感兴趣。在这种情况下,你要么定制设计摄像头模块,要么找一个市面上有售的摄像头模块。从头创建模块会很有趣,但费钱、耗时。一个有趣的市售解决方案是 OpenMV Cam。

OpenMV Cam 是一款类似 Arduino 的小型开发板,包括开发者实现 MV 入门所需的一切。首先,必须明白硬件是有不同版本的。最新版本是 OpenMV Cam H7(图 1)。Cam H7 基于 STMicroelectronics STM32H743VI 的微控制器,采用 Arm Cortex-M7 架构,时钟速度为 480 MHz。该零件还具有 1 MB SRAM 和 2 MB 闪存。在使用 MV 和学习应用工作时,有大量的内存可用总是一件好事。Cam H7 使用 MT9M114 摄像头模块,可以每秒 40 帧 (fps) 的速度捕捉 640 x 320 8 位灰度图像,或以 40 - 80 fps 的速度捕捉 320 x 240 QVGA 图像。可以根据应用需求改变摄像头模块。

图 1:OpenMV Cam H7 模块拥有开始 MV 设计所需的一切。(图片来源:OpenMV)

OpenMV 的开发环境

OpenMV 集成开发环境 (IDE) 如图 2 所示,是开发者与 Cam H7 的互动途径。有了 IDE,开发者能够对将在模块上运行的 Python 脚本进行编辑。Cam H7 使用 MicroPython,这是一个专门用于在基于微控制器的系统上运行的 C Python 端口。开发人员可以连接 Cam H7,将脚本加载到设备上并运行应用。集成开发环境也可用于获取 Cam H7 帧缓冲器图像的实时反馈。

图 2:OpenMV 的开发环境包括开发者对 Cam H7 进行编程并与之互动所需的一切,如文本编辑器、终端和图像捕捉显示窗口。(图片来源:OpenMV)

对于那些希望使用该模块实现机器视觉并最终进行机器学习的开发者,不需要看得很远。OpenMV 集成开发环境包含的示例脚本涵盖从将系统置于低功耗模式,到物体和人脸检测等示例脚本。还有将模块与诸如 Wi-Fi、惯性测量装置 (IMU) 等外部开发板连接的示例,以及其他选项。

检测图像中的一个圆

OpenMV IDE 包括一个 HelloWorld 脚本,允许开发人员连接摄像头并拍摄图片,为帧缓冲器提供信息。在这篇文章中,用具体的示例讲解更能激发我们的兴趣。在本示例中,可以检测图像中的一些东西,比如圆。

如果你打开 OpenMV IDE,点击 File->Examples->Feature-Detection->find_circles.py(见图 3),就会出现用于检测圆的脚本。测试这个脚本超级简单;首先,我们需要准备一张纸或一张便条,画一个圆(请不要评价我的绘画能力,会惊掉你的下巴!)。接下来,在 IDE 左下方,你会发现一个连接按钮。点击该按钮,连接 Cam H7。然后,点击连接按钮下房的绿色播放按钮。最后,将 Cam H7 对准你画的圆圈,并在 OpenMV IDE 中监视帧缓冲区。

图 3:在 OpenMV IDE 中导航至 find_circles.py 示例脚本。(图片来源:Beningo Embedded Group)

你将看到,在帧缓冲器中会周期性地画出一个红色的圆,与你画的圆重叠,如图 4 所示。请注意,尽管我的绘画能力有待提高,但 Cam H7 仍然能够检测到所拍摄的图像中有一个类似圆的图形。在这个系列博客文章中,这是我们第一次检测圆圈,但不是最后一次!让我们看一下示例脚本,了解其工作原理。

图 4:find_circles.py 示例脚本将在帧缓冲区添加一个红色的圆,并在检测到圆时突出显示。(图片来源:Beningo Embedded Group)

分析 find_circles.py 示例

OpenMV IDE 提供的圆检测脚本直截明了。首先,该脚本导入所需的 Python 库,并初始化摄像头传感器和时钟,如列表 1 所示。

副本import sensor, image, time

sensor.reset()
sensor.set_pixformat(sensor.RGB565) # grayscale is faster
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
clock = time.clock()

列表 1:摄像头传感器的初始化示例代码。(代码来源:OpenMV)

接下来,一个无限循环会持续运行该应用,就像在任何标准嵌入式应用中一样。然后,也是最后,就是促使检测进行的魔法。我们花点时间来研究列表 2。

副本while(True):
  clock.tick()
  img = sensor.snapshot().lens_corr(1.8)

  for c in img.find_circles(threshold = 2000, x_margin = 10, y_margin = 10, r_margin = 10,
      r_min = 2, r_max = 100, r_step = 2):
    img.draw_circle(c.x(), c.y(), c.r(), color = (255, 0, 0))
    print(c)

  print("FPS %f" % clock.fps())

列表 2:读取摄像头传感器并搜索图像中的圆代码示例。(代码来源:OpenMV)

列表 2 中的代码从截取图像开始。然后,使用 OpenMV 库中一种名为 find_circles 的方法搜索图像中的圆。你可以阅读实际源代码例子中的注释,了解参数细节,但我们最感兴趣的是 r_min、r_max 和 r_step 参数。r_min 参数指定可以检测的圆的最小半径。r_max 参数设定圆的最大半径值。在此例子中,程序将看到 2 到 100 像素之间的圆。

检测到圆时,draw_circle 方法以及圆的 x、y 和半径值被用来在检测到的圆上画一个圆。你会注意到,颜色是用 R、G 和 B 符号指定的,在此例中,所画的圆为红色。

总结

开发者可以使用机器视觉和 TinyML,并应用于几乎无限的用例。在这篇博客中,我们只是介绍了 OpenMV Cam H7 和 OpenMV IDE,让你开始运行,检测圆。不过,检测圆并不需要 tinyML,只需要一些库函数。在下一篇博客中,我们将探索内置的机器学习示例,然后再引入一个更复杂的示例,然后以此为例训练、部署我们的检测项目。

关于此作者

Image of Jacob Beningo

Jacob Beningo 是一位嵌入式软件顾问,目前与十几个国家的客户保持合作,通过帮助客户改善产品质量、降低成本和加快上市时间来大幅改变他们的业务。Jacob 先后发表了 200 多篇关于嵌入式软件开发技术的文章,是一位广受欢迎的演讲者和技术培训师。他拥有三个学位,其中包括密歇根大学的工程硕士学位。如有需要,欢迎随时通过 jacob@beningo.com 与其联系,也可访问其网站 www.beningo.com,并订阅其月度 Embedded Bytes Newsletter

More posts by Jacob Beningo
 TechForum

Have questions or comments? Continue the conversation on TechForum, Digi-Key's online community and technical resource.

Visit TechForum