OpenMV的官方教程:寻找色块;single_color_rgb565_blob_tracking示例讲解;视频讲解


需要提前看的文章:程序烧录;颜色阈值设置


目录


threshold_index和thresholds解析


固定代码部分


死循环部分


clock.tick()讲解


sensor.snapshot()讲解


for ... in ...部分


image.find_blobs()函数讲解


blob.elongation()讲解


img.draw_edges()和 img.draw_line部分解析


img.draw_rectangle(blob.rect())解析。


print()解析


结论:


我们点击右上角文件——>示例——>OpenMV——>Color Tracking——>single_color_rgb565_blob_tracking,打开单颜色识别的代码。代码如下,我增加了中文注释,你打开的将会是英文的注释。


# 这个例子展示了使用OpenMV Cam的单色RGB565跟踪。

import sensor, image, time, math

threshold_index = 0 # 0 for red, 1 for green, 2 for blue

# 颜色跟踪阈值 (L Min, L Max, A Min, A Max, B Min, B Max)

# 下面的阈值通常跟踪红色/绿色/蓝色的东西。您可能希望调整它们……

thresholds = [(30, 100, 15, 127, 15, 127), # 通用的红色阈值

             (30, 100, -64, -8, -32, 32), # 通用的绿色阈值

             (0, 30, 0, 64, -128, 0)]     # 通用的蓝色阈值

sensor.reset()                      #重置感光元件,重置摄像机

sensor.set_pixformat(sensor.RGB565) #设置颜色格式为RGB565,彩色,每个像素16bit。

sensor.set_framesize(sensor.QVGA)   #图像大小为QVGA

sensor.skip_frames(time = 2000)     #跳过n张照片,在更改设置后,跳过一些帧,等待感光元件变稳定。

sensor.set_auto_gain(False)         #颜色识别必须关闭自动增益,会影响颜色识别效果

sensor.set_auto_whitebal(False)     #颜色识别必须关闭白平衡,会影响颜色识别效果,导致颜色的阈值发生改变

clock = time.clock()

# 只有像素大于“pixels_threshold”和面积大于“area_threshold”的区域才会

# 由下面的"find_blobs"返回。如果更改相机分辨率,则更改“pixels_threshold”和  

# “area_threshold”。"merge=True"合并图像中所有重叠的斑点。。

while(True):

   clock.tick()             # 追踪两个snapshots()之间经过的毫秒数.

   img = sensor.snapshot()  #截取感光元件中的一张图片

   #在img.find_blobs这个函数中,我们进行颜色识别

   #roi是“感兴趣区”,是在画面的中央还是右上方或者哪里进行颜色识别。此处我们没有进行配置,默认整个图像进行识别

   for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):

       # 这些值依赖于blob不是循环的-否则它们将不稳定。

       if blob.elongation() > 0.5:

           img.draw_edges(blob.min_corners(), color=(255,0,0))     #利用一个红色的方框,绘制出Blob的最小边界

           img.draw_line(blob.major_axis_line(), color=(0,255,0))  #利用一个绿色的线,绘制穿过最小面积矩形的最长边

           img.draw_line(blob.minor_axis_line(), color=(0,0,255))  #利用一个蓝色的线,绘制穿过最小面积矩形的最短边

       # 这些值始终是稳定的。

       img.draw_rectangle(blob.rect())      #用矩形标记出目标颜色区域

       img.draw_cross(blob.cx(), blob.cy()) #在目标颜色区域的中心画十字形标记

       # 注意- blob的旋转是唯一的0-180。

       img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)

   print(clock.fps()) #打印帧率,可在OpenMV IDE的左下角串行终端查看

threshold_index和thresholds解析

threshold_index:设置要识别的颜色值,示例中的0表示识别红色,1识别绿色,2识别蓝色。


thresholds:存放可能要识别物体的LAB阈值。此处分别是红色,绿色,蓝色的阈值


threshold_index = 0 # 0 for red, 1 for green, 2 for blue

# 颜色跟踪阈值 (L Min, L Max, A Min, A Max, B Min, B Max)

# 下面的阈值通常跟踪红色/绿色/蓝色的东西。您可能希望调整它们……

thresholds = [(30, 100, 15, 127, 15, 127), # 通用的红色阈值

             (30, 100, -64, -8, -32, 32), # 通用的绿色阈值

             (0, 30, 0, 64, -128, 0)]     # 通用的蓝色阈值

固定代码部分

以下是固定代码,没什么好讲的。只需要注意,因为我们是颜色识别,所以必须关闭白平衡和自动增益。如果不关闭会导致颜色阈值发生改变,影响识别效果。感光元件介绍,这是官方介绍。RGB565表示是彩色识别,GRAYSCALE是黑白的。set_framesize是设置图像大小。


