【无标题】

24电赛E题视觉(OPENMV4)分享

前言

本人与两位队友均为暑假大一升大二,第一次参加电赛与分享经验,坐标江苏,希望大家一起交流进步!八月六号结果出来也是很幸运的获得了省一等奖(开心)!

视觉部分

闲聊

29日上午题目出来后我们本意是选H题小车(因为我们的赛前准备工作是以小车为载体的),然后也忙活了大半个上午搭TI环境。后经过午饭看了一下三子棋题目,发现也能做,便觉得不再受TI鸟气直奔E题!(可惜的是我刚把keil删了准备换新版本就换题目了),饭后认认真真看了下题目,在和队友商讨了方案以后,视觉部分我只需要发送坐标给主控让他可以换算出实际坐标即可,以及我还需发送每一个方格内黑白棋子状况。这么一看,着实简单?

找棋盘算法

方案1

对于找棋盘算法,一开始我选择的是find_rects()函数,可以直接用。再通过调整面积各种限定条件找到合适大小的矩形框即可?可是在实际操作起来,因为机械结构还没有搭建起来,光线等各种原因导致识别效果一直拉跨。(大佬知道有解决办法请多指教)故放弃。

#引入必要模块和方法
import pyb,math,sensor,image,time#必要模块
from pyb import UART#用于串口发送
import json,ustruct#用于打包数据
#摄像头初始化
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QQVGA)
sensor.skip_frames(time = 2000)
sensor.set_auto_whitebal(True) # 自动白平衡功能(颜色识别需用)
sensor.set_auto_gain(True) # 关闭图像传感器的自动增益(颜色识别需用)
sensor.set_brightness(-3)
sensor.set_contrast(-3)
#时钟
clock = time.clock()
#像素长(w)x,高(h)y,QQVGA固定为160*120,此值固定不变
pixel_x=160
pixel_y=120
#                                 ---矩形框部分---
#正摆时像素系数从零到1,可变
factor_x=1.0
factor_y=1.0
#斜摆时像素系数从01,可变
factor_left_x=1.0
factor_right_x=1.0
factor_top_y=1.0
factor_bottom_y=1.0
#---矩形框相关函数---

color_thresholds=[18, 83, -20, 18, -18, 20]
#判别最大矩形的大小,并将最大矩形及角点框出,从左上开始顺时针输出角点xy坐标
def find_rect_x_y(choice):
    global RT_x,RB_x,LT_x,LB_x,LT_y,RT_y,LB_y,RB_y
    img = sensor.snapshot()


    # 下面的`threshold`应设置为足够高的值,以滤除在图像中检测到的
    # 低边缘幅度的噪声矩形。最适用与背景形成鲜明对比的矩形。
    [[LB_x,LB_y],[RB_x,RB_y],[RT_x,RT_y],[LT_x,LT_y]]=find_max_rect(img)
    #如果逆时针转
    left_dx=RT_x-LT_x
    right_dx=RB_x-RT_x
    higher_dy=RT_y-LT_y
    lower_dy=LB_y-LT_y
    #矩形的大小判断,公式factor_x=x/pixel_x,factor_y=y/pixel_y
    #如果正着摆放
    if choice==1:
        factor_x=0.51
        factor_y=0.63
        if (left_dx+right_dx)>56 and (higher_dy+lower_dy)<80:
        #if left_dx>=pixel_x*(factor_x-0.1)and left_dx<=pixel_x*(factor_x+0.1) and lower_dy>=pixel_y*(factor_y-0.1) and lower_dy<=pixel_y*(factor_y+0.1) :
            print(LT_x,LT_y,RT_x,RT_y,RB_x,RB_y,LB_x,LB_y)
            rects=img.find_rects(threshold = 10000)
            max_rect=find_maxr(rects)
            img.draw_rectangle(max_rect.rect(), color = (255, 0, 0))
            img.draw_circle(LT_x,LT_y,2,color = (0, 0, 255), thickness = 2, fill = False)
    #如果顺时针转,顺时针45度左右
    elif choice==2:
        left_dx=LT_x-LB_x
        right_dx=RT_x-LT_x
        higher_dy=RT_y-LT_y
        lower_dy=RB_y-RT_y
        factor_x=0.50
        factor_y=0.62
        if (left_dx+right_dx)>80 and (left_dx+right_dx)<105:
        #if right_dx>=pixel_x*(factor_x-0.1)and right_dx<=pixel_x*(factor_x+0.1) and lower_dy>=pixel_y*(factor_y-0.1) and lower_dy<=pixel_y*(factor_y+0.1) :
            print(LT_x,LT_y,RT_x,RT_y,RB_x,RB_y,LB_x,LB_y)
            rects=img.find_rects(threshold = 10000)
            max_rect=find_maxr(rects)
            img.draw_rectangle(max_rect.rect(), color = (255, 0, 0))
    #如果逆时针转,逆时针45度左右
    elif choice==3:
        left_dx=RT_x-LT_x
        right_dx=RB_x-RT_x
        higher_dy=LT_y-LT_y
        lower_dy=LB_y-LT_y
        factor_x=0.31
        factor_y=0.40
        if (left_dx+right_dx)>80 and (left_dx+right_dx)<105:
        #if left_dx>=pixel_x*(factor_x-0.2)and left_dx<=pixel_x*(factor_x+0.2) and higher_dy>=pixel_y*(factor_y-0.25) and higher_dy<=pixel_y*(factor_y+0.25) :
            print(LT_x,LT_y,RT_x,RT_y,RB_x,RB_y,LB_x,LB_y)
            rects=img.find_rects(threshold = 10000)
            max_rect=find_maxr(rects)
            img.draw_rectangle(max_rect.rect(), color = (255, 0, 0))
    k = [LT_x,LT_y,RT_x,RT_y,RB_x,RB_y,LB_x,LB_y]
    return k



#描点函数,传入x1,y1,x2...,不加括号
def draw_crosses(k):
    index=0
    while index < len(k):
        img.draw_cross(k[index],k[index+1])
        index=index+2

#返回最大矩形角点
def find_max_rect(img):
    rects=img.find_rects(threshold = 10000)
    if rects:
        max_rect=find_maxr(rects)
#        img.draw_rectangle(max_rect.rect(), color = (255, 0, 0))
        point=max_rect.corners()
        return point[0],point[1],point[2],point[3]
    else:
        return (-1,-1),(-1,-1),(-1,-1),(-1,-1)
#判断最大矩形
def find_maxr(rects):
    global max_size
    max_size=0

    global max_rect

    for rect in rects:
        x,y,w,h=rect.rect()
        if w*h > max_size:
            max_rect=rect
            max_size = w*h
    return max_rect
#                           ---串口部分---
uart=UART(3,9600)
uart.init(9600,bits=8,parity=None,stop=1)
#串口发送一个字节
def sending_data(num):
    global uart;#?
    data=ustruct.pack("<b",int(num))#帧头+数据+帧尾
    uart.write(data);
#串口接收一个字节
def get_data():
    global pattern
    getrx = uart.readchar()#获取char类型数据
    if getrx == 0 or getrx==1 or getrx==2 or getrx==3:
        pattern = getrx
        return pattern
#发送外框坐标
def sending_rectangle():
    k=find_rect_x_y(3)
    sending_data(0xff)
    sending_data(k[0])
    sending_data(k[1])
    sending_data(k[2])
    sending_data(k[3])
    sending_data(k[4])
    sending_data(k[5])
    sending_data(k[6])
    sending_data(k[7])
    sending_data(0xfe)
    sending_data(0xfe)
#                             ---主循环---
while True:
    clock.tick()
    find_rect_x_y(2)









方案2

之后我想到了find_blobs()函数,因为黑线分割出来多个棋盘就可以了,分别找色块即可。可实施起来依旧困难,光线什么的也不确定最后也就不了了之了。(其实是因为懒得调)

方案3

image.find_line_segments()函数,最后我也确实是用的这个,找多条线段求斜率换算得到矩形框坐标。

识别棋子算法

方案1

找圆形。

方案2

找黑白色块

方案3

统计区域内lab信息

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值