目录

  • 一、OpenMV是什么
  • 二、OpenART mini与OpenMV对比
  • 三、图像处理背景知识
    • 1.像素和分辨率
    • 2. 帧率
    • 3.RGB三原色
    • 4.LAB颜色空间
  • 四、OpenMV图像处理方法
    • 1.感光元件
      • 自动增益/白平衡/曝光
      • 窗口ROI
    • 2.画图
      • 画线
      • 画框
      • 画圆
      • 画十字
      • 写字
      • 示例
    • 3. 寻找色块(颜色识别)
      • find_blobs()函数
      • find_blobs()返回值
      • 示例
    • 4. 测距
  • 四、串口通道
  • 五、条形码、矩形码、二维码
    • 1.条形码
    • 2.矩形码
    • 3.二维码

一、OpenMV是什么

  OpenMV是一款具有图像处理功能的可编程摄像头模块,可以实现简单的机器视觉应用,例如人脸检测、Apriltag追踪、圆形检测、矩形检测等。

二、OpenART mini与OpenMV对比

  (这里介绍另一款可编程摄像头模块OpenART mini,在功能上与OpenMV几乎无差别,但性能和价格都优于OpenMV)
  OpenART mini是逐飞科技恩智浦的OpenART套件的基础上,去除非视觉部分而制作出来的迷你版。虽说只是迷你版,但“麻雀虽小,五脏俱全”。OpenART mini 不仅可以很轻松的完成机器视觉应用,还可以完成神经网络模型的部署。

比较项目 OpenMV4 H7 Plus OpenART mini
价格 599 380
处理器 STM32H743II MIMXRT1064
主频 480MHz 600MHz
RAM 1M 1M
FLASH 2M 4M
编程环境 Micropython Micropython
OpenMV视觉库

三、图像处理背景知识

1.像素和分辨率

  • 像素:像素是数字图像中的最小单元

  • 分辨率:分辨率指单位长度内像素点的数量,常用的度量为ppi(pixels per inch),即每英寸有多少像素点。

  感光元件是由很多个感光点构成的,比如有 640 × 480 640×480 640×480个点,每个点就是一个像素,把每个点的像素收集整理起来,就是一副图片,那么这张图片的分辨率就是 640 × 480 640×480 640×480:

2. 帧率

  帧率(FPS,Frames Per Second)就是每秒钟处理的图片数量,如果超过20帧,人眼就基本分辨不出卡顿。电影的帧率一般是24FPS,游戏的帧率一般都大于30FPS。

3.RGB三原色

  RGB指的是红绿蓝三种颜色,是光学三原色,所有的颜色都可以由这三种色彩混合而成。(三原色是依据人类视觉定义的,不存在绝对的三原色)

4.LAB颜色空间

  Lab是由一个亮度通道和两个颜色通道组成的。在Lab颜色空间中,每个颜色用L、a、b三个数字表示,各个分量的含义是这样的:

  • L 代表亮度
  • a 代表从绿色到红色的分量
  • b 代表从蓝色到黄色的分量

  Lab是基于人对颜色的感觉来设计的,更具体地说,它是感知均匀(perceptual uniform)的。Perceptual uniform的意思是,如果数字(即前面提到的L、a、b这三个数)变化的幅度一样,那么它给人带来视觉上的变化幅度也差不多。

  Lab相较于RGB与CMYK等颜色空间更符合人类视觉,也更容易调整:想要调节亮度就调节L通道,想要调节色彩平衡就分别调ab

四、OpenMV图像处理方法

1.感光元件

  OpenMV中使用sensor模块来设置感光元件的参数,具体使用方法如下:

import sensor#引入感光元件的模块# 设置摄像头
sensor.reset()#初始化感光元件
sensor.set_pixformat(sensor.RGB565)#设置为彩色
sensor.set_framesize(sensor.QVGA)#设置图像的大小
sensor.skip_frames()#跳过n张照片,在更改设置后,跳过一些帧,等待感光元件变稳定。# 一直拍照
while(True):img = sensor.snapshot()#拍摄一张照片,img为一个image对象

自动增益/白平衡/曝光

  • sensor.set_auto_gain()
    自动增益开启(True)或者关闭(False)。在使用颜色追踪时,需要关闭自动增益。
  • sensor.set_auto_whitebal()
    自动白平衡开启(True)或者关闭(False)。在使用颜色追踪时,需要关闭自动白平衡。
  • sensor.set_auto_exposure(enable[, exposure_us])
    • enable 打开(True)或关闭(False)自动曝光。默认打开。
    • 如果 enable 为 False,则可以用 exposure_us 设置一个固定的曝光时间(以微秒为单位)。

窗口ROI

  ROI:Region Of Interest,图像处理中的术语“感兴趣区”。就是在要处理的图像中提取出的要处理的区域。

  • sensor.set_windowing(roi)
    roi的格式是(x, y, w, h)

    • x:ROI区域中左上角的x坐标
    • y:ROI区域中左上角的y坐标
    • w:ROI的宽度
    • h:ROI的高度

2.画图

  视觉系统通常需要给使用者提供一些反馈信息。直接在图像中显示出来,很直观。

画线

  • image.draw_line(line_tuple, color=White)
    在图像中画一条直线。

    • line_tuple的格式是(x0, y0, x1, y1),意思是(x0, y0)到(x1, y1)的直线。
    • 颜色可以是灰度值(0-255),或者是彩色值(r, g, b)的tupple。默认是白色

画框

  • image.draw_rectangle(rect_tuple, color=White)
    在图像中画一个矩形框。

    • rect_tuple 的格式是 (x, y, w, h)。

画圆

  • image.draw_circle(x, y, radius, color=White)
    在图像中画一个圆。

    • x,y是圆心坐标
    • radius是圆的半径

画十字

  • image.draw_cross(x, y, size=5, color=White)
    在图像中画一个十字

    • x,y是坐标
    • size是两侧的尺寸

写字

  • image.draw_string(x, y, text, color=White)
    在图像中写字 8x10的像素

    • x,y是坐标。
    • text是要写的字符串。

示例

# Hello World Example
#
# Welcome to the OpenMV IDE! Click on the green run arrow button below to run the script!import sensor, image, timesensor.reset() # 初始化摄像头
sensor.set_pixformat(sensor.RGB565) # 格式为 RGB565.
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(10) # 跳过10帧,使新设置生效
while(True):img = sensor.snapshot()         # Take a picture and return the image.img.draw_line((20, 30, 40, 50))img.draw_line((80, 50, 100, 100), color=(255,0,0))img.draw_rectangle((20, 30, 41, 51), color=(255,0,0))img.draw_circle(50, 50, 30)img.draw_cross(90,60,size=10)img.draw_string(10,10, "hello world!")

3. 寻找色块(颜色识别)

  OpenMV通过find_blobs()函数可以找到色块(带颜色的物体),返回色块的位置、高度、像素等信息。

find_blobs()函数

  • image.find_blobs(thresholds, roi=Auto, x_stride=2, y_stride=1, invert=False, area_threshold=10, pixels_threshold=10, merge=False, margin=0, threshold_cb=None, merge_cb=None)

    • thresholds是颜色的阈值,在返回的色块对象blob可以调用code方法,来判断是什么颜色的色块。
    • x_stride(查找的色块的x方向上最小宽度的像素,默认为2)
    • y_stride(查找的色块的y方向上最小宽度的像素,默认为1)
    • invert(反转阈值,把阈值以外的颜色作为阈值进行查找)
    • area_threshold(面积阈值,如果色块被框起来的面积小于这个值,会被过滤掉)
    • pixels_threshold(像素个数阈值,如果色块像素数量小于这个值,会被过滤掉)
    • merge(合并,如果设置为True,那么合并所有重叠的blob为一个)
      注意:这会合并所有的blob,无论是什么颜色的。如果你想混淆多种颜色的blob,只需要分别调用不同颜色阈值的find_blobs。
    • margin(边界,如果设置为1,那么两个blobs如果间距1一个像素点,也会被合并)

find_blobs()返回值

  • for blob in img.find_blobs(thresholds):

    • blob.rect() 返回这个色块的外框——矩形元组(x, y, w, h)
    • blob.x() 返回色块的外框的x坐标(int)
    • blob.y() 返回色块的外框的y坐标(int)
    • blob.w() 返回色块的外框的宽度w(int)
    • blob.h() 返回色块的外框的高度h(int)
    • blob.pixels() 返回色块的像素数量(int)
    • blob.cx() 返回色块的外框的中心x坐标(int)
    • blob.cy() 返回色块的外框的中心y坐标(int)
    • blob.rotation() 返回色块的旋转角度(单位为弧度)(float)
    • blob.code() 返回一个16bit数字,每一个bit会对应每一个阈值
    • blob.count() 如果merge=True,那么就会有多个blob被合并到一个blob,这个函数返回的就是这个的数量
    • blob.area() 返回色块的外框的面积
    • blob.density() 返回色块的密度

示例

# Single Color RGB565 Blob Tracking Example
#
# This example shows off single color RGB565 tracking using the OpenMV Cam.import sensor, image, time, maththreshold_index = 0 # 0 for red, 1 for green, 2 for blue# Color Tracking Thresholds (L Min, L Max, A Min, A Max, B Min, B Max)
# The below thresholds track in general red/green/blue things. You may wish to tune them...
thresholds = [(30, 100, 15, 127, 15, 127), # generic_red_thresholds(30, 100, -64, -8, -32, 32), # generic_green_thresholds(0, 30, 0, 64, -128, 0)] # generic_blue_thresholdssensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False) # must be turned off for color tracking
sensor.set_auto_whitebal(False) # must be turned off for color tracking
clock = time.clock()# Only blobs that with more pixels than "pixel_threshold" and more area than "area_threshold" are
# returned by "find_blobs" below. Change "pixels_threshold" and "area_threshold" if you change the
# camera resolution. "merge=True" merges all overlapping blobs in the image.while(True):clock.tick()img = sensor.snapshot()for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):# These values depend on the blob not being circular - otherwise they will be shaky.if blob.elongation() > 0.5:img.draw_edges(blob.min_corners(), color=(255,0,0))img.draw_line(blob.major_axis_line(), color=(0,255,0))img.draw_line(blob.minor_axis_line(), color=(0,0,255))# These values are stable all the time.img.draw_rectangle(blob.rect())img.draw_cross(blob.cx(), blob.cy())# Note - the blob rotation is unique to 0-180 only.img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)print(clock.fps())

4. 测距

  OpenMV采用的是单目摄像头,想要实现测距,就需要选参照物,利用参照物的大小比例来计算距离。

# Measure the distance
#
# This example shows off how to measure the distance through the size in imgage
# This example in particular looks for yellow pingpong ball.import sensor, image, time# For color tracking to work really well you should ideally be in a very, very,
# very, controlled enviroment where the lighting is constant...
yellow_threshold   = ( 56,   83,    5,   57,   63,   80)
# You may need to tweak the above settings for tracking green things...
# Select an area in the Framebuffer to copy the color settings.sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.RGB565) # use RGB565.
sensor.set_framesize(sensor.QQVGA) # use QQVGA for speed.
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # turn this off.
clock = time.clock() # Tracks FPS.K=5000#the value should be measuredwhile(True):clock.tick() # Track elapsed milliseconds between snapshots().img = sensor.snapshot() # Take a picture and return the image.blobs = img.find_blobs([yellow_threshold])if len(blobs) == 1:# Draw a rect around the blob.b = blobs[0]img.draw_rectangle(b[0:4]) # rectimg.draw_cross(b[5], b[6]) # cx, cyLm = (b[2]+b[3])/2length = K/Lmprint(length)#print(clock.fps()) # Note: Your OpenMV Cam runs about half as fast while# connected to your computer. The FPS should increase once disconnected.

四、串口通道

  在项目中,OpenMV通常只用来处理图像数据,而处理结果要传到MCU中做下一步处理。这个过程中需要用到串口来传送数据。

from machine import UART
uart = UART(1, baudrate=115200)     # 初始化串口 波特率设置为115200 TX是B12 RX是B13
uart.write("uart test\r\n")         # 发送字符串
uart_num = 0                        # 定义一个变量
uart_array = [48,49,50,51,52,53,54,55,56,57]  # 定义一个列表 保存数字
uart.write(bytearray(uart_array))   # 发送列表
uart.write(bytearray([0x41]))       # 发送一个十六进制数据
while(True):uart_num = uart.any()       # 获取当前串口数据数量if(uart_num):uart_str = uart.read(uart_num) # 读取串口数据uart.write(uart_str)    # 将读取到的串口数据发回# uart.read会自动在数据末尾添加\n的操作,如果想去掉可以用strip()去掉# 例如 uart_str = uart.read(uart_num).strip()# 这样 uart_str得到的数据就不会被自动添加\n

五、条形码、矩形码、二维码

1.条形码

  • find_barcodes([roi])
    查找 roi 内所有一维条形码并返回一个 image.barcode 对象列表
# 条形码识别例程
#
# 这个例子展示了使用OpenMV Cam M7来检测条形码是多么容易。条形码检测不适用于M4相机。import sensor, image, time, mathsensor.reset()
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.VGA) # High Res!
sensor.set_windowing((640, 80)) # V Res of 80 == less work (40 for 2X the speed).
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)  # 必须关闭此功能,以防止图像冲洗…
sensor.set_auto_whitebal(False)  # 必须关闭此功能,以防止图像冲洗…
clock = time.clock()# 条形码检测可以在OpenMV Cam的OV7725相机模块的640x480分辨率下运行。
# 条码检测也将在RGB565模式下工作,但分辨率较低。 也就是说,
# 条形码检测需要更高的分辨率才能正常工作,因此应始终以640x480的灰度运行。def barcode_name(code):if(code.type() == image.EAN2):return "EAN2"if(code.type() == image.EAN5):return "EAN5"if(code.type() == image.EAN8):return "EAN8"if(code.type() == image.UPCE):return "UPCE"if(code.type() == image.ISBN10):return "ISBN10"if(code.type() == image.UPCA):return "UPCA"if(code.type() == image.EAN13):return "EAN13"if(code.type() == image.ISBN13):return "ISBN13"if(code.type() == image.I25):return "I25"if(code.type() == image.DATABAR):return "DATABAR"if(code.type() == image.DATABAR_EXP):return "DATABAR_EXP"if(code.type() == image.CODABAR):return "CODABAR"if(code.type() == image.CODE39):return "CODE39"if(code.type() == image.PDF417):return "PDF417"if(code.type() == image.CODE93):return "CODE93"if(code.type() == image.CODE128):return "CODE128"while(True):clock.tick()img = sensor.snapshot()codes = img.find_barcodes()for code in codes:img.draw_rectangle(code.rect())print_args = (barcode_name(code), code.payload(), (180 * code.rotation()) / math.pi, code.quality(), clock.fps())print("Barcode %s, Payload \"%s\", rotation %f (degrees), quality %d, FPS %f" % print_args)if not codes:print("FPS %f" % clock.fps())

2.矩形码

# 矩形码识别例程
#
# 这个例子展示了使用OpenMV Cam M7来检测数据矩阵是多么容易。数据矩阵检测不适用于M4相机。import sensor, image, time, mathsensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)  # 必须关闭此功能,以防止图像冲洗…
sensor.set_auto_whitebal(False)  # 必须关闭此功能,以防止图像冲洗…
clock = time.clock()while(True):clock.tick()img = sensor.snapshot()img.lens_corr(1.8) # 1.8的强度对于2.8mm的镜头来说是好的。matrices = img.find_datamatrices()for matrix in matrices:img.draw_rectangle(matrix.rect(), color = (255, 0, 0))print_args = (matrix.rows(), matrix.columns(), matrix.payload(), (180 * matrix.rotation()) / math.pi, clock.fps())print("Matrix [%d:%d], Payload \"%s\", rotation %f (degrees), FPS %f" % print_args)if not matrices:print("FPS %f" % clock.fps())

3.二维码

# 二维码例程
#
# 这个例子展示了OpenMV Cam使用镜头校正来检测QR码的功能(请参阅qrcodes_with_lens_corr.py脚本以获得更高的性能)。
import sensor, image, timesensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_gain(False)  # 必须关闭此功能,以防止图像冲洗…
clock = time.clock()while(True):clock.tick()img = sensor.snapshot()img.lens_corr(1.8) # 1.8的强度参数对于2.8mm镜头来说是不错的。for code in img.find_qrcodes():img.draw_rectangle(code.rect(), color = (255, 0, 0))print(code)print(clock.fps())

参考文章
OpenMV嵌入式图像处理

彻底搞懂Lab 颜色空间

OpenMV入门介绍相关推荐

  1. .NET读写Excel工具Spire.Xls使用(1)入门介绍

    原文:[原创].NET读写Excel工具Spire.Xls使用(1)入门介绍 在.NET平台,操作Excel文件是一个非常常用的需求,目前比较常规的方法有以下几种: 1.Office Com组件的方式 ...

  2. 独家 | 集成学习入门介绍

    作者:Jason Brownlee 翻译:wwl 校对:王琦 本文约3300字,建议阅读8分钟. 本文介绍了我们在生活中的许多决定包括了其他人的意见,由于群体的智慧,有的时候群体的决策优于个体.在机器 ...

  3. SpringBoot 2.0 系列001 -- 入门介绍以及相关概念

    为什么80%的码农都做不了架构师?>>>    SpringBoot 2.0 系列001 -- 入门介绍以及相关概念 什么是SpringBoot? 项目地址:http://proje ...

  4. ECC加密算法入门介绍

    作者  : ZMWorm[CCG]   E-Mail: zmworm@sohu.com   主页  : Http://ZMWorm.Yeah.Net/ 前言 同RSA(Ron Rivest,Adi S ...

  5. [翻译][1.4.2]Flask-Admin入门介绍

    为什么80%的码农都做不了架构师?>>>    #Flask-Admin入门介绍 ##让我们荡起双桨 初始化 Introduction To Flask-Admin Getting ...

  6. 谷歌大脑科学家亲解 LSTM:一个关于“遗忘”与“记忆”的故事 本文作者:奕欣 2017-01-14 09:46 导语:AI科技评论保证这是相对通俗易懂的一篇入门介绍了,看不懂的话欢迎关注「AI 科技

    谷歌大脑科学家亲解 LSTM:一个关于"遗忘"与"记忆"的故事 本文作者:奕欣 2017-01-14 09:46 导语:AI科技评论保证这是相对通俗易懂的一篇入 ...

  7. Tomcat容器入门介绍

    Tomcat容器入门介绍 Tomcat环境配置 PS:JDK的安装这里就不讲了,找到安装包直接下一步下一步就行了. 1.配置JDK 在Windows10下,找到环境变量 在环境变量中添加JDK主目录 ...

  8. QWT中Qdial的入门介绍

    最近使用了一下QWT.因为是第一次使用,所以有一些需要注意的地方,特记录在此,以供后来者参考. 1,QWT的安装与配置环境 有关QWT的安装与配置,网络上已经有很多篇文章,这里就不再重复了.介绍一下自 ...

  9. Spring入门介绍:

    Spring入门介绍 Spring诞生: 创建Spring的目的就是用来替代更加重量级的的企业级Java技术 简化Java的开发 基于POJO轻量级和最小侵入式开发 通过依赖注入和面向接口实现松耦合 ...

最新文章

  1. Android程序获得APP哈希值,Android – SMS Retriever API – 计算应用程序的哈希字符串问题...
  2. C指针原理(40)-递归(1)
  3. 大学生拍照搜题_大学生心理健康教育知识,请问:这个考试有没有找答案软件?...
  4. DESUtils 加解密时 Given final block not properly padded bug小记
  5. 适合于小团队产品迭代的APP测试流程 1
  6. linux源码scripts目录是什么,linux-kernel – linux / scripts / recordmcount:没有这样的文件或目录...
  7. [******] 堆排序
  8. 中国大陆物联网驶入快车道 台商抢上车
  9. Oracle输入默认密码错误,oracle中默认账号oracle 11g SQL plus软件怎么打开?打开显示密码错误怎么办?...
  10. Python:用类与对象写一元二次方程计算器中遇到的错误
  11. 为什么标签天线振子长度小于半个波长?
  12. [Python黑帽] 二.Python能做什么攻击?正则表达式、网络爬虫和套接字通信入门
  13. ## Asset Store(unity商店) 如何下载已购买的资源?*
  14. 签租房电子合同必须留意什么地方?
  15. Dart Web开发环境搭建及新建运行项目
  16. 怎么查看自己本地的ip地址
  17. php ios表情包,php处理APP中 emoji表情包的方法
  18. 选课系统 - 数据库查询(一)
  19. python中heapq的库是什么_Python中heapq模块的用法
  20. 华为超越三星拿下第一!2019年全球5G手机出货量榜单揭晓

热门文章

  1. 记录java.util.Collections.unmodifiableList()使用
  2. 刘汝佳训练指南《网络流》专题 BY 9974
  3. 微积分——Rolle定理的理解(罗尔定理)
  4. Pandas处理数据遇到的问题与解决
  5. 怎么给自己的U盘加密
  6. c语言找出一个数组中出现次数最多的那个元素,c语言找出数组中出现次数最多地那个元素...
  7. 【论文翻译】GoogleNet网络论文中英对照翻译--(Going deeper with convolutions)
  8. 食品卡路里是如何计算出来的?
  9. Unity3D 内存管理
  10. Visual Studio 2022