2021电赛F题数字识别和巡线部分

2021电赛F题数字识别和巡线部分

文章之前12月发了一次,但是我后来申请的免毕设后,用到了一些文字,所以删了这篇文章,但是还是查重了,于是我把一些程序讲解先删了,等毕设结束后再编辑加上。

这次电赛我没有准备多少东西,只提前准备了图像识别和坐标计算一类的。在20年的省赛帮过雪地调过k210后,自己后来为了比赛,也买了一个。参加了省物联网和交通科技比赛。

由于这边学校对竞赛支持力度不大,经费不多,所以我就用了一块k210.用它作识别和巡线其实是完全够用的。只需要写个判断分开就好。

识别这块我起初自己配的aconda和pycharm环境,不过出现各种问题,没耐下心去做(这学期课程依旧很多,而且还有别的事)。直接用了 mxyolo这款软件,一键配置环境库,再加上英伟达cuda加速就可以了。

我用了总共600张图片,花了20分钟大概(我的老笔记本gtx1050,没有独显直连所以也没有出过视频了。) 对象的1650大概在10分钟出头。标记是门体力活,好在有了不错的识别效果,图片样本拍摄是在不同光线和距离情况下,最终模型识别成功率大概在80%左右,速度很快。只是,7容易识别成1,5有时候会识别成2,这是在距离不定的情况下,我想是训练数据集不够。迭代在30,loss挺低了。

在摄像头悬空情况下,正好可以识别2-3个数字。

后来想起软件图片,突然想写一篇文章,发现当时没有截图。

[En]

When I remembered the software picture later, I suddenly wanted to write an article and found that there was no screenshot at that time.

再说一说软件部分吧,k210我是在Maixpy下进行编写的,调用外设库非常方便,只是没有花括号的缩进,我看着很难受。

初始化程序打开了各个外设以及定义了灰度值,灰度值需要在菜单栏里的——工具——机器视觉——阈值编辑器,选择帧缓冲图像,拖动滚动条,把红线与地面的背景分隔开。红线为白,其它为黑。(麻了,我又没存图,当时只留意存了十字线和巡线的。)

import sensor,image,lcd,time
import KPU as kpu
from Maix import FPIOA, GPIO
from fpioa_manager import fm
from board import board_info
from machine import UART
from Maix import GPIO

fm.register(17, fm.fpioa.GPIO0, force=True)
s_flag = GPIO(GPIO.GPIO0, GPIO.OUT)

flag=1

GRAYSCALE_THRESHOLD = [(87, 255)]    #划分的灰度值
THRESHOLD =(10, 34, -41, 74, -109, 127)   #摄像头垂直于地面

lcd.init(freq=15000000)
sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
#sensor.set_hmirror(0)   #镜像
#sensor.set_vflip(1)     #翻转
lcd.rotation(2)     #旋转方向 参数是0~3, 分别代表顺时针旋转 0度 90度 180度 270度
sensor.set_windowing((224, 224))
#sensor.set_brightness(2)
sensor.run(1)
clock = time.clock()

fm.register(23,fm.fpioa.UART2_TX)
uart_A = UART(UART.UART2, 115200, 8, None, 1, timeout=1000, read_buf_len=4096)

task = kpu.load("/sd/tt.kmodel")
f=open("anchors.txt","r")
anchor_txt=f.read()
L=[]
for i in anchor_txt.split(","):
    L.append(float(i))
anchor=tuple(L)
f.close()
a = kpu.init_yolo2(task, 0.6, 0.3, 5, anchor)

f=open("lable.txt","r")
labels_txt=f.read()
labels = labels_txt.split(",")
f.close()

死循环中我是通过标志位来切换两种模式的。首先上电先进入数字识别,第一次完成后进入巡线程序。后续切换是通过另一个主控发送数据改变的。
主控那边我简单说下吧,是通过闭环加入编码器计里程和十字线辅助判断每个路口,自加是第几个路口,停下来发信号给k210,在开始数字判断。
下面程序是老版本的,少写一些通信,数字在屏幕的左右正负偏差坐标即是数字在病房路口的位置,通过这个信息去PWM差速转向。
使用的PD进行转向控制,能精确锁住中线行驶。主控我认为用什么都可以,stc12啊,stc8都可以。之前自己做亚克力小车,加升压,在智能车赛道上一圈开环也能跑个16-18秒(没有加三岔路和圆环)。
这次比赛我用的是GD32的芯片,因为便宜,他们家封装的库还是挺好用的。

2021电赛F题数字识别和巡线部分

这题我选择后,第一天深夜我才确定用摄像头方案,以前没有试过巡线,凌晨3点从openmv那里速成,代码搬过来了。后续我想学学opencv。

我发现这道题有很多漏洞,我一个人做不完,所以我需要一些技巧。

[En]

I found that there are so many holes in this problem that I can’t finish it by myself, so I need some tricks.

在开环中直线行驶很稳定,但在十字路口会受到干扰,所以我加上了我的判断,忽略了左右两侧的白色区域作为直线。(在主控中,我根据我通过的十字路口和数字进行综合判断。)

[En]

Driving in a straight line in an open loop is very stable, but it will be disturbed at the crossroads, so I added my judgment and ignored the white areas on the left and right sides as a straight line. (in the main control, I make a comprehensive judgment based on the crossroads and numbers I have passed.)

def c_line():
    s_flag.value(1) #识别到数字后17口高电平s
    img = sensor.snapshot().binary([THRESHOLD])
    lcd.display(img)

    roi0=(80, 0,30, 30)     #给识别中线的位置标上兴趣框,并画下来,验证。
    most_pixels=0
    img.draw_rectangle(roi0, color =170)
    blob0 = img.find_blobs(GRAYSCALE_THRESHOLD, roi=roi0,pixels_threshold=100, area_threshold=100, merge=True)
    if blob0:
        for n in range(len(blob0)):
        #目标区域找到的颜色块(线段块)可能不止一个,找到最大的一个,作为本区域内的目标直线
           if blob0[n].pixels() > most_pixels:
               most_pixels = blob0[n].pixels()
               #merged_blobs[i][4]是这个颜色块的像素总数,如果此颜色块像素总数大于
               largest_blob = n
           R = 1

    else:
        R = 0

    roi1=(80, 200,30, 30)
    img.draw_rectangle(roi1, color =170)
    blob1 = img.find_blobs(GRAYSCALE_THRESHOLD, roi=roi1,pixels_threshold=100, area_threshold=100, merge=True)
    if blob1:
        for n in range(len(blob1)):
           if blob1[n].pixels() > most_pixels:
               most_pixels = blob1[n].pixels()
               largest_blob = n
           L = 1

    else:
        L = 0
    uart_A.write('L')
    uart_A.write(str(L))
    uart_A.write('Z')

    uart_A.write('R')
    uart_A.write(str(R))
    uart_A.write('X')

    line=img.get_regression([(20, 250)],roi=(0,0,210,210),x_srtide=2,y_srtide=1,robust=False)  #灰度 白黑
    if(line):
        rho_err = abs(line.rho())-img.width()/2   #piancha
        #print(int(rho_err))
        uart_A.write('P')
        uart_A.write(str(int(rho_err)))
        uart_A.write('S')
        if line.theta()>90:
            theta_err = line.theta()-180
        else:
            theta_err = line.theta()
        img.draw_line(line.line(), color = 127)

        print('R',R ,'L',L)

        #print(rho_err,line.magnitude(),theta_err)

下面部分是识别数字的,比较简单,都是框架。因为比赛自己做自己用的,串口没有用到多严格的格式,只加了头尾,确保传的数正确就好。主控那边我加了语音播报病房号,也算个额外加分点,这个屡试不爽~

def c_num():
    global flag
    img = sensor.snapshot()
    code = kpu.run_yolo2(task, img)
    print(anchor)
    a = lcd.display(img)
    if code:
        for i in code:
            a=img.draw_rectangle(i.rect(),(0,255,0),2)
            a = lcd.display(img)
            for i in code:
                lcd.draw_string(i.x()+45, i.y()-5, labels[i.classid()]+" "+'%.2f'%i.value(), lcd.WHITE,lcd.GREEN)
                #print(labels[i.classid()])
                #print('x',i.x(),y,'i.y()')
                if(labels[i.classid()]=='1'):
                    #print('1')
                    uart_A.write('N')
                    uart_A.write('1')
                    uart_A.write('M')

                if(labels[i.classid()]==' 2'):
                    uart_A.write('N')
                    uart_A.write('2')
                    uart_A.write('M')
                if(labels[i.classid()]==' 3'):
                    uart_A.write('N')
                    uart_A.write('3')
                    uart_A.write('M')
                if(labels[i.classid()]==' 4'):
                    uart_A.write('N')
                    uart_A.write('4')
                    uart_A.write('M')
                if(labels[i.classid()]==' 5'):
                    uart_A.write('N')
                    uart_A.write('5')
                    uart_A.write('M')
                if(labels[i.classid()]==' 6'):
                    uart_A.write('N')
                    uart_A.write('6')
                    uart_A.write('M')
                if(labels[i.classid()]==' 7'):
                    uart_A.write('N')
                    uart_A.write('7')
                    uart_A.write('M')
                if(labels[i.classid()]==' 8'):
                    uart_A.write('N')
                    uart_A.write('8')
                    uart_A.write('M')

        flag=0
        s_flag.value(0)
    else:
        a = lcd.display(img)
        #uart_A.write('N')
        #uart_A.write('0')
        #uart_A.write('M')

Python我并没有好好学过,几乎没写过几次,都是临时抱佛脚,代码写的很烂。 这次没有什么详细讲解,代码直接甩出去,(不负责的我,这次写完就不想补充完善了)留给大家自己慢慢研究了。我感觉除了那个灰度图像阈值需要自己调整外,其他没有什么太大问题。

嗯,这次比赛没有完赛材料,所以我没有参加创作和开源,也没有拿到奖金,但问题不大。我太懒了。

[En]

Well, there was no completion material in this competition, so I didn’t take part in the creation and open source, and I didn’t get a bonus, but it wasn’t a big problem. I was lazy.

创创的奖金比学校还高,学校还会再减奖金,因为今年获奖参赛的人很多,所以我笑了。这所学校里所有卑鄙小人的事情都会被摆出来,直到我的毕业答辩结束。在一个好的专业上它不如我好。

[En]

The bonus of Chuangchuang is even higher than that of the school, and the school will reduce the bonus again, because there are many people who won the prize and participated in the competition this year, so I laughed. The things of all kinds of mean people in this school will be laid out until my graduation defense is over. It’s not as good as me in a good specialty.

白嫖个便携式示波器挺好的。

2021电赛F题数字识别和巡线部分

继19年电赛在专科拿过一次国一后,没想到在本科这边又拿了一次。唯一一次遗憾的就是智能车了,但那个是外在因素,等完全毕业之后再谈。

Original: https://blog.csdn.net/zy19981110/article/details/122179873
Author: 随风飘零翼
Title: 2021电赛F题数字识别和巡线部分

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/10459/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

免费咨询
免费咨询
扫码关注
扫码关注
联系站长

站长Johngo!

大数据和算法重度研究者!

持续产出大数据、算法、LeetCode干货,以及业界好资源!

2022012703491714

微信来撩,免费咨询:xiaozhu_tec

分享本页
返回顶部