sensor.reset()                      #重置感光元件,重置摄像机

sensor.set_pixformat(sensor.RGB565) #设置颜色格式为RGB565,彩色,每个像素16bit。

sensor.set_framesize(sensor.QVGA)   #图像大小为QVGA

sensor.skip_frames(time = 2000)     #跳过n张照片,在更改设置后,跳过一些帧,等待感光元件变稳定。

sensor.set_auto_gain(False)         #颜色识别必须关闭自动增益,会影响颜色识别效果

sensor.set_auto_whitebal(False)     #颜色识别必须关闭白平衡,会影响颜色识别效果,导致颜色的阈值发生改变

clock = time.clock()


死循环部分

进入死循环


while(True):

clock.tick()讲解

clock.tick() ,OpenMV官方文档的解释是开始追踪运行时间。我将其注释掉也可以正常运行。应该就只是记录OpenMV运行时间而已,返回值并没有接收,可有可无。


clock.tick()             # 追踪两个snapshots()之间经过的毫秒数.

sensor.snapshot()讲解

img = sensor.snapshot(),截取感光元件中的照片,将截取的图片存入辅助帧缓冲存储区,返回参数image对象。这个时候,img这个变量就是image,可以理解为等价。


img = sensor.snapshot()#截取感光元件中的一张图片

for ... in ...部分

image.find_blobs()函数讲解

这个for ... in ...,我们先看img.find_blobs。前面说了,这个时候,img这个变量就是image。也就是说img.find_blobs=image.find_blobs。我们查官方手册查看此函数内容,可以看到第一个参数thresholds表示颜色阈值,也就是上面我们自己设置的LAB值。


第二个参数是roi,感兴趣区,通俗来说就是,我们要在画面中的哪一部分进行颜色识别。此处没有设置,就表面是整个区域都要进行颜色识别。


第三,四个参数是x_stride ,y_stride 。表示x和y轴上像素点个数大于等于x_stride和y_stride才会被识别。比如说, x_stride=2, y_stride=1是默认参数,此处这里没有设置,系统就认定X轴像素点不能小于2个。如果识别到x和y轴仅有一个像素点宽度,将会被忽略。


第五个参数是invert, 反转阈值,把阈值以外的颜色作为阈值进行查找。意思就是说,如果invert=True,而我们设置的颜色阈值是红色。那么OpenMV将会识别除红色以外的所有区域。


第六,七个参数分别是area_threshold (面积阈值),pixels_threshold (像素个数阈值)。如果如果色块被框起来的面积小于area_threshold,或者色块像素数量小于pixels_threshold,会被过滤掉。


第八个参数是merge 。默认为False,如果merge=True,那么识别到的所有色块将会合并成一个大色块。例如,OpenMV识别到右上方,中间分别一个色块(注:两个没有连接,具有明显的距离)。如果merge=False,那么图像上将会出现两个方框。而如果merge=True,那么将会是一个大方框将两个方框都包含。


第九个参数margin ,如果设置为1,那么两个blobs如果间距1一个像素点,也会被合并。通俗来说就是,如果左边a个像素点,右边b个像素点,这两个都被识别。但是a和b中间有一个像素点不属于识别单位,因为margin=1,我们会将这一个不是识别单位强行变成识别单位。但是假如a和b之间有两个像素点不属于识别单位,这样着两个像素点就不会被强行变成识别单位。


之后的四个参数我也没搞明白,默认参数就行,不用管。


此处,我们对这个img.find_blobs传入了四个值,分别是目标LAB阈值,目标像素个数低于200个的忽略,被框选面积小于200也被忽略。具体值可以根据需求调整。识别到的所有色块将会合并成一个大色块。(注意,如果我们不是按照规定的顺序给函数传入参数,必须前面加参数类型=传入值。如,thresholds[threshold_index]就是第一个参数值,所以不需要写成thresholds=[thresholds[threshold_index]],而后面三个需要,因为他们具体传参不是在第二,三,四位置)


之后img.find_blobs这个函数会根据传入参数进行输出一个包括每个色块的色块对象的列表,此列表存入blob中。


for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):

# 如果我们需要配置感兴趣区,方法如下。roi的格式是(x, y, w, h)的tupple.

# x:ROI区域中左上角的x坐标

# y:ROI区域中左上角的y坐标

# w:ROI的宽度

# h:ROI的高度

left_roi = [0,0,160,240]  

blobs = img.find_blobs([red],roi=left_roi)

blob.elongation()讲解

后面这句if blob.elongation() > 0.5:,blob.elongation()这个函数的作用就是看这个图案是否像圆形,如果越像圆,这个值越小,越不像圆,这个值越大。




if blob.elongation() > 0.5:  #可忽略

img.draw_edges()和 img.draw_line部分解析

