K210摄像头矩形图坐标识别

我接触的第一个硬件项目是设计一个简陋的智能视觉小车,我在项目里的任务是识别一张纸上六个目标点坐标然后发送给小车。

图一  场地样式

就是将上图六个点的坐标识别然后传输给小车。

识别效果大概是这样:

 图二 识别效果

因为是第一次做这样的项目,第一次使用maixpy不熟练之处还望大佬见谅,项目完成符合预期。

K210摄像头使用专门的maixpyIDE进行编辑。 它是用python语言进行编写但感觉缩进要求更加严格,不是四格缩进就会运行错误。

首先是导入:

import sensor,image,lcd,time

导入没有什么说法,设备、图像、显示屏、时间,没有其他特别的导入。

然后是初始化,因为之前没接触过硬件项目,初始化是直接拿的常用初始化:

lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)   #后置拍摄模式
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # 白平衡关闭
sensor.snapshot(1.8)#去鱼眼化

然后是一个找最大色块的函数:

def find_max(blobs): #找最大色块函数。这里是比较像素面积的方式,只返回最大面积色块
    max_size=0
    for blob in blobs:
        if blob[4] > max_size:
            max_blob=blob
            max_size = blob[4]
    return max_blob

因为坐标函数只是标注像素位置,所以我们要根据整个场地标注相对位置,这里是找黑线的方式找到整个场地,因为场地黑线过多所以要标注最大的黑色色块,就需要写一个只输出最大色块的函数。这里是通过比较所含像素点个数找到最大色块。blob[4]是像素个数。

要准确识别颜色就要准确的找到颜色阈值,可以通过工具——机器视觉——阈值编辑器找到颜色阈值。

 图三 阈值获取

导入图片文件调节阈值,当只有想要的颜色程白色时复制阈值,这个阈值摄像头识别的可能跟真实值有差距,调试的时候要在一定范围内稍微更改使摄像头识别更准确。

 图三 阈值编辑器

该项目阈值为:

green1_threshold   = (0, 55, -128, -18, 127, -18)
black_threshold  =(0, 46, -128, 15, -2, 44)

然后使用find-blobs进行颜色识别:

    blobs = img.find_blobs([black_threshold])#黑色边框定义识别
    blobs1 = img.find_blobs([green1_threshold])#绿色目标点定义

之后是识别黑色边框然后进行计算,算出一个单位长度的像素长度。

if blobs:        #寻找黑色边框
        max_blob = find_max(blobs)

        x1=max_blob[0]
        y1=max_blob[1]
        w1=max_blob[2]
        h1=max_blob[3]
        a1=(int((w1/2)+x1)-max_blob[0])/4
        a2=(int((h1/2)+y1)-max_blob[1])/4#计算单位坐标像素长度
        if a1==0:
            a1=1
        if a2==0:
            a2=1        #a1、a2之后要做分母,摄像镜头一开始找目标可能会出现0这里去零
        img.draw_rectangle(max_blob[0:4], color=(0,0,0))#对找到的目标进行黑框标注
        img.draw_cross(int((w1/2)+x1), int((h1/2)+y1))#使用十字标注目标中心点位置
        img.draw_string(max_blob[0],max_blob[1], (str(max_blob[0])+','+str(max_blob[1])), color = (0,0,0))#在显示屏标注目标最左和最下的坐标

这里的计算单位长度是按照该项目8*8的场地计算的,如果要计算其他规格的场地,上面代码写的复杂了,大致是黑框长度max-blob除以场地x格数,这里是除以八。

然后是寻找绿色目标,并计算目标坐标。

    if (blobs and blobs1):#寻找绿色目标点

        for b in blobs1:
            i=i+1
            x = b[0]
            y = b[1]
            width = b[2]
            height = b[3]




            if (x>=x1 and x<=x1+w1 and y>=y1 and y<=h1):
                c1=int(((b[5]-x1)+10)/a1)
                c2=int(((b[6]-y1)+10)/a2)#计算目标点坐标这里加10是摄像头有误差,我的加10最准确

                img.draw_rectangle([x,y,width,height])#用矩形标记出目标颜色区域
                t1[i-1]=8-abs(c1)
                t2[i-1]=8-abs(c2)#因为显示屏上图像是反转的,所以这里要用8减去。这里要看初始化跟不跟我的一样
                t=[t1[i-1],t2[i-1]]#形成数组,这就是目标点的坐标
                img.draw_cross(b[5], b[6]) #用十字标注目标中心点

要注意的是计算坐标时要不断调试,加减像素值防止较大误差,这里就在坐标上加了10个像素值才能准确的显示坐标,不同设备可能不一样。

后面包括去重复数据和显示屏显示注释比较全,不一一说明这里直接上完整代码。

完整代码:

import sensor,image,lcd,time
green1_threshold   = (0, 55, -128, -18, 127, -18)
black_threshold  =(0, 46, -128, 15, -2, 44)

#常用初始化
lcd.init()
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_vflip(1)   #后置拍摄模式
sensor.skip_frames(10) # Let new settings take affect.
sensor.set_auto_whitebal(False) # 白平衡关闭
sensor.snapshot(1.8)#去鱼眼化
def find_max(blobs): #找最大色块函数。这里是比较像素面积的方式,只返回最大面积色块
    max_size=0
    for blob in blobs:
        if blob[4] > max_size:
            max_blob=blob
            max_size = blob[4]
    return max_blob
i=0#循环计数
m=0#去除重复计数
t1=[0 for n in range(10000)]
t2=[0 for n in range(10000)]   #将t1和t2进行数组化,便于之后去重复数据
while True:
    img=sensor.snapshot()
    img = sensor.snapshot().lens_corr(strength = 1.2, zoom = 1.0)  #调整显示屏使其更“平整”便于识别,里面参数可更改
    blobs = img.find_blobs([black_threshold])#黑色边框定义识别
    blobs1 = img.find_blobs([green1_threshold])#绿色目标点定义


    if blobs:        #寻找黑色边框
        max_blob = find_max(blobs)

        x1=max_blob[0]
        y1=max_blob[1]
        w1=max_blob[2]
        h1=max_blob[3]
        a1=(int((w1/2)+x1)-max_blob[0])/4
        a2=(int((h1/2)+y1)-max_blob[1])/4#计算单位坐标像素长度
        if a1==0:
            a1=1
        if a2==0:
            a2=1        #a1、a2之后要做分母,摄像镜头一开始找目标可能会出现0这里去零
        img.draw_rectangle(max_blob[0:4], color=(0,0,0))#对找到的目标进行黑框标注
        img.draw_cross(int((w1/2)+x1), int((h1/2)+y1))#使用十字标注目标中心点位置
        img.draw_string(max_blob[0],max_blob[1], (str(max_blob[0])+','+str(max_blob[1])), color = (0,0,0))
        #在显示屏标注目标最左和最下的坐标
        if (max_blob[1]==0):#因为周围环境黑色较多,这里设置当黑色边框顶格时卡顿一下,调整摄像头恢复
            continue

    if (blobs and blobs1):#寻找绿色目标点

        for b in blobs1:
            i=i+1
            x = b[0]
            y = b[1]
            width = b[2]
            height = b[3]




            if (x>=x1 and x<=x1+w1 and y>=y1 and y<=h1):
                c1=int(((b[5]-x1)+10)/a1)
                c2=int(((b[6]-y1)+10)/a2)#计算目标点坐标这里加10是摄像头有误差,我的加10最准确

                img.draw_rectangle([x,y,width,height])#用矩形标记出目标颜色区域
                t1[i-1]=8-abs(c1)
                t2[i-1]=8-abs(c2)#因为显示屏上图像是反转的,所以这里要用8减去。这里要看初始化跟不跟我的一样
                t=[t1[i-1],t2[i-1]]#形成数组,这就是目标点的坐标
                img.draw_cross(b[5], b[6]) #用十字标注目标中心点
            
                n=0
                j=0

                while j<i: #防重复
                    if (t1[i-1]==t1[j-1] and t2[i-1]==t2[j-1]):
                        n=i+1
                    j=j+1
                if (n==0 and (abs(t1[i-1])<9)):#这里是对点进行输出,重复点不输出
                    print(t)
                    m=m+1#计数,记录输出几个点
                img.draw_string(x,y, "x")#标注文本x、y
                img.draw_string(x+10, y, str(t))#标注坐标
                img.draw_string(x,y+20, "green")#标注文本green如果是其他颜色请更改

    lcd.display(img)#lcd屏幕显示

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
青葱年少的头像青葱年少普通用户
上一篇 2023年7月29日
下一篇 2023年7月29日

相关推荐