2023电赛E题视觉部分OpenMV

电赛E题视觉基础部分:

      OpenMV固定于舵机云台前,屏幕画面置于镜头前,OpenMV将屏幕中数据信息,包括原点位置,激光点位置,A4靶纸边框位置利用串口传给主控芯片。(完整代码直接见第四部分)

一、OpenMV串口部分代码

        初始化OpenMV串口3,利用数据包一次发送十个数据给主控,包括五个坐标点——激光点坐标,靶值四个角点坐标。当需要发送数据时,只要在程序中引用此函数即可。

import sensor, image, time
import ustruct
from pyb import UART,LED

uart = UART(3,9600)
uart.init(9600, bits=8, parity=None, stop=1)  # 开启OpenMV串口3  波特率为9600,8位,一位停止位

def sending_data(rx,ry,cx,cy,cw,ch,xx,xy,xw,xh):  # 定义发送数据包函数  包头位“FF”,包尾为“FE”  
    global uart;                              # 数据包中有十个数据
    data = ustruct.pack("<bhhhhhhhhb",        # 分别为激光点中心坐标以及靶纸corner坐标
                        0xFF,
                        int(rx),
                        int(ry),
                        int(cx),
                        int(cy),
                        int(cw),
                        int(ch),
                        int(xx),
                        int(xy),
                        int(xw),
                        int(xh),
                        0xFE)
    uart.write(data);

二、识别激光点

        利用OpenMV 自带的寻找色块的函数,寻找画面中最大激光点阈值的色块并读取中心坐标。3

2.1 阈值设置

        首先进行阈值的选择、ROI的选择以及曝光时间选择。(所给的数据均为比赛时我用的数据,请自行调整)

#****************************阈值调整*******************************
area=(45, 2, 200, 198)
red=(88, 100, -16, 22, -128, 127)  

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_auto_whitebal(True)
sensor.set_auto_gain(False)
sensor.skip_frames(time = 2000)
sensor.set_vflip(True)
sensor.set_hmirror(True)
#****************************曝光时间*******************************
sensor.set_auto_exposure(False,4500)

clock = time.clock()

2.2 色块识别

while(True)
    clock.tick()
    img = sensor.snapshot().lens_corr(strength = 1.6, zoom = 1.0)

    red_point= img.find_blobs([red])
    if red_point:
        r= red_point[0]
        img.draw_rectangle(r[0:4],color=(0,0,0)) # rect
        rx=r[5]
        ry=r[6]

三、识别A4靶纸上电工胶带角点

3.1 方法一 :直线交点法

        用OpenMV自带的寻找直线的函数在ROI中找到所有的直线,然后通过判断所寻找的直线数是否为四进行下一步求交点。

#*****************************line_threshold**********************
line_threshold=2500
rect_threshold=10000

while(True):
    clock.tick()
    img = sensor.snapshot().lens_corr(strength = 1.6, zoom = 1.0)

    red_point= img.find_blobs([red])
    if red_point:
        r= red_point[0]
        img.draw_rectangle(r[0:4],color=(0,0,0)) # rect
        rx=r[5]
        ry=r[6]
        #print(rx,ry)


#******************************************************************lines*****************
    lines = img.find_lines(roi=area, threshold=line_threshold)
    i=0
    if len(lines)==4 :

        如果识别到四条直线,依次两两直线遍历,是否夹角大于一定值,判断直线是否相交,从而求出交点坐标 。

    if len(lines)==4 :
        theta0=lines[0].theta()
        theta1=lines[1].theta()
        theta2=lines[2].theta()
        theta3=lines[3].theta()
        for line in lines:
            img.draw_line(line.line(),color=[255,0,0])
        if abs(theta0-theta1)>45:
            a[i]=calculate_intersection(lines[0],lines[1])[0]
            i=i+1
            a[i]=calculate_intersection(lines[0],lines[1])[1]
            i=i+1
        if abs(theta0-theta2)>45:
            a[i]=calculate_intersection(lines[0],lines[2])[0]
            i=i+1
            a[i]=calculate_intersection(lines[0],lines[2])[1]
            i=i+1
        if abs(theta0-theta3)>45:
            a[i]=calculate_intersection(lines[0],lines[3])[0]
            i=i+1
            a[i]=calculate_intersection(lines[0],lines[3])[1]
            i=i+1
        if abs(theta1-theta2)>45:
            a[i]=calculate_intersection(lines[2],lines[1])[0]
            i=i+1
            a[i]=calculate_intersection(lines[2],lines[1])[1]
            i=i+1
        if abs(theta1-theta3)>45:
            a[i]=calculate_intersection(lines[1],lines[3])[0]
            i=i+1
            a[i]=calculate_intersection(lines[1],lines[3])[1]
            i=i+1
        if abs(theta3-theta2)>45:
            a[i]=calculate_intersection(lines[2],lines[3])[0]
            i=i+1
            a[i]=calculate_intersection(lines[2],lines[3])[1]
            i=i+1

     其中求交点的坐标函数如下:

