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

news2024/12/23 8:17:09

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

目录

  • 1.使用神经网络来进行识别
  • 2.使用模板匹配来进行识别
    • 1.1 将这种灰度图转化为黑白图检测更快更准
    • 1.2第一次进行识别记住给的数字
    • 1.3 第二次识别十字与T字后,再次识别数字判断左右转
  • 3.巡线代码的实现
  • 4.与主控芯片的通信
  • 5.完整代码

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

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

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

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

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

在这里插入图片描述
在这里插入图片描述

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

key = 0
t = 0
R = 0
text_contrast = ()
while(True):
    img = sensor.snapshot()
    img.binary([low_threshold], invert = 1)  # 根据像素是否在阈值列表 low_threshold中的阈值内,将图像中的所有像素设置为黑色
    img.draw_rectangle((50, 25, 60, 65), 0)   # 摄像头的感兴趣区域,在图像的中心一块,减少运算量;同时减少图像畸变带来的不准确性
    key = 0
```python


     # 在此识别最开始给与的数字,因为模板匹配自身的一些机制,使得容易出错,所以设计了一个循环
    # 只有五次识别的数字相同,车辆才可以前进
    if key < 6:
        for i in range(5):       # img.find_template的第二个参数范围是(0—1),越接近1,拍摄图片相似度越高,元组参数使得在规定范围内检测
            r1 = img.find_template(template1, 0.65, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r1:
                #img.draw_rectangle(r1, 0)
                R = 1
                text_contrast = r1
                #sending_data(R);
            r2 = img.find_template(template2, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r2:
                #img.draw_rectangle(r2, 0)
                R = 2
                text_contrast = r2
                #sending_data(1);
            r3 = img.find_template(template3, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r3:
                #img.draw_rectangle(r3, 0)
                R = 3
                text_contrast = r3
                #sending_data(1);
            r4 = img.find_template(template4, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r4:
                #img.draw_rectangle(r4, 0)
                R = 4
                text_contrast = r4
                #sending_data(1);
            r5 = img.find_template(template5, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r5:
                #img.draw_rectangle(r5, 0)
                R = 5
                text_contrast = r5
                #sending_data(1);
            r6 = img.find_template(template6, 0.70, (50, 25, 70, 65), step=4, search=SEARCH_EX)
            if r6:
                #img.draw_rectangle(r6, 0)
                R = 6
                text_contrast = r6
                #sending_data(1);
            r7 = img.find_template(template7, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r7:
                #img.draw_rectangle(r7, 0)
                R = 7
                text_contrast = r7
                #sending_data(1)
            r8 = img.find_template(template8, 0.65,  (50, 25, 60, 65),step=4, search=SEARCH_EX)
            if r8:
                #img.draw_rectangle(r8, 0)
                R = 8
                text_contrast = r8
                #sending_data(1);
            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

        #print(t)    # 测试时用于确定检测到的数
        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:                          # 实现十字路口和T字路口的识别,img.find_blobs()导入红线数组RED_line,检测很灵敏准确,所以没有使用多次检测功能
        blobs = img.find_blobs(RED_line, roi=r[0:4], merge=True)      #找到视野中的线,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:   # 用来确认检测到了十字路口和T字路口,之后进入再次比对数字模式
            h = 0
            for i in range(4):

                                                                        #这里g和上面的R是相同的
                if g == 1:
                    r1 = img.find_template(template1, 0.55, step=4, search=SEARCH_EX)
                    if r1:
                        img.draw_rectangle(r1, 0)
                        print("100")                               # 测试时连电脑使用:img.draw_rectangle(r1, 0);  print("100")
                        h = 100

                        if int(r1[0]+r1[2])/2  > 50:           # 通过获取检测图像的r1[0]检测图像的左上角横坐标;
                            print("右")                        # r1[2]图像的宽,通过判断是否超过图像的一半来确定左右转
                            sending_data(3);                   # 正常来说一半的分界线是80,但是因为摄像机的角度问题,使用50更为准确(摄像头偏右)
                        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()
                     #merged_blobs[i][4]是这个颜色块的像素总数,如果此颜色块像素总数大于
                     #most_pixels,则把本区域作为像素总数最大的颜色块。更新most_pixels和largest_blob
                    largest_blob = i
            img.draw_rectangle(blobs[largest_blob].rect())
            img.draw_rectangle((0,0,30, 30))
            #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]
            #计算centroid_sum,centroid_sum等于每个区域的最大颜色块的中心点的x坐标值乘本区域的权值

    center_pos = (centroid_sum / weight_sum)
       #中间公式

    deflection_angle = 0
    deflection_angle = -math.atan((center_pos-160)/120)
    #角度计算.80 60 分别为图像宽和高的一半,图像大小为QQVGA 160x120.
    #注意计算得到的是弧度值

    deflection_angle = math.degrees(deflection_angle)
    #将计算结果的弧度值转化为角度值

    A=deflection_angle
    uart_buf =int (A)+66
    print("Turn Angle: %d" % uart_buf)     #输出时强制转换类型为int
    sending_data(uart_buf);   #这个函数可以输出int型

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

4.与主控芯片的通信

uart = UART(3,115200)                          # 串口设置
uart.init(115200, bits=8, parity=None, stop=1)

template1 = image.Image("/1.pgm")               # 前8个是数字模板,后面两个是十字和T字
def sending_data(uart_buf):                      # 串口通信格式的设定
    global uart;
    data = ustruct.pack("<bbhhb",            #格式为俩个字符俩个短整型(2字节)
                   0x2C,                       #帧头1
                   0x12,                       #帧头2
                   uart_buf,
                   0x5B)
    uart.write(data);                          #必须要传入一个字节数组
clock = time.clock()

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

5.完整代码

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

# Untitled - By: 22358 - 周日 11月 7 2021
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)                         # 跳过前30帧使相机图像稳定下来

uart = UART(3,115200)                          # 串口设置
uart.init(115200, bits=8, parity=None, stop=1)

template1 = image.Image("/1.pgm")               # 前8个是数字模板,后面两个是十字和T字
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")
#template10_2 = image.Image("/10_2.pgm")

def sending_data(uart_buf):                      # 串口通信格式的设定
    global uart;
    data = ustruct.pack("<bbhhb",            #格式为俩个字符俩个短整型(2字节)
                   0x2C,                       #帧头1
                   0x12,                       #帧头2
                   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)
       ]
#roi代表三个取样区域,(x,y,w,h,weight),代表左上顶点(x,y)宽高分别为w和h的矩形,
#weight为当前矩形的权值。注意本例程采用的QQVGA图像大小为160x120,roi即把图像横分成三个矩形。
#三个矩形的阈值要根据实际情况进行调整,离机器人视野最近的矩形权值要最大,


weight_sum = 0               # 后面巡线需要使用的,权值和初始化
for r in ROIS:
    weight_sum += r[4]       # #计算权值和。遍历上面的三个矩形,r[4]即每个矩形的权值。



key = 0
t = 0
R = 0
text_contrast = ()
while(True):
    img = sensor.snapshot()
    img.binary([low_threshold], invert = 1)  # 根据像素是否在阈值列表 low_threshold中的阈值内,将图像中的所有像素设置为黑色
    img.draw_rectangle((50, 25, 60, 65), 0)   # 摄像头的感兴趣区域,在图像的中心一块,减少运算量;同时减少图像畸变带来的不准确性
    key = 0

     # 在此识别最开始给与的数字,因为模板匹配自身的一些机制,使得容易出错,所以设计了一个循环
    # 只有五次识别的数字相同,车辆才可以前进
    if key < 6:
        for i in range(5):       # img.find_template的第二个参数范围是(0—1),越接近1,拍摄图片相似度越高,元组参数使得在规定范围内检测
            r1 = img.find_template(template1, 0.65, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r1:
                #img.draw_rectangle(r1, 0)
                R = 1
                text_contrast = r1
                #sending_data(R);
            r2 = img.find_template(template2, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r2:
                #img.draw_rectangle(r2, 0)
                R = 2
                text_contrast = r2
                #sending_data(1);
            r3 = img.find_template(template3, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r3:
                #img.draw_rectangle(r3, 0)
                R = 3
                text_contrast = r3
                #sending_data(1);
            r4 = img.find_template(template4, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r4:
                #img.draw_rectangle(r4, 0)
                R = 4
                text_contrast = r4
                #sending_data(1);
            r5 = img.find_template(template5, 0.72, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r5:
                #img.draw_rectangle(r5, 0)
                R = 5
                text_contrast = r5
                #sending_data(1);
            r6 = img.find_template(template6, 0.70, (50, 25, 70, 65), step=4, search=SEARCH_EX)
            if r6:
                #img.draw_rectangle(r6, 0)
                R = 6
                text_contrast = r6
                #sending_data(1);
            r7 = img.find_template(template7, 0.55, (50, 25, 60, 65), step=4, search=SEARCH_EX)
            if r7:
                #img.draw_rectangle(r7, 0)
                R = 7
                text_contrast = r7
                #sending_data(1)
            r8 = img.find_template(template8, 0.65,  (50, 25, 60, 65),step=4, search=SEARCH_EX)
            if r8:
                #img.draw_rectangle(r8, 0)
                R = 8
                text_contrast = r8
                #sending_data(1);
            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

        #print(t)    # 测试时用于确定检测到的数
        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:                          # 实现十字路口和T字路口的识别,img.find_blobs()导入红线数组RED_line,检测很灵敏准确,所以没有使用多次检测功能
        blobs = img.find_blobs(RED_line, roi=r[0:4], merge=True)      #找到视野中的线,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:   # 用来确认检测到了十字路口和T字路口,之后进入再次比对数字模式
            h = 0
            for i in range(4):

                                                                        #这里g和上面的R是相同的
                if g == 1:
                    r1 = img.find_template(template1, 0.55, step=4, search=SEARCH_EX)
                    if r1:
                        img.draw_rectangle(r1, 0)
                        print("100")                               # 测试时连电脑使用:img.draw_rectangle(r1, 0);  print("100")
                        h = 100

                        if int(r1[0]+r1[2])/2  > 50:           # 通过获取检测图像的r1[0]检测图像的左上角横坐标;
                            print("右")                        # r1[2]图像的宽,通过判断是否超过图像的一半来确定左右转
                            sending_data(3);                   # 正常来说一半的分界线是80,但是因为摄像机的角度问题,使用50更为准确(摄像头偏右)
                        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()
                     #merged_blobs[i][4]是这个颜色块的像素总数,如果此颜色块像素总数大于
                     #most_pixels,则把本区域作为像素总数最大的颜色块。更新most_pixels和largest_blob
                    largest_blob = i
            img.draw_rectangle(blobs[largest_blob].rect())
            img.draw_rectangle((0,0,30, 30))
            #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]
            #计算centroid_sum,centroid_sum等于每个区域的最大颜色块的中心点的x坐标值乘本区域的权值

    center_pos = (centroid_sum / weight_sum)
       #中间公式

    deflection_angle = 0
    deflection_angle = -math.atan((center_pos-160)/120)
    #角度计算.80 60 分别为图像宽和高的一半,图像大小为QQVGA 160x120.
    #注意计算得到的是弧度值

    deflection_angle = math.degrees(deflection_angle)
    #将计算结果的弧度值转化为角度值

    A=deflection_angle
    uart_buf =int (A)+66
    print("Turn Angle: %d" % uart_buf)     #输出时强制转换类型为int
    sending_data(uart_buf);   #这个函数可以输出int型

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/995657.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Idea上传gitee注意事项,push reject错误

一、 你在项目所在文件夹的空白处&#xff0c;鼠标右键&#xff0c;点击git bash here 会自动进入该目录下 二、 如果你遇到push reject 输入下面的命令&#xff1a; git pull origin master –allow-unrelated-historiesgit push -u origin master -f再次push就好了。 三、 …

教你怎么爬元气桌面的壁纸和视频

开发语言&#xff1a;我大前端必备的nodejs 看成果先&#xff1a; 这次爬下来的是手机端视频壁纸&#xff0c;共848个视频 -----------------------------------下边正式开始---------------------------------- 1、用fiddler抓包&#xff0c;查看接口地址 接口地址为&#…

springboot~自定义favicon加载问题

影响自定义favicon加载的原因 1、浏览器缓存问题2、由于favicon图标是在一个session会话中&#xff0c;所以需要关闭重开浏览器3、favicon源文件格式问题 1、浏览器缓存问题 清空浏览器缓存&#xff0c;或者是在network请求中停用缓存 2、由于favicon图标是在一个session会话中…

18 矩阵置0

矩阵置0 题解1 首行首列做标志记录&#xff08;原地改数组&#xff09;题解2 位计算 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 提示&#xff1a; m matrix.lengthn matrix[0].length1 …

210. 课程表 II

文章目录 Tag题目来源题目解读解题思路方法一&#xff1a;拓扑排序 写在最后 Tag 【拓扑排序】 题目来源 210. 课程表 II 题目解读 在选修某些课程之前需要先学习某些课程&#xff0c;先学习的课程有数组 prerequisites 给出&#xff0c;其中 prerequisites[i] [ai, bi] 表…

机器学习入门教学——交叉验证

1、简介 交叉验证是在机器学习建立模型和验证模型参数时常用的办法&#xff0c;一般被用于评估一个机器学习模型的表现。更多的情况下&#xff0c;我们也用交叉验证来进行模型选择。【注】在训练模型时&#xff0c;为了提高模型的质量&#xff0c;我们会将数据集划分为训练集、…

【算法与数据结构】501、LeetCode二叉搜索树中的众数

文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析&#xff1a;根据前面几篇文章98、LeetCode验证二叉搜索树、530、LeetCode二叉搜索树的最小绝对差。我们知道二叉搜…

大数据分析案例-基于随机森林算法构建二手房价格预测模型

🤵‍♂️ 个人主页:@艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞👍🏻 收藏 📂加关注+ 喜欢大数据分析项目的小伙伴,希望可以多多支持该系列的其他文章 大数据分析案例合集…

钟爱墨西哥市场?长城汽车官宣进入,已启动本地化生产研究和规划

长城汽车公司宣布正式进入墨西哥市场&#xff0c;并以“Hello Tomorrow”为主题发布了GWM品牌暨哈弗H6 HEV车型。这标志着长城汽车在墨西哥市场的运营开始&#xff0c;公司已启动本地化生产的研究和规划工作。 据悉&#xff0c;长城汽车公司已在拉丁美洲开设24家经销商&#xf…

代码随想录第45天|70. 爬楼梯,322. 零钱兑换,279.完全平方数

70. 爬楼梯 开始按感觉做 class Solution {public int climbStairs(int n) {//第一版按感觉做//dp[i]爬到第i个台阶的方法数int[] dpnew int[n1];//初始化dp[0]1;dp[1]1;for(int i2;i<n;i){dp[i]dp[i-1]dp[i-2];}return dp[n];} } 改进-用完全背包做 这是背包里求排列问…

关于点光源踩坑的一点总结

1 点光源不能单独作用域几何体。需要有其他光源的辅助 2 如果你添加了点光源&#xff0c;同时设置的是默认值&#xff0c;那么界面上很可能展示的几何体没有任何光源效 3对于点光源特别注意它的属性光照距的衰退量也就是decay。其默认值为2.&#xff0c;如果我们设置一个较小…

国产编程IDE到底败在哪里?E4A安卓开发,猎码,易语言,火山

最新发现&#xff0c;原来的猎码下载链接都找不到了&#xff0c;再也没有猎码的影子了。 猎码的好处是Jdk,ADK等一起打包了解压自动配置好环境;编绎时各种出错情况提示不人性化&#xff0c;比较难用。 最近出了一款Amix&#xff0c;说是支持跨平台,安卓APP,小程序开发等功能。…

深度思考ES面经

1 推荐文章 2万字详解&#xff0c;吃透 Elasticsearch 2 什么是倒排索引&#xff0c;为什么这么叫&#xff1f; 倒排索引&#xff08;Inverted Index&#xff09;是一种为快速全文搜索而设计的数据结构。它被广泛应用于搜索引擎&#xff0c;其中 Elasticsearch&#xff08;简…

报错处理:Docker镜像无法启动

报错环境&#xff1a; Linux Docker 具体报错&#xff1a; standard_init_linux.go:211: exec user process caused "no such file or directory" 排错思路&#xff1a; 当尝试启动Docker镜像时&#xff0c;如果出现 no such file or directory 的错误&#xff0c;可…

简单记录一下Splunk ES 升级

1: 背景: 现在有些app 产品对splunk ES (enterprise security) 的版本有要求,这个就要求splunk ES 随着Splunk enterprise 也一起升级,下面先列一下各个版本的兼容: Splunk products version compatibility matrix - Splunk Documentation 下面列出的8.2.11 的版本: 2:…

Electron和vue3集成

本篇我们仅实现Electron和vue3通过先运行起vue3项目&#xff0c;再将vue3的url地址交由Electron打开的方案&#xff0c;仅由Electron在vue3项目上套一层壳来达到脱离本机浏览器运行目的 1、参考快速上手 | Vue.js搭建起vue3初始项目 npm install -g vue npm install -g vue/c…

【拯救大学生计划】:我做了一个QQ分组神器

文章目录 &#x1f60a;前言&#x1f603;使用教程第一步&#xff1a;获取好友网名和备注第二步&#xff1a;文件设置第三步&#xff1a;自动选择好友 &#x1f606;停顿问题解决方法&#x1f604;结束语&#x1f4da;资源 专栏Python零基础入门篇&#x1f525;Python网络蜘蛛&…

【改进算法】【IHAOAVOA】天鹰优化算法和非洲秃鹫混合优化算法

目录 1 主要内容 2 部分代码 3 程序结果 4 下载链接 1 主要内容 该程序复现《IHAOAVOA: An improved hybrid aquila optimizer and African vultures optimization algorithm for global optimization problems》&#xff0c;天鹰优化算法&#xff08;AO&#xff09;和非洲…

智慧工地: 建筑施工一体化信息管理系统源码

智慧工地管理云平台系统是一种利用人工智能和物联网技术来监测和管理建筑工地的系统。它可以通过感知设备、数据处理和分析、智能控制等技术手段&#xff0c;实现对工地施工、设备状态、人员安全等方面的实时监控和管理。 一、智慧工地管理系统让工程施工智能化 1、内容全面&a…

区块链技术与应用 - 学习笔记3【比特币数据结构】

大家好&#xff0c;我是比特桃。本系列笔记只专注于探讨研究区块链技术原理&#xff0c;不做其他违反相关规定的讨论。 区块链技术已被纳入国家十四五规划&#xff0c;在“加快数字发展 建设数字中国”篇章中&#xff0c;区块链被列为“十四五”七大数字经济重点产业之一&#…