工程训练大赛智能物流小车:OpenMV视觉识别与串口通信实战解析

📅 2026/7/16 14:35:59
工程训练大赛智能物流小车:OpenMV视觉识别与串口通信实战解析
1. OpenMV视觉识别模块搭建指南第一次接触工程训练大赛物流小车项目时我和队友们对着OpenMV开发板发呆了整整两天。这块火柴盒大小的摄像头模组要承担起二维码识别、色块定位、色环检测三大核心任务。经过三个版本的迭代我们总结出这套稳定可靠的搭建方案。硬件配置上建议选择OpenMV H7 Plus版本它的ARM Cortex-M7处理器能流畅处理QVGA分辨率的图像。我实测过在同时运行二维码解码和色块追踪时帧率能保持在15fps以上。镜头选用2.8mm焦距的标配镜头即可要注意安装时保持水平我们最初因为镜头倾斜5度导致识别坐标总是偏移。开发环境搭建有个小坑务必使用OpenMV IDE 2.6以上版本。旧版对Python3支持不完善我们在阈值调试时遇到过颜色空间转换异常的问题。安装时记得勾选Add OpenMV to PATH否则后续调用串口库时会报错。基础代码框架建议这样初始化import sensor, image, time from pyb import UART sensor.reset() sensor.set_pixformat(sensor.RGB565) # 比灰度模式更适合颜色识别 sensor.set_framesize(sensor.QVGA) # 320x240分辨率 sensor.skip_frames(time2000) # 实测需要2秒稳定曝光 sensor.set_auto_gain(False) # 必须关闭自动增益 sensor.set_auto_whitebal(False) # 必须关闭白平衡2. 二维码识别优化策略比赛场地的二维码可能贴在货架、托盘或墙壁上我们遇到过反光、倾斜、部分遮挡等多种情况。经过实测这套方案能应对90%以上的复杂场景。首先要用lens_corr()校正镜头畸变参数1.8适合大多数2.8mm镜头。有个细节建议在识别前先做一次高斯模糊处理能显著提升污损二维码的识别率img.lens_corr(1.8) img.gaussian(1) # 标准差设为1效果最佳 for code in img.find_qrcodes(): if code.payload(): # 过滤空数据 uart.write(code.payload()\r\n)我们总结的调参经验光照不足时将sensor.set_contrast(3)调高对比度识别距离超过50cm时改用VGA分辨率但帧率会下降遇到动态模糊可以尝试sensor.set_auto_exposure(False, 1400)固定曝光3. 色块识别的阈值魔法色块识别最大的坑就是环境光影响。我们记录了比赛现场三种典型光照下的阈值数据光照条件红色阈值范围绿色阈值范围蓝色阈值范围自然光(42,76,5,35,-3,88)(53,66,-23,-5,17,-5)(49,61,-12,18,-27,-3)暖光灯(38,72,10,40,0,80)(50,63,-20,-8,20,0)(45,58,-15,15,-30,0)LED补光(45,80,0,30,-5,90)(55,70,-25,-3,15,-8)(52,65,-10,20,-25,-5)实际开发中发现用find_blobs()时设置mergeTrue能合并相邻色块但要注意area_threshold不能太小否则会误检。推荐的核心代码red_thresh (42, 76, 5, 35, -3, 88) # L最小,L最大,A最小,A最大,B最小,B最大 blobs img.find_blobs([red_thresh], pixels_threshold200, area_threshold200, mergeTrue) if blobs: max_blob max(blobs, keylambda b: b.pixels()) img.draw_rectangle(max_blob.rect()) send_data(max_blob.cx(), max_blob.cy()) # 发送中心坐标4. 串口通信的防丢包设计和下位机通信时我们遇到过数据错乱、丢包、解析失败各种问题。最终采用的解决方案是自定义通信协议包含帧头、校验和、数据长度等信息。数据打包推荐用struct模块比JSON格式效率高10倍以上。这是我们验证过的稳定方案import struct def pack_data(x, y): # 帧头0xAA 0xAE | x坐标(int) | y坐标(int) | 校验和 checksum (0xAA 0xAE x y) 0xFF return struct.pack(BBiiB, 0xAA, 0xAE, x, y, checksum) # 下位机解析示例(C语言): # if(rx_buf[0]0xAA rx_buf[1]0xAE){ # int x *(int*)rx_buf[2]; # int y *(int*)rx_buf[6]; # uint8_t sum 0; # for(int i0;i10;i) sumrx_buf[i]; # if(sum0) 数据有效 # }实测中要注意波特率建议115200太高会导致STM32解析困难每次发送间隔至少50ms给下位机处理时间添加LED指示灯发送时点亮对应颜色LED便于调试5. 色环识别的图像预处理色环识别比色块更难因为存在颜色渐变。我们采用的方案是先二值化再形态学处理# 红色色环识别示例 img.binary([red_thresh]) # 先用颜色阈值二值化 img.dilate(2) # 膨胀消除边缘锯齿 img.erode(1) # 腐蚀平滑内部区域 blobs img.find_blobs([(100,255)], # 灰度阈值 pixels_threshold2500, mergeTrue)关键参数经验值膨胀次数2次适合3cm直径色环像素阈值直径10cm的色环约2500像素面积阈值建议1600-3000根据距离调整6. 多任务调度策略当需要同时处理二维码、色块和串口通信时建议采用状态机模式。这是我们实际使用的框架state 0 # 0:待机 1:二维码 2:色块 3:色环 uart UART(3, 115200) while True: img sensor.snapshot() # 状态切换 if uart.any(): cmd uart.read().decode().strip() if cmd in [1,2,3]: state int(cmd) # 任务执行 if state 1: process_qrcode(img) elif state 2: process_blob(img) elif state 3: process_ring(img) time.sleep_ms(50) # 控制循环频率这个方案在省赛现场稳定运行了6小时没出过故障。关键点是给每个任务足够的处理时间避免在一个循环周期内做太多操作。