接下来这三句话也可以注释,因为我们只需要把目标框选出来就可以了。这三句话作用就是利用一个红色的方框,绘制出Blob的最小边界。利用一个绿色的线,绘制穿过最小面积矩形的最长边。利用一个蓝色的线,绘制穿过最小面积矩形的最短边。如果我这么说不理解,可以分别注释掉着三句话,查看OpenMV的反应,就能理解了。


           img.draw_edges(blob.min_corners(), color=(255,0,0))     #利用一个红色的方框,绘制出Blob的最小边界

           img.draw_line(blob.major_axis_line(), color=(0,255,0))  #利用一个绿色的线,绘制穿过最小面积矩形的最长边

           img.draw_line(blob.minor_axis_line(), color=(0,0,255))  #利用一个蓝色的线,绘制穿过最小面积矩形的最短边

img.draw_rectangle(blob.rect())解析。

img.draw_rectangle(blob.rect())就是利用矩形将目标单位框选出来。blob.rect(),返回一个色块边界框,矩形元组(x, y, w, h) ,对应左上角x,y坐标,矩形宽和高。image.draw_rectangle(),利用(x, y, w, h) 绘制矩形,颜色默认为白色。


blob.cx(), blob.cy()分别返回色块中心点的x,有坐标。利用 img.draw_cross()绘制一个十字形标记。

       img.draw_rectangle(blob.rect())      #用矩形标记出目标颜色区域

       img.draw_cross(blob.cx(), blob.cy()) #在目标颜色区域的中心画十字形标记

print()解析

最后这句就是打印帧率(帧率是每秒图像的数量)。如果只想用于颜色识别,可注释掉。


   print(clock.fps()) #打印帧率

结论:

最后结果如下,可删除注释部分


# 这个例子展示了使用OpenMV Cam的单色RGB565跟踪。

import sensor, image, time, math

threshold_index = 0 # 0 for red, 1 for green, 2 for blue

# 颜色跟踪阈值 (L Min, L Max, A Min, A Max, B Min, B Max)

# 下面的阈值通常跟踪红色/绿色/蓝色的东西。您可能希望调整它们……

thresholds = [(16, 8, -39, 18, -31, 9), # generic_red_thresholds

             (54, 77, -9, 9, 85, 47), # generic_green_thresholds

             ]     # generic_blue_thresholds

sensor.reset()#重置感光元件,重置摄像机

sensor.set_pixformat(sensor.RGB565) #设置颜色格式为RGB565,彩色,每个像素16bit。

sensor.set_framesize(sensor.QVGA)   #图像大小为QVGA

sensor.skip_frames(time = 2000)     #跳过n张照片,在更改设置后,跳过一些帧,等待感光元件变稳定。

sensor.set_auto_gain(False)         #颜色识别必须关闭自动增益,会影响颜色识别效果

sensor.set_auto_whitebal(False)     #颜色识别必须关闭白平衡,会影响颜色识别效果,导致颜色的阈值发生改变

clock = time.clock()

# 只有像素大于“pixels_threshold”和面积大于“area_threshold”的区域才是

# 由下面的"find_blobs"返回。更改“pixels_threshold”和“area_threshold”

# 相机的分辨率。"merge=True"合并图像中所有重叠的斑点。

while(True):

   clock.tick()# 追踪两个snapshots()之间经过的毫秒数.

   img = sensor.snapshot()#截取感光元件中的一张图片

   #在img.find_blobs这个函数中,我们进行颜色识别

   #roi是“感兴趣区”,是在画面的中央还是右上方或者哪里进行颜色识别。此处我们没有进行配置,默认整个图像进行识别

   for blob in img.find_blobs([thresholds[threshold_index]], pixels_threshold=200, area_threshold=200, merge=True):

       # 这些值依赖于blob不是循环的-否则它们将不稳定。

       #if blob.elongation() > 0.5:

           #img.draw_edges(blob.min_corners(), color=(255,0,0))    #利用一个红色的方框,绘制出Blob的最小边界

           #img.draw_line(blob.major_axis_line(), color=(0,255,0)) #利用一个绿色的线,绘制穿过最小面积矩形的最长边

           #img.draw_line(blob.minor_axis_line(), color=(0,0,255)) #利用一个蓝色的线,绘制穿过最小面积矩形的最短边

       # 这些值始终是稳定的。

       img.draw_rectangle(blob.rect())      #用矩形标记出目标颜色区域

       img.draw_cross(blob.cx(), blob.cy()) #在目标颜色区域的中心画十字形标记

       # 注意- blob的旋转是唯一的0-180。

       #img.draw_keypoints([(blob.cx(), blob.cy(), int(math.degrees(blob.rotation())))], size=20)

   #print(clock.fps()) #打印帧率