19年电赛的条形码,二维码的识别使用k210的自带的
find_qrcodes()
和find_barcodes()
函数(之前的文章检测三码并保存其照片中有使用),最近使用了模板匹配的方法,发现识别的效果更好。
首先让我们学习一下模板匹配的函数,已经了解的可以直接跳到文章末尾查看实例
官方文档的解释
image.find_template(template, threshold[, roi[, step=2[, search=image.SEARCH_EX]]])尝试使用归一化互相关(NCC)算法在图像中找到第一个模板匹配的位置。返回匹配位置的边界框元组(x, y, w, h),否则返回None。
template 是一个与这个图像对象相匹配的小图像对象。注意:两图像须都为灰度图。threshold 是浮点数(0.0-1.0),其中较小的值在提高检测速率同时增加误报率。相反,较高的值会降低检测速率,同时降低误报率。
roi 是感兴趣区域的矩形元组(x,y,w,h)。如果未指定,ROI即整个图像的图像矩形。 操作范围仅限于 roi 区域内的像素。
step 是查找模板时需要跳过的像素数量。跳过像素可大大提高算法运行的速度。该方法只适用于SERACH_EX模式下的算法。
search 可为 image.SEARCH_DS or image.SEARCH_EX. image.SEARCH_DS 搜索模板所用算法较 image.SEARCH_EX 更快,但若模板位于图像边缘周围,可能无法成功搜索。 image.SEARCH_EX 可对图像进行较为详尽的搜索,但其运行速度远低于 image.SEARCH_DS 。
仅支持灰度图像。
大家想到模板匹配首先想到的都是模板匹配对识别时的环境、距离、光线等要求严格,所以一般实例开发时都不会使用这个方法,但是!!一个模板难以识别,那就对同一个物体进行多模板匹配,这样就可以增加识别到的几率。
下面是提高模板匹配的准确率的一些方法:
要提高模板匹配的准确率,以下是一些建议:
- 选择具有清晰、明显且唯一特征的模板图像:模板图像应该有与目标图像区分开的独特特征。较复杂的背景或模糊的图像可能会导致匹配不准确。
- 确保模板图像与目标图像具有相同的灰度格式:在进行模板匹配之前,确保模板图像和目标图像都转换为相同的灰度格式,以便进行正确的像素比较和匹配。
- 考虑模板图像的大小和比例:模板图像的大小应适合于目标图像中可能出现的目标物体的大小。如果目标物体在实际运行时可能具有不同的比例,可以考虑使用多个不同尺寸的模板图像进行匹配。
- 选择多个不同的角度和变形的模板图像:如果目标物体可能在实际运行时出现不同的角度或变形,可以选择多个不同角度和变形的模板图像,以增加匹配的准确性。
- 通过数据增强技术生成更多的训练样本:对于较复杂的目标物体,可以使用数据增强技术生成更多的训练样本,如旋转、缩放、平移和变形等,以扩大模板图像的多样性。
还有!所有的模板都需要将格式转化为pgm的图片,可以在这个网站转换https://convertio.co/zh/bmp-pgm/
我自己在使用模板匹配的时候曾想过可不可以将模板的分辨率减小,而运行时的分辨率大,这样像素比较的时候,会不会准确更好。然后进行了测试,发现模板可以选取比运行时的分辨率小的,而且模板应该尽量只包括要是别的物体这样ncc算法在进行比较匹配的时候匹配到的概率会大大提升。
检测方法:大家可以自己测试一下
①准备多张只包含被测物图的模板图片(灰度),然后使用r=img.find_template()函数进行匹配后img.draw_rectangle®,将匹配到的模板圈出来
②反例:准备多张和运行时大小一样的模板也同样使用img.draw_rectangle®函数画出模板
结论:第一种方法圈出来的就只有被测物体,说明只要被测物体的角度大小与模板相同,在运行时的分辨率中存在就会被检测到;同样,第二个方法圈出来的就是整个画面,匹配难度更大,要几乎完全一样才可以被圈出。
实现功能:
sd卡中保存有两种物体的模板,前五张图片是条形码的灰度图片,后五张是二维码的灰度图片——注意!图片是实际运行时的各角度的图片(大家也需要尽量提高模板的质量来提高模板匹配的准确率).
当匹配到是条形码时通过串口发送data=1的数据(给飞控当然也可以是其他设备)并且保存当前图片(不超过三张,超过将自动覆盖),LED亮红灯;
但匹配到二维码时,串口发送数据data=2,并且保存当前图片(不超过三张,超过将自动覆盖)LED亮绿灯;
如果没有匹配到则发送数据data=0,LED亮蓝灯。
亮LED是为了在脱机运行时可以更好的判断是否识别到,识别到什么。
import sensor, image, time, ustruct
from image import SEARCH_EX
from pyb import UART
from pyb import LED
sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_framesize(sensor.QQVGA)
sensor.set_auto_exposure(False)
sensor.set_auto_whitebal(False)
sensor.skip_frames(time=2000)
uart = UART(3, 115200)
uart.init(115200, bits=8, parity=None, stop=1)
led_red=LED(1)
led_green=LED(2)
led_blue=LED(3)
# Load templates.
templates = ["/1.pgm","/2.pgm", "/3.pgm", "/4.pgm", "/5.pgm", "/6.pgm", "/7.pgm","/8.pgm","/9.pgm","/10.pgm"]
i=0 #条形码保存张数
j=0 #二维码保存张数
# 串口发送函数0x43模板匹配
# 没识别到0,条形码1,二维码2
def uart_send_43(data):
length = 1
data = bytearray([0xaa, 0x29, 0x05, 0x43, length, data, 0xbb])
uart.write(data)
while True:
img = sensor.snapshot()
for index, t in enumerate(templates):
template = image.Image(t)
r = img.find_template(template,0.7, step=4, search=SEARCH_EX)#step 每次匹配的像素数
if r:
print("Matched template:", index+1)
if index < 5:
if i<3:
img.save("/sd/barc"+str(i+1)+".jpg")
print("保存第%d张条形码成功"%(i+1))
i=i+1
else:
i=0
print("已保存足够的条形码")
uart_send_43(1) # 匹配到1-5的模板,发送data=1
led_red.on()
led_green.off()
led_blue.off()
else:
uart_send_43(2) # 匹配到其他模板,发送data=2
led_red.off()
led_green.on()
led_blue.off()
if j<3:
img.save("/sd/qrc"+str(j+1)+".jpg")
print("保存第%d张条形码成功"%(j+1))
j=j+1
else:
j=0
print("已保存足够的条形码")
break
else:
led_red.off()
led_green.off()
led_blue.on()
uart_send_43(0) # 没有匹配到模板,发送data=0
写在最后:模板匹配难点其实在于模板的质量,如果难以得到好的模板,可以试试神经网络。