视觉识别数字、十字路口和T字路口,巡线于一体的基于openmv的解决方案(2021年电赛f题)

普通二本生(大二)没获奖,因为驱动方面和视觉协同问题没有做好(驱动方面跑太快,速度降不下来)只跑了最初级的,这个文章就是去记录一下我的成长过程吧。

目录

1.使用神经网络来进行识别

最开始我的视觉方案,是通过训练神经网络实现识别数字的功能。但是训练出来却不能使用,也不知道是我的问题还是openmv的太老了不兼容。训练出来的包放入openmv中,openmv无法正常运行。(我使用的产品图片会在之后上传,在家没有硬件图),具体教程:https://book.openmv.cc/example/25-Machine-Learning/nn-lenet.html

2.使用模板匹配来进行识别

于是想到了是否可以通过模板匹配来确定数字,模板匹配教程openmv官网上有。采用他们的方法,我首先尝试了一下,但是普通的灰色图片。因为我们的版本openmv只支持sensor.QQVGA: 160×120
拍摄出来的照片普遍偏暗,进行识别时识别效率太低。于是我们想是否可以将图片二值化。这样黑与白,对比非常鲜明,同时将黑白图导到画图工具里面通过修图软件将每一个色块非黑即白识别效率更高。结果也非常好,识别率大约达到了百分之八九十。但是进行比赛的话,一旦出错的话满盘皆失。当时想到了可以通过。让摄像头进行多次对比,只有当多次对比,结果相同时才将信息,通过串口传输给32。通过调整次数。实现接近100%的识别。

1.1 将这种灰度图转化为黑白图检测更快更准

视觉识别数字、十字路口和T字路口,巡线于一体的基于openmv的解决方案(2021年电赛f题)
视觉识别数字、十字路口和T字路口,巡线于一体的基于openmv的解决方案(2021年电赛f题)

; 1.2第一次进行识别记住给的数字

key = 0
t = 0
R = 0
text_contrast = ()
while(True):
    img = sensor.snapshot()
    img.binary([low_threshold], invert = 1)
    img.draw_rectangle((50, 25, 60, 65), 0)
    key = 0
`python

    if key < 6:
        for i in range(5):
            r1 = img.find_template(template1, 0.65, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r1:

                R = 1
                text_contrast = r1

            r2 = img.find_template(template2, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r2:

                R = 2
                text_contrast = r2

            r3 = img.find_template(template3, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r3:

                R = 3
                text_contrast = r3

            r4 = img.find_template(template4, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r4:

                R = 4
                text_contrast = r4

            r5 = img.find_template(template5, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r5:

                R = 5
                text_contrast = r5

            r6 = img.find_template(template6, 0.70, (50, 25, 70, 65), step=4, search=SEARCH_EX)
            if r6:

                R = 6
                text_contrast = r6

            r7 = img.find_template(template7, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r7:

                R = 7
                text_contrast = r7

            r8 = img.find_template(template8, 0.65,  (50, 25, 60, 65),step=4, search=SEARCH_EX)
            if r8:

                R = 8
                text_contrast = r8

            if t == 0:
                t = R
                continue
            elif t == R:
                key = key + 1
                continue
            else:
                break
        if key == 5:
            img.draw_rectangle(text_contrast, 0)
            sending_data(1);
        else:
            continue

        g = t
        break

当时其实我们考虑过另一种方案。通过各个角度拍摄图片来进行匹配。但是这样的话需要更多的图片,且运行效率变慢。同时不同方向的图片也会出现错误。比如2,5,8很容易混淆机器。所以这个方案就被放弃了。

1.3 第二次识别十字与T字后,再次识别数字判断左右转

十字路口同样也是模板匹配。因为比赛规则是一开始先让摄像头看一下,需要去的病房也就是数字。所以我们最开始的设计是将感兴趣区域设计为摄像头的最中心。在运行完一次之后,我们会运行之后的循环。当检测到十字路口或T字路口的时候,进入新的数字检测部分,这个新的数字检测部分的话,范围是整个图像(左侧和右侧的确定是通过将左上角x轴坐标+宽度除以2,获取到需要的数字是在左侧范围还是右侧范围)。通过检测数字与第1次的数字进行比对,从而确定左转和右转。这个的话就需要与32方面相配合,因为你不知道最后会刹车停在哪里。转弯过后,这个对比数字的程序一直在运行,因为最上侧的两个是两个拐弯口,但是视觉因为程序过多,运行速度还是偏慢,只有30左右,还有就是转弯的时候容易看到黑线停止,因此黑线停止是由光电传感器实现(视觉检测黑线,距离太近了,车无法停下来)。

while (True):
    clock.tick()
    img = sensor.snapshot()
    centroid_sum = 0
    img = sensor.snapshot()
    img.binary([low_threshold], invert = 1)

    for r in ROIS:
        blobs = img.find_blobs(RED_line, roi=r[0:4], merge=True)
        r9 = img.find_template(template9, 0.65, step=4, search=SEARCH_EX)
        if r9:
            img.draw_rectangle(r9, 0)
            print("9")
            sending_data(2);
            key = 10
        r10 = img.find_template(template10, 0.65, step=4, search=SEARCH_EX)
        if r10:
            img.draw_rectangle(r10, 0)
            print("10")
            sending_data(2);
            key = 10

        if key > 9:
            h = 0
            for i in range(4):

                if g == 1:
                    r1 = img.find_template(template1, 0.55, step=4, search=SEARCH_EX)
                    if r1:
                        img.draw_rectangle(r1, 0)
                        print("100")
                        h = 100

                        if int(r1[0]+r1[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 2:
                    r2 = img.find_template(template2, 0.55, step=4, search=SEARCH_EX)
                    if r2:
                        img.draw_rectangle(r2, 0)
                        h = 200
                        print("200")

                        if int(r2[0] + r2[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 3:
                    r3 = img.find_template(template3, 0.55, step=4, search=SEARCH_EX)
                    if r3:
                        img.draw_rectangle(r3, 0)
                        h = 300
                        print("300")
                        if int(r3[0]+r3[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 4:
                    r4 = img.find_template(template4, 0.55, step=4, search=SEARCH_EX)
                    if r4:
                        img.draw_rectangle(r4, 0)
                        h = 400
                        print("400")
                        if int(r4[0]+r4[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 5:
                    r5 = img.find_template(template5, 0.55, step=4, search=SEARCH_EX)
                    if r5:
                        img.draw_rectangle(r5, 0)
                        h = 500
                        print("500")
                        if int(r5[0]+r5[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 6:
                    r6 = img.find_template(template6, 0.55, step=4, search=SEARCH_EX)
                    if r6:
                        img.draw_rectangle(r6, 0)
                        h = 600
                        print("600")
                        if int(r6[0]+r6[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 7:
                    r7 = img.find_template(template7, 0.55, step=4, search=SEARCH_EX)
                    if r7:
                        img.draw_rectangle(r7, 0)
                        h = 700
                        print("700")
                        if int(r7[0]+r7[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 8:
                    r8 = img.find_template(template8, 0.55, step=4, search=SEARCH_EX)
                    if r8:
                        img.draw_rectangle(r8, 0)
                        h = 800
                        print("800")
                        if int(r8[0]+r8[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if h:
                    key = key - 1
                    continue
                else:
                    break

3.巡线代码的实现

寻红线代码是借鉴了https://blog.csdn.net/weixin_43679759/article/details/88205708?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522162462579216780269848930%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=162462579216780269848930&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-88205708.pc_search_result_control_group&utm_term=openmv%E5%BE%AA%E8%BF%B9%E5%B0%8F%E8%BD%A6&spm=1018.2226.3001.4187的巡线代码,将黑色线改为红色线,同时加入了纠正功能当左侧或右侧出现黑线时,它会根据方位来左右转。来实现此功能。因为这类的代码是最简洁的,运行速度也是最快的,而对于这个硬件。本身的处理能力是有限的,需要尽可能的简洁代码减少计算,以达到高效的运行效率。
代码如下:

 if blobs:
            most_pixels = 0
            largest_blob = 0
            for i in range(len(blobs)):

                if blobs[i].pixels() > most_pixels:
                    most_pixels = blobs[i].pixels()

                    largest_blob = i
            img.draw_rectangle(blobs[largest_blob].rect())
            img.draw_rectangle((0,0,30, 30))

            img.draw_cross(blobs[largest_blob].cx(),
                           blobs[largest_blob].cy())
            centroid_sum += blobs[largest_blob].cx() * r[4]

    center_pos = (centroid_sum / weight_sum)

    deflection_angle = 0
    deflection_angle = -math.atan((center_pos-160)/120)

    deflection_angle = math.degrees(deflection_angle)

    A=deflection_angle
    uart_buf =int (A)+66
    print("Turn Angle: %d" % uart_buf)
    sending_data(uart_buf);

代码不完整,给大家看个原理,文章最后完整代码。

4.与主控芯片的通信

uart = UART(3,115200)
uart.init(115200, bits=8, parity=None, stop=1)

template1 = image.Image("/1.pgm")
def sending_data(uart_buf):
    global uart;
    data = ustruct.pack(",
                   0x2C,
                   0x12,
                   uart_buf,
                   0x5B)
    uart.write(data);
clock = time.clock()

后面只要调用sending_data()函数就可以发送数据了。

5.完整代码

最后摄像头和机器真的安在一起进行实验时。发现机器车跑得过快。与硬件部的同学商量了一下。他们说没有无刷电机,速度最慢就是这样。机器车的速度非常快跑个直线大约20秒左右。识别速度跟不上,他们也降不了速。只能将检测到黑色停止转向的功能去除。加入光电传感器来实现检测黑色停止转向,以提高视觉检测效率。
代码如下:


import sensor, image, time, math
from image import SEARCH_EX, SEARCH_DS
from pyb import LED
from pyb import UART
import json
import ustruct
sensor.reset()
sensor.set_contrast(1)
sensor.set_gainceiling(16)
sensor.set_framesize(sensor.QQVGA)
sensor.set_pixformat(sensor.GRAYSCALE)
sensor.set_auto_gain(False)
sensor.set_auto_whitebal(False)
sensor.skip_frames(30)

uart = UART(3,115200)
uart.init(115200, bits=8, parity=None, stop=1)

template1 = image.Image("/1.pgm")
template2 = image.Image("/2.pgm")
template3 = image.Image("/3.pgm")
template4 = image.Image("/4.pgm")
template5 = image.Image("/5.pgm")
template6 = image.Image("/6.pgm")
template7 = image.Image("/7.pgm")
template8 = image.Image("/8.pgm")
template9 = image.Image("/9.pgm")
template10 = image.Image("/10.pgm")
template10_1 = image.Image("/10_1.pgm")

def sending_data(uart_buf):
    global uart;
    data = ustruct.pack(",
                   0x2C,
                   0x12,
                   uart_buf,
                   0x5B)
    uart.write(data);
clock = time.clock()

low_threshold = (0, 66)
RED_line = [(0, 64)]
ROIS = [
        (0, 100, 160, 40, 0.7),
        (0, 60, 160, 40, 0.3),
        (0, 20, 160, 40, 0.1)
       ]

weight_sum = 0
for r in ROIS:
    weight_sum += r[4]

key = 0
t = 0
R = 0
text_contrast = ()
while(True):
    img = sensor.snapshot()
    img.binary([low_threshold], invert = 1)
    img.draw_rectangle((50, 25, 60, 65), 0)
    key = 0

    if key < 6:
        for i in range(5):
            r1 = img.find_template(template1, 0.65, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r1:

                R = 1
                text_contrast = r1

            r2 = img.find_template(template2, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r2:

                R = 2
                text_contrast = r2

            r3 = img.find_template(template3, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r3:

                R = 3
                text_contrast = r3

            r4 = img.find_template(template4, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r4:

                R = 4
                text_contrast = r4

            r5 = img.find_template(template5, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r5:

                R = 5
                text_contrast = r5

            r6 = img.find_template(template6, 0.70, (50, 25, 70, 65), step=4, search=SEARCH_EX)
            if r6:

                R = 6
                text_contrast = r6

            r7 = img.find_template(template7, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r7:

                R = 7
                text_contrast = r7

            r8 = img.find_template(template8, 0.65,  (50, 25, 60, 65),step=4, search=SEARCH_EX)
            if r8:

                R = 8
                text_contrast = r8

            if t == 0:
                t = R
                continue
            elif t == R:
                key = key + 1
                continue
            else:
                break
        if key == 5:
            img.draw_rectangle(text_contrast, 0)
            sending_data(1);
        else:
            continue

        g = t
        break

while (True):
    clock.tick()
    img = sensor.snapshot()
    centroid_sum = 0
    img = sensor.snapshot()
    img.binary([low_threshold], invert = 1)

    for r in ROIS:
        blobs = img.find_blobs(RED_line, roi=r[0:4], merge=True)
        r9 = img.find_template(template9, 0.65, step=4, search=SEARCH_EX)
        if r9:
            img.draw_rectangle(r9, 0)
            print("9")
            sending_data(2);
            key = 10
        r10 = img.find_template(template10, 0.65, step=4, search=SEARCH_EX)
        if r10:
            img.draw_rectangle(r10, 0)
            print("10")
            sending_data(2);
            key = 10

        if key > 9:
            h = 0
            for i in range(4):

                if g == 1:
                    r1 = img.find_template(template1, 0.55, step=4, search=SEARCH_EX)
                    if r1:
                        img.draw_rectangle(r1, 0)
                        print("100")
                        h = 100

                        if int(r1[0]+r1[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 2:
                    r2 = img.find_template(template2, 0.55, step=4, search=SEARCH_EX)
                    if r2:
                        img.draw_rectangle(r2, 0)
                        h = 200
                        print("200")

                        if int(r2[0] + r2[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 3:
                    r3 = img.find_template(template3, 0.55, step=4, search=SEARCH_EX)
                    if r3:
                        img.draw_rectangle(r3, 0)
                        h = 300
                        print("300")
                        if int(r3[0]+r3[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 4:
                    r4 = img.find_template(template4, 0.55, step=4, search=SEARCH_EX)
                    if r4:
                        img.draw_rectangle(r4, 0)
                        h = 400
                        print("400")
                        if int(r4[0]+r4[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 5:
                    r5 = img.find_template(template5, 0.55, step=4, search=SEARCH_EX)
                    if r5:
                        img.draw_rectangle(r5, 0)
                        h = 500
                        print("500")
                        if int(r5[0]+r5[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 6:
                    r6 = img.find_template(template6, 0.55, step=4, search=SEARCH_EX)
                    if r6:
                        img.draw_rectangle(r6, 0)
                        h = 600
                        print("600")
                        if int(r6[0]+r6[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 7:
                    r7 = img.find_template(template7, 0.55, step=4, search=SEARCH_EX)
                    if r7:
                        img.draw_rectangle(r7, 0)
                        h = 700
                        print("700")
                        if int(r7[0]+r7[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if g == 8:
                    r8 = img.find_template(template8, 0.55, step=4, search=SEARCH_EX)
                    if r8:
                        img.draw_rectangle(r8, 0)
                        h = 800
                        print("800")
                        if int(r8[0]+r8[2])/2  > 50:
                            print("右")
                            sending_data(3);
                        else:
                            print("左")
                            sending_data(4);
                if h:
                    key = key - 1
                    continue
                else:
                    break

        if blobs:
            most_pixels = 0
            largest_blob = 0
            for i in range(len(blobs)):

                if blobs[i].pixels() > most_pixels:
                    most_pixels = blobs[i].pixels()

                    largest_blob = i
            img.draw_rectangle(blobs[largest_blob].rect())
            img.draw_rectangle((0,0,30, 30))

            img.draw_cross(blobs[largest_blob].cx(),
                           blobs[largest_blob].cy())
            centroid_sum += blobs[largest_blob].cx() * r[4]

    center_pos = (centroid_sum / weight_sum)

    deflection_angle = 0
    deflection_angle = -math.atan((center_pos-160)/120)

    deflection_angle = math.degrees(deflection_angle)

    A=deflection_angle
    uart_buf =int (A)+66
    print("Turn Angle: %d" % uart_buf)
    sending_data(uart_buf);

Original: https://blog.csdn.net/Meat_buns_dogs/article/details/126145510
Author: Meat_buns_dogs
Title: 视觉识别数字、十字路口和T字路口,巡线于一体的基于openmv的解决方案(2021年电赛f题)

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

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

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球