【嘉楠科技 CanMV K230测评】单一颜色识别&简单二维码识别
[复制链接]
单一颜色识别
在K230的颜色识别中,使用的是LAB色彩模型。有区别于我们人眼色RGB模型。其中的L、A、B分别代表的是颜色的亮度,红色到绿色的指示,黄色和蓝色之间的指示。其检测的原理可以简单的理解为,我们通过这三个参数设置了一个有限的范围,在整张图片中,计算出每个像素点的LAB数值,然后去和我们所设定的阈值进行对比,当在阈值范围的时候,我们就认为这个就是我们所要检测到的颜色,从而进行标记出来进行显示。那么实现这个过程,K230为我们提供了一个封好的函数叫做find_blobs。
image.find_blobs(thresholds[, invert=False[, roi[, x_stride=2[, y_stride=1[, area_threshold=10[, pixels_threshold=10[, merge=False[, margin=0[, threshold_cb=None[,merge_cb=None]]]]]]]]]])这个是find_blobs的函数定义,可以看到参数的数量较多。
thresholds参数需要输入一个元组列表,这个位置可以存放六个数据,用来表示LAB三个参数的低阈值和高阈值。顺序依次是l_lo,l_hi,a_lo,a_hi,b_lo,b_hi。如果图像是一个灰度图像,则仅需要两个参数值进行显示,即灰度最小值和灰度最大值。如果元组数值不足6个,则后面缺少的会自动补齐为最大,若超过六个,则超出的部分自动忽略。
invert参数为反相,即最终识别的是在阈值范围内还是阈值范围外,若为Flase则不进行反相,识别的内容为阈值范围内,若为True则进行反相,识别阈值范围外的所有像素点。
roi是检测的区域范围,若不设置默认为整张图像。
x_stride和y_stride是查找色块时跳过的像素数量。色块较大时,可以增加数值来加快查找色块的速度。
area_threshold为边框区域阈值,当边框区域小于这个数值的时候,会被过滤掉。pixels_threshold为像素数阈值,当色块的像素数少于这个数值的时候,会被过滤掉。
后面的四个参数用于表示合并相关的内容。
调用这个函数返回的对象是image.blob。这个是检测到的关于色块的信息。包含的内容有矩形元组(即能刚好框住该色块的矩形框,包含的数据有x、y、w、h,分别是横坐标、纵坐标、宽度和高度),像素数量,色块的中心横纵坐标,色块的旋转角度等信息。3.11 image 图像处理 API手册 — K230 CanMV
下面实际操作来试一下颜色识别的功能。
在程序中依旧是调用摄像头、拍照、显示的步骤。检测的程序放在了拍照和显示之间。这里是直接调用了find blobs的函数,并将返回的信息存在blobs变量中,然后针对这个变量元组中不同位置的信息,进行绘制标识的操作。这里结合之前画圆的函数,实现了把圆形表示出来的效果。需要注意的是,画圆函数输入的值是int类型,因此当b[2]这个数值为偶数的时候,除2可以得到int类型,但是当该数值为奇数的时候,除2就会得到小数,因此就需要进行一下强转,将其转为int类型,就可以实现。如果不进行强转出现的报错提醒是Exception can't convert float to int,需要注意一下。
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)] # 蓝色阈值
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([thresholds[0]]) # 0,1,2分别表示红,绿,蓝色。
if blobs:
for b in blobs: #画矩形和箭头表示
tmp=img.draw_circle(b[5],b[6],int(b[2]/2),color = (255, 255, 255),thickness = 2,fill = False)
tmp=img.draw_cross(b[5], b[6], thickness = 2)
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()
当然颜色阈值采用的是官方例程中提供的阈值,因为使用的检测图像也是官方例程中提供的。这里的阈值更改可以直接更改在程序引入相关接口后定义的元组中,进行更改。更改的流程首先要导入图像(可以选择帧缓冲区),然后点击IDE中的工具->机器视觉->阈值编辑器,然后选择帧缓冲区或导入图像,然后在下面的滑块中调整,确保只识别出你想要的颜色,然后复制参数,更改元组的数据即可。操作效果如下所示。注意白色的位置才是被跟踪的像素,若是采用下图的方式,则是刚好将蓝色区域排除了,所以可以选择使用反相来实现检测。
最终的演示效果如下所示:
原图
红色区域识别
蓝色区域识别(反相,自定义颜色阈值范围)
二维码识别
二维码现在被广泛的使用在我们的日常生活中,查找信息、结账支付、登陆账号等等。因此能够准确的识别二维码也是如今机器视觉的一个重要功能。
二维码是采用某种特定的几何图形按照一定的规律进行分布的图形,利用了计算机中的01概念,从而实现了使用图形来表示众多的信息。
在K230中使用函数find_qrcodes()即可实现二维码的检测和采集信息。
这个函数的参数仅有感兴趣的范围一个参数,即roi,如果不进行设置则默认整张图片。
返回的信息是一个元组列表。[0]-[3]是起始点的横纵坐标,[4]是载荷信息,[5]是版本号。image - 图像处理 — K210 CanMV
下面是代码的演示。
import time, math, os, gc
from media.sensor import * #导入sensor模块,使用摄像头相关接口
from media.display import * #导入display模块,使用display相关接口
from media.media import * #导入media模块,使用meida相关接口
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() #拍摄图片
res = img.find_qrcodes() #寻找二维码
if len(res) > 0: #在图片和终端显示二维码信息
img.draw_rectangle(res[0].rect(), thickness=2)
img.draw_string_advanced(0, 0, 30, res[0].payload(), color = (255, 255, 255))
print(res[0].payload()) #串口终端打印
Display.show_image(img) #显示图片
print(clock.fps()) #打印帧率
###################
# IDE中断释放资源代码
###################
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()
效果演示
使用草料二维码生成一个包含EEWORLD字符信息的二维码,进行识别扫描,可以实现准确的识别,并可以将信息显示在屏幕上以及打印在串行终端中进行显示。
|