def calculate_intersection(line1, line2):
    '''
    计算两条线的交点
    '''
    a1 = line1.y2() - line1.y1()
    b1 = line1.x1() - line1.x2()
    c1 = line1.x2()*line1.y1() - line1.x1()*line1.y2()

    a2 = line2.y2() - line2.y1()
    b2 = line2.x1() - line2.x2()
    c2 = line2.x2() * line2.y1() - line2.x1()*line2.y2()

    if (a1 * b2 - a2 * b1) != 0 and (a2 * b1 - a1 * b2) != 0:
        cross_x = int((b1*c2-b2*c1)/(a1*b2-a2*b1))
        cross_y = int((c1*a2-c2*a1)/(a1*b2-a2*b1))
        return (cross_x, cross_y)
    return None

3.2 方法二 :   矩形角点法

        利用OpenMV自带的寻找矩形函数。但需要注意阈值以及ROI,可以设置识别矩形的长宽范围筛选出我们所需要的那个矩形,从而记录角点坐标。

while(True):
    clock.tick()
    img = sensor.snapshot()

# -----矩形框部分-----
    # 在图像中寻找矩形
    for r in img.find_rects(threshold = 10000):
        # 判断矩形边长是否符合要求
        if r.w() > 20 and r.h() > 20:
            # 在屏幕上框出矩形
            img.draw_rectangle(r.rect(), color = (255, 0, 0), scale = 4)
            # 获取矩形角点位置
            corner = r.corners()
            # 在屏幕上圈出矩形角点
            img.draw_circle(corner[0][0], corner[0][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
            img.draw_circle(corner[1][0], corner[1][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
            img.draw_circle(corner[2][0], corner[2][1], 5, color = (0, 0, 255), thickness = 2, fill = False)
            img.draw_circle(corner[3][0], corner[3][1], 5, color = (0, 0, 255), thickness = 2, fill = False)

        # 打印四个角点坐标, 角点1的数组是corner[0], 坐标就是(corner[0][0],corner[0][1])
        # 角点检测输出的角点排序每次不一定一致,矩形左上的角点有可能是corner0,1,2,3其中一个
            corner1_str = f"corner1 = ({corner[0][0]},{corner[0][1]})"
            corner2_str = f"corner2 = ({corner[1][0]},{corner[1][1]})"
            corner3_str = f"corner3 = ({corner[2][0]},{corner[2][1]})"
            corner4_str = f"corner4 = ({corner[3][0]},{corner[3][1]})"
            print(corner1_str + "\n" + corner2_str + "\n" + corner3_str + "\n" + corner4_str)

四、完整程序

这里只给方法一的完整代码,方法二自行替换即可。

import sensor, image, time
import ustruct
from pyb import UART,LED

#****************************阈值调整*******************************
area=(45, 2, 200, 198)
red=(88, 100, -16, 22, -128, 127)  #only red

sensor.reset()
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_auto_whitebal(True)
sensor.set_auto_gain(False)
sensor.skip_frames(time = 2000)
sensor.set_vflip(True)
sensor.set_hmirror(True)
#****************************曝光时间*******************************
sensor.set_auto_exposure(False,4500)

clock = time.clock()
#*****************************line_threshold**********************
line_threshold=2500
rect_threshold=10000

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

def calculate_intersection(line1, line2):
    '''
    计算两条线的交点
    '''
    a1 = line1.y2() - line1.y1()
    b1 = line1.x1() - line1.x2()
    c1 = line1.x2()*line1.y1() - line1.x1()*line1.y2()

    a2 = line2.y2() - line2.y1()
    b2 = line2.x1() - line2.x2()
    c2 = line2.x2() * line2.y1() - line2.x1()*line2.y2()

    if (a1 * b2 - a2 * b1) != 0 and (a2 * b1 - a1 * b2) != 0:
        cross_x = int((b1*c2-b2*c1)/(a1*b2-a2*b1))
        cross_y = int((c1*a2-c2*a1)/(a1*b2-a2*b1))
        return (cross_x, cross_y)
    return None

def sending_data(rx,ry,cx,c):
    global uart;
    data = ustruct.pack("<bhhhhhhhhb",
                        0xFF,
                        int(rx),
                        int(ry),
                        int(cx),
                        int(cy),
                        int(cw),
                        int(ch),
                        int(xx),
                        int(xy),
                        int(xw),
                        int(xh),
                        0xFE)
    uart.write(data);
cx=0
cy=0
rx=0
ry=0
a=[0,0,0,0,0,0,0,0,0,0]

while(True):
    clock.tick()
    img = sensor.snapshot().lens_corr(strength = 1.6, zoom = 1.0)

    red_point= img.find_blobs([red])
    if red_point:
        r= red_point[0]
        img.draw_rectangle(r[0:4],color=(0,0,0)) # rect
        rx=r[5]
        ry=r[6]
        #print(rx,ry)
        
#******************************************************************lines*****************
    lines = img.find_lines(roi=area, threshold=line_threshold)
    i=0
    if len(lines)==4 :
        theta0=lines[0].theta()
        theta1=lines[1].theta()
        theta2=lines[2].theta()
        theta3=lines[3].theta()
        for line in lines:
            img.draw_line(line.line(),color=[255,0,0])
        if abs(theta0-theta1)>45:
            a[i]=calculate_intersection(lines[0],lines[1])[0]
            i=i+1
            a[i]=calculate_intersection(lines[0],lines[1])[1]
            i=i+1
        if abs(theta0-theta2)>45:
            a[i]=calculate_intersection(lines[0],lines[2])[0]
            i=i+1
            a[i]=calculate_intersection(lines[0],lines[2])[1]
            i=i+1
        if abs(theta0-theta3)>45:
            a[i]=calculate_intersection(lines[0],lines[3])[0]
            i=i+1
            a[i]=calculate_intersection(lines[0],lines[3])[1]
            i=i+1
        if abs(theta1-theta2)>45:
            a[i]=calculate_intersection(lines[2],lines[1])[0]
            i=i+1
            a[i]=calculate_intersection(lines[2],lines[1])[1]
            i=i+1
        if abs(theta1-theta3)>45:
            a[i]=calculate_intersection(lines[1],lines[3])[0]
            i=i+1
            a[i]=calculate_intersection(lines[1],lines[3])[1]
            i=i+1
        if abs(theta3-theta2)>45:
            a[i]=calculate_intersection(lines[2],lines[3])[0]
            i=i+1
            a[i]=calculate_intersection(lines[2],lines[3])[1]
            i=i+1
        print(a)
        FH = bytearray([0xFF,rx,ry,a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],0xFE])
        uart.write(FH)
        print(rx,ry)

    print(clock.fps())

<think>好的,我现在需要处理用户关于2023子设计竞OpenMV相关目和信息的查询。首先,根据用户提供的引用内容,特别是引用[1]和引用[2],这两处都提到了2023E,涉及OpenMV的应用。我需要先确认这些信息是否足够回答用户的问,或者是否需要补充其他资料。 首先,引用[1]提到OpenMV用于视觉部分,固定在舵机云台前,负责识别屏幕中的原点、激光点位置和A4靶纸边框,并通过串口传输数据给主控芯片。这说明在E中,OpenMV主要承担图像处理和坐标识别的任务。引用[2]则概述了竞的流程,并提到该团队获得全国二等奖,核心代码思路分享,但具体细节可能需要进一步查找。 接下来,我需要检查是否有其他相关信息未被用户引用,但根据用户提供的资料,可能需要围绕E展开。用户的问是关于OpenMV2023中的目和相关资料,因此重点应放在E的内容和要求上。 根据已知信息,E是“运动目标控制与自动追踪系统”,这需要参者设计一个能够跟踪运动目标的系统。OpenMV在此任务中负责视觉识别,捕捉目标的位置信息,然后主控芯片(可能是STM32或其他微控制器)根据这些信息控制舵机云台调整激光点的位置,以实现自动追踪。此外,代码部分涉及串口通信,将OpenMV处理后的坐标数据发送给主控端。 现在需要整理这些信息,以清晰的结构呈现给用户。可能需要分点说明目要求、OpenMV的具体应用、系统组成以及相关资料的位置。同时,生成相关问需要考虑用户可能进一步询问的方向,例如硬件连接、算法优化、代码实现等。 需要确保回答中的技术术语准确,比如舵机云台、串口通信、图像处理算法等。同时,要引用提供的引用来源,正确标注[^1]和[^2]。此外,用户可能对如何实现目标追踪的具体方法感兴趣,比如使用颜色识别、形状识别或模板匹配等OpenMV功能。 最后,生成的相关问应围绕用户可能的需求,例如系统设计细节、代码示例、调试技巧或竞经验分享。需要确保问具有针对性和实用性,帮助用户深入理解如何在实际项目中应用OpenMV。</think>### 2023子设计竞EOpenMV相关解析 2023年全国大学生子设计竞)E为**“运动目标控制与自动追踪系统”**,OpenMV在此任务中承担视觉感知与坐标定位的核心功能。以下为目关键信息及OpenMV应用细节: #### 1. **目要求概述** - **目标**:设计一个通过视觉识别动态追踪屏幕中激光点的系统,需实时反馈激光点与靶标的相对位置,并通过舵机云台调整激光指向。 - **功能需求**: - OpenMV识别屏幕中的**原点、激光点、A4靶纸边框**坐标; - 主控芯片(如STM32)根据坐标数据控制舵机云台运动; - 实现动态目标追踪与静态位置校准。 #### 2. **OpenMV核心任务** - **图像处理**:通过OpenMV的OV7725摄像头采集图像,使用阈值分割或模板匹配算法识别靶纸边框和激光点。 - **坐标转换**:将像素坐标转换为实际物理坐标系,例如通过透视变换(需标定摄像头参数)。 - **串口通信**:将处理后的坐标数据(格式如`(x,y)`)实时发送至主控芯片,波特率通常设置为**115200**。 #### 3. **系统组成与代码逻辑** - **硬件架构**: ``` OpenMV摄像头 → 主控芯片 → 舵机云台 → 激光发射模块 ``` - **OpenMV代码片段**(简化版): ```python import sensor, image, time, pyb from pyb import UART uart = UART(3, 115200) # 初始化串口 sensor.reset() sensor.set_pixformat(sensor.RGB565) sensor.set_framesize(sensor.QVGA) while True: img = sensor.snapshot() # 识别靶纸和激光点(示例为颜色阈值法) blobs = img.find_blobs([(255, 0, 0)], roi=(0, 0, 320, 240)) # 假设激光点为蓝色 if blobs: max_blob = max(blobs, key=lambda b: b.area()) x, y = max_blob.cx(), max_blob.cy() uart.write(f"{x},{y}\n") # 发送坐标 ``` *注:实际代码需结合A4靶纸的矩形识别与坐标修正*。 #### 4. **参考资料与实现难点** - **参考资料**:E完整代码通常包含**摄像头标定、PID控制算法、多目标滤波**等模块,可参考开源社区分享的代码库。 - **难点与优化**: - **抗干扰设计**:环境光变化可能导致误识别,需动态调整阈值或引入机器学习模型; - **实时性提升**:降低图像分辨率或使用硬件加速(如OpenMV的JPG压缩); - **坐标精度**:通过非线性校正补偿镜头畸变。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值