【嘉楠科技 CanMV K230测评】多色识别以及颜色计数&AprilTag初次使用
<p><strong>多色识别</strong></p><p>之前我们做过单一色彩识别的程序,多色识别实际上就是使用一个循环函数,在循环中,每次切换不同的判断标准,然后依次进行draw,就可以标识出不同的颜色的色块。</p>
<p>基本的程序逻辑是,在find blobs的时候,选取的阈值,不是单一的,而是在一个范围为3的循环中(已知仅有三种颜色),每一次的循环都会切换不同的阈值。在每一次的循环中,都会找到对应的阈值的所有blobs,返回一个元组列表,在这个元组列表中进行一个新的循环,对每一个元组列表里的色块进行单独的框选标识和打印对应的字符。</p>
<p>这里的话,需要单独的去建立两个新的元组,用来存放颜色信息和字符信息。分别来表示不同的颜色。</p>
<p>下面是代码的演示。</p>
<p>可以看到多出了两个新的变量元组,colors1和colors2,分别存储的是红绿蓝三色的颜色数据和颜色字符数据。</p>
<p>在拍照和显示的中间,加入了两个循环,其中第一个循环用来循环不同的颜色,第二个循环用来循环同一个颜色中的不同的色块。整体的程序与单一颜色识别的程序相差不大。</p>
<pre>
<code class="language-python">import time, os, sys
from media.sensor import * #导入sensor模块,使用摄像头相关接口
from media.display import * #导入display模块,使用display相关接口
from media.media import * #导入media模块,使用meida相关接口
# 颜色识别阈值 (L Min, L Max, A Min, A Max, B Min, B Max) LAB模型
# 下面的阈值元组是用来识别 红、绿、蓝三种颜色,当然你也可以调整让识别变得更好。
thresholds = [(30, 100, 15, 127, 15, 127), # 红色阈值
(30, 100, -64, -8, 50, 70), # 绿色阈值
(0, 40, 0, 90, -128, -20)] # 蓝色阈值
colors1 = [(255,0,0), (0,255,0), (0,0,255)]
colors2 = ['RED', 'GREEN', 'BLUE']
try:
sensor = Sensor() #构建摄像头对象
sensor.reset() #复位和初始化摄像头
sensor.set_framesize(width=800, height=480) #设置帧大小为LCD分辨率(800x480),默认通道0
sensor.set_pixformat(Sensor.RGB565) #设置输出图像格式,默认通道0
Display.init(Display.VIRT, sensor.width(), sensor.height()) #只使用IDE缓冲区显示图像
MediaManager.init() #初始化media资源管理器
sensor.run() #启动sensor
clock = time.clock()
while True:
os.exitpoint() #检测IDE中断
################
## 这里编写代码 ##
################
clock.tick()
img = sensor.snapshot() #拍摄一张图片
for i in range(3):
blobs = img.find_blobs(]) # 0,1,2分别表示红,绿,蓝色。
if blobs:
for b in blobs: #画矩形、箭头和字符表示
tmp=img.draw_rectangle(b, thickness = 4, color = colors1)
tmp=img.draw_cross(b, b, thickness = 2)
tmp=img.draw_string_advanced(b, b-35, 30, colors2,color = colors1)
img.draw_string_advanced(0, 0, 30, 'FPS: '+str("%.3f"%(clock.fps())), color = (255, 255, 255))
Display.show_image(img) #显示图片
print(clock.fps()) #打印FPS
###################
# IDE中断释放资源代码
###################
except KeyboardInterrupt as e:
print("user stop: ", e)
except BaseException as e:
print(f"Exception {e}")
finally:
# sensor stop run
if isinstance(sensor, Sensor):
sensor.stop()
# deinit display
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
# release media buffer
MediaManager.deinit()
</code></pre>
<p>效果演示。</p>
<div style="text-align: center;"></div>
<p><strong>颜色识别计数</strong></p>
<p>在实际的生活和生产工程中,可能会存在同一个物品散落,需要进行计数的情况,这样的物体通常都有颜色一致的特征。find blobs函数最终返回的是一个元组列表,那么这个返回值就有一个很好的特性,就是可以计算出元组的长度用来表示检测到的色块的数量。同样例程中也给出了一个检测黄色跳线帽的一个例程,我们运行来实验一下。</p>
<p>代码仿照上面的单一颜色识别程序,需要改变的是颜色阈值的设定,这里我们可以导入一张包含有跳线帽的图片,通过阈值编辑器来进行阈值的获取。然后在获取执行完fing blobs的函数后,得到了一个blobs的元组列表对象。使用len函数(在python中有明确定义,用来获取一个对象的长度,这个对象可以是元组列表等也可以是一个字典)对blobs这个元组列表进行长度的获取,然后使用draw进行字符的打印。下面使用代码实现一下。</p>
<pre>
<code class="language-python">import time, os, sys
from media.sensor import * #导入sensor模块,使用摄像头相关接口
from media.display import * #导入display模块,使用display相关接口
from media.media import * #导入media模块,使用meida相关接口
thresholds = [(18, 72, -13, 31, 18, 83)] #黄色跳线帽阈值
try:
sensor = Sensor() #构建摄像头对象
sensor.reset() #复位和初始化摄像头
sensor.set_framesize(width=800, height=480) #设置帧大小为LCD分辨率(800x480),默认通道0
sensor.set_pixformat(Sensor.RGB565) #设置输出图像格式,默认通道0
Display.init(Display.VIRT, sensor.width(), sensor.height()) #只使用IDE缓冲区显示图像
MediaManager.init() #初始化media资源管理器
sensor.run() #启动sensor
clock = time.clock()
while True:
os.exitpoint() #检测IDE中断
################
## 这里编写代码 ##
################
clock.tick()
img = sensor.snapshot()
blobs = img.find_blobs(])
if blobs: #画框显示
for b in blobs:
tmp=img.draw_rectangle(b)
tmp=img.draw_cross(b, b)
#显示计算信息
img.draw_string_advanced(0, 0, 30, 'FPS: '+str("%.3f"%(clock.fps()))+' Num: '
+str(len(blobs)), color = (255, 255, 255))
Display.show_image(img)
print(clock.fps()) #打印FPS
###################
# IDE中断释放资源代码
###################
except KeyboardInterrupt as e:
print("user stop: ", e)
except BaseException as e:
print(f"Exception {e}")
finally:
# sensor stop run
if isinstance(sensor, Sensor):
sensor.stop()
# deinit display
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
# release media buffer
MediaManager.deinit()
</code></pre>
<p>下面使用例程中提供的图片,进行效果的演示。</p>
<div style="text-align: center;"></div>
<p><strong>AprilTag识别</strong></p>
<p>AprilTag是一种视觉标签,用于增强现实(AR)、机器人导航和计算机视觉等应用。它由一系列黑白图案组成,每个标签都有一个唯一的标识符。相机可以识别这些标签,并计算它们在三维空间中的位置和朝向。这个标签有更高的识别率,即使在环境较差的情况下,也能实现较为精准的识别,而且容易生成和使用,因此被广泛的应用在需要空间定位的应用中。</p>
<p>K230中可以使用find_apriltags进行AprilTag的识别。其函数原型是find_apriltags(]]]]])。其中参数roi是识别的范围,families是要解码的标签家族的位掩码,fx和fy是以像素为单位的相机x和y方向的焦距。cx和cy是图像的中心。</p>
<p>下面进行代码的演示。</p>
<pre>
<code class="language-python">import time, math, os, gc
from media.sensor import * #导入sensor模块,使用摄像头相关接口
from media.display import * #导入display模块,使用display相关接口
from media.media import * #导入media模块,使用meida相关接口
# apriltag代码最多支持可以同时处理6种tag家族。
# 返回的tag标记对象,将有其tag标记家族及其在tag标记家族内的id。
tag_families = 0
tag_families |= image.TAG36H11
def family_name(tag):
if(tag.family() == image.TAG16H5):
return "TAG16H5"
if(tag.family() == image.TAG25H7):
return "TAG25H7"
if(tag.family() == image.TAG25H9):
return "TAG25H9"
if(tag.family() == image.TAG36H10):
return "TAG36H10"
if(tag.family() == image.TAG36H11):
return "TAG36H11"
if(tag.family() == image.ARTOOLKIT):
return "ARTOOLKIT"
try:
sensor = Sensor(width=1280, height=960) #构建摄像头对象,将摄像头长宽设置为4:3
sensor.reset() #复位和初始化摄像头
sensor.set_framesize(width=320, height=240) #设置帧大小为LCD分辨率(800x480),默认通道0
sensor.set_pixformat(Sensor.RGB565) #设置输出图像格式,默认通道0
Display.init(Display.ST7701, to_ide=True) #同时使用3.5寸mipi屏和IDE缓冲区显示图像,800x480分辨率
MediaManager.init() #初始化media资源管理器
sensor.run() #启动sensor
clock = time.clock()
while True:
os.exitpoint() #检测IDE中断
clock.tick()
img = sensor.snapshot() #拍摄图片
for tag in img.find_apriltags(families=tag_families): # 如果没有给出家族,默认TAG36H11。
img.draw_rectangle(tag.rect(), color = (255, 0, 0), thickness=4)
img.draw_cross(tag.cx(), tag.cy(), color = (0, 255, 0), thickness=2)
print_args = (family_name(tag), tag.id(), (180 * tag.rotation()) / math.pi) #打印标签信息
print("Tag Family %s, Tag ID %d, rotation %f (degrees)" % print_args)
#显示图片,LCD居中方式显示
Display.show_image(img, x=round((800-sensor.width())/2),y=round((480-sensor.height())/2)) #显示图片
print(clock.fps()) #打印帧率
except KeyboardInterrupt as e:
print(f"user stop")
except BaseException as e:
print(f"Exception '{e}'")
finally:
# sensor stop run
if isinstance(sensor, Sensor):
sensor.stop()
# deinit display
Display.deinit()
os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)
time.sleep_ms(100)
# release media buffer
MediaManager.deinit()
</code></pre>
<p>演示效果如下,可以看到在打印窗口中可以看到识别到的AprilTag以及角度的信息,或许可以借助这个角度的信息进行一些空间定位。(之前没有应用过这个AprilTag,最近比较忙,下周研究一下相关的文档,看看相关的原理是怎么实现的。)</p>
<div style="text-align: center;"></div>
<p> </p>
<p>借助这个角度的信息进行一些空间定位这个可以做做</p>
页:
[1]