赞
踩
OpenMV是一款具有图像处理功能的可编程摄像头模块,可以实现简单的机器视觉应用,例如人脸检测、Apriltag追踪、圆形检测、矩形检测等。
(这里介绍另一款可编程摄像头模块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视觉库 | √ | √ |
像素:像素是数字图像中的最小单元。
分辨率:分辨率指单位长度内像素点的数量,常用的度量为ppi(pixels per inch),即每英寸有多少像素点。
感光元件是由很多个感光点构成的,比如有 640 × 480 640×480 640×480个点,每个点就是一个像素,把每个点的像素收集整理起来,就是一副图片,那么这张图片的分辨率就是 640 × 480 640×480 640×480:
帧率(FPS,Frames Per Second)就是每秒钟处理的图片数量,如果超过20帧,人眼就基本分辨不出卡顿。电影的帧率一般是24FPS,游戏的帧率一般都大于30FPS。
RGB指的是红绿蓝三种颜色,是光学三原色,所有的颜色都可以由这三种色彩混合而成。(三原色是依据人类视觉定义的,不存在绝对的三原色)
Lab是由一个亮度通道和两个颜色通道组成的。在Lab颜色空间中,每个颜色用L、a、b三个数字表示,各个分量的含义是这样的:
Lab是基于人对颜色的感觉来设计的,更具体地说,它是感知均匀(perceptual uniform)的。Perceptual uniform的意思是,如果数字(即前面提到的L、a、b这三个数)变化的幅度一样,那么它给人带来视觉上的变化幅度也差不多。
Lab相较于RGB与CMYK等颜色空间更符合人类视觉,也更容易调整:想要调节亮度就调节L通道,想要调节色彩平衡就分别调a和b。
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对象
ROI:Region Of Interest,图像处理中的术语“感兴趣区”。就是在要处理的图像中提取出的要处理的区域。
视觉系统通常需要给使用者提供一些反馈信息。直接在图像中显示出来,很直观。
# Hello World Example
#
# Welcome to the OpenMV IDE! Click on the green run arrow button below to run the script!
import sensor, image, time
sensor.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!")
OpenMV通过find_blobs()函数可以找到色块(带颜色的物体),返回色块的位置、高度、像素等信息。
for blob in img.find_blobs(thresholds):
# Single Color RGB565 Blob Tracking Example
#
# This example shows off single color RGB565 tracking using the OpenMV Cam.
import sensor, image, time, math
threshold_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_thresholds
sensor.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())
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 measured
while(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]) # rect
img.draw_cross(b[5], b[6]) # cx, cy
Lm = (b[2]+b[3])/2
length = K/Lm
print(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
# 条形码识别例程
#
# 这个例子展示了使用OpenMV Cam M7来检测条形码是多么容易。条形码检测不适用于M4相机。
import sensor, image, time, math
sensor.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())
# 矩形码识别例程
#
# 这个例子展示了使用OpenMV Cam M7来检测数据矩阵是多么容易。数据矩阵检测不适用于M4相机。
import sensor, image, time, math
sensor.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())
# 二维码例程
#
# 这个例子展示了OpenMV Cam使用镜头校正来检测QR码的功能(请参阅qrcodes_with_lens_corr.py脚本以获得更高的性能)。
import sensor, image, time
sensor.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嵌入式图像处理
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。