基于 OpenMV 的矩形识别与 STM32 串口通信(电子设计大赛实用教程)
🎯 基于 OpenMV 的矩形识别与 STM32 串口通信(电子设计大赛实用教程)
一、前言
在本科生电子设计大赛中,经常会遇到图像识别相关的任务,例如:
- 识别 矩形框(如识别一个 A4 纸、黑色标记框等);
- 将识别结果传输到 STM32 单片机,用于后续控制(舵机、移动小车、机械臂等)。
很多同学会用 OpenMV 来做图像处理,因为它开箱即用、Python 脚本开发方便,能快速实现视觉任务。再配合 STM32,就能完成 感知 + 控制 的闭环。
今天我就带大家梳理一份完整的 OpenMV 矩形识别 + STM32 串口通信 的实例代码,并讲解核心思路,帮助大家快速上手。
二、整体思路
1. OpenMV 端(负责“看”)
- 使用摄像头拍摄画面。
- 利用
find_blobs()
方法寻找黑色区域,并筛选出符合 矩形特征 的目标。 - 计算矩形的 中心点坐标,并绘制出来。
- 将坐标通过 UART 串口 发给 STM32。
2. STM32 端(负责“动”)
- 接收 OpenMV 发来的坐标字符串。
- 解析坐标数据(例如
CENTER:160,120
)。 - 可以基于坐标进行舵机或电机的控制(例如居中跟踪)。
这样,OpenMV 负责 视觉识别,STM32 负责 运动控制,两者结合就能完成各种电子设计大赛任务。
三、OpenMV 代码详解
下面是完整的 OpenMV 代码(已加详细注释),功能:
👉 识别 A4 比例的矩形目标,并实时将中心点坐标通过串口发送给 STM32。
import sensor, image, time, math
from pyb import UART# ================== 初始化串口 ==================
uart = UART(3, 9600) # 使用 UART3,波特率 9600
uart.init(9600, bits=8, parity=None, stop=1)# ================== 初始化摄像头 ==================
sensor.reset()
sensor.set_pixformat(sensor.RGB565) # 彩色图像
sensor.set_framesize(sensor.QVGA) # 分辨率 320x240
sensor.skip_frames(time=2000) # 等待摄像头稳定
sensor.set_auto_gain(False) # 关闭自动增益
sensor.set_auto_whitebal(False) # 关闭自动白平衡# ================== 参数设置 ==================
MIN_AREA = 2000 # 最小矩形面积
MAX_AREA = 40000 # 最大矩形面积
A4_RATIO = 1.414 # A4纸长宽比 √2
A4_RATIO_INV = 0.707 # 1/√2
RATIO_TOLERANCE = 0.6 # 长宽比容差# 黑色检测阈值(在 LAB 色彩空间)
BLACK_THRESHOLD = [(0, 30, -128, 127, -128, 127)]# ================== 判断矩形函数 ==================
def is_valid_rectangle(blob):rect = blob.rect()w, h = rect[2], rect[3]if w == 0 or h == 0:return Falseratio_wh = w / hratio_hw = h / wis_valid_ratio = (abs(ratio_wh - A4_RATIO) < RATIO_TOLERANCE orabs(ratio_wh - A4_RATIO_INV) < RATIO_TOLERANCE orabs(ratio_hw - A4_RATIO) < RATIO_TOLERANCE orabs(ratio_hw - A4_RATIO_INV) < RATIO_TOLERANCE)if is_valid_ratio:rectangularity = blob.area() / (w * h)if rectangularity > 0.6: # 矩形度阈值return Truereturn False# ================== 查找矩形中心 ==================
def find_rectangle_center(img):img_gray = img.to_grayscale()blobs = img_gray.find_blobs(BLACK_THRESHOLD,pixels_threshold=80,area_threshold=MIN_AREA,merge=True)best_blob, best_score = None, 0for blob in blobs:if blob.area() < MIN_AREA or blob.area() > MAX_AREA:continueif is_valid_rectangle(blob):rect = blob.rect()rectangularity = blob.area() / (rect[2] * rect[3])score = blob.area() * rectangularityif score > best_score:best_score, best_blob = score, blobreturn best_blob# ================== 绘制矩形并输出中心点 ==================
def draw_rectangle_info(img, blob):if blob is None:return Nonerect = blob.rect()center_x = rect[0] + rect[2] // 2center_y = rect[1] + rect[3] // 2img.draw_rectangle(rect, color=(255,0,0), thickness=2)img.draw_circle(center_x, center_y, 8, color=(0,0,255), thickness=3)img.draw_string(10, 10, f"Center: ({center_x},{center_y})", color=(255,255,255))return (center_x, center_y)# ================== 主循环 ==================
print("OpenMV矩形检测启动...")
clock = time.clock()
last_send_time = 0
SEND_INTERVAL = 100 # 每 100ms 发送一次while True:clock.tick()img = sensor.snapshot()best_blob = find_rectangle_center(img)if best_blob:center = draw_rectangle_info(img, best_blob)if center:current_time = time.ticks_ms()if current_time - last_send_time > SEND_INTERVAL:message = f"CENTER:{center[0]},{center[1]}\n"uart.write(message)print("发送:", message.strip())last_send_time = current_timeelse:img.draw_string(10, 10, "未检测到矩形", color=(255,0,0))
四、STM32 代码解析
在 STM32 上,我们需要做的事情比较简单:
- 接收串口数据;
- 判断一条数据是否接收完成(以
\n
作为结束标志); - 解析数据,提取坐标;
- 打印确认,或者做后续控制。
下面是处理函数的示例:
// 串口数据接收处理
void process_uart_data(void)
{if (Serial_GetRxFlag() == 1) // 判断是否有数据{RxData = Serial_GetRxData();if (RxData == '\n') // 接收完成{received_data[data_index] = '\0';new_data_flag = 1; // 标志位置 1}else if (RxData != '\r' && data_index < 99){received_data[data_index++] = RxData;}else if (data_index >= 99){data_index = 0; // 缓冲区溢出,重置}}
}// 处理 OpenMV 发来的数据
void process_openmv_data(char *data)
{if (strncmp(data, "CENTER:", 7) == 0){if (sscanf(data + 7, "%d,%d", ¢er_x, ¢er_y) == 2){printf("STM32: 接收到中心点(%d,%d)\r\n", center_x, center_y);// 这里可以添加舵机控制逻辑}else{printf("数据格式错误: %s\r\n", data);}}else{printf("未知数据: %s\r\n", data);}
}
五、运行效果
-
在摄像头前放置一个黑色矩形(如 A4 纸加黑边框)。
-
OpenMV 能识别出矩形,并实时计算 中心点坐标。
-
通过串口发送数据到 STM32,格式类似:
CENTER:160,120
-
STM32 成功接收,并打印确认:
STM32: 接收到中心点(160,120)
-
后续可以加上 舵机转动、PID 调整 等功能,实现自动跟踪。
六、总结
本文分享了一个 电子设计大赛常用模块:
- OpenMV 实现矩形检测,核心在于 blob 检测 + 长宽比筛选;
- STM32 串口解析数据,实现视觉到控制的桥梁。
这个小模块能应用在很多场景:
✅ 自动对准目标(如巡线小车的识别框);
✅ 机械臂定位(对准工件中心点);
✅ 运动控制(云台自动居中)。
掌握这一套,就等于打通了视觉识别和控制的关键环节。🚀
👉 如果你也在准备电子设计大赛,建议先把这份代码跑通,再在 STM32 上加上电机/舵机控制逻辑,你的速度已经超越大部分本科生了!
附上文字版的接线说明
🔌 OpenMV 与 STM32 串口接线说明
OpenMV 模块和 STM32 开发板之间通过 UART 串口通信,一般只需要接 4 根线:
-
GND (地线)
- OpenMV 的 GND → STM32 的 GND
- 必须共地,否则串口通信不稳定。
-
TX (发送端)
- OpenMV 的 TX → STM32 的 RX(接收端口)
- 负责将 OpenMV 发送的数据传输给 STM32。
-
RX (接收端)
- OpenMV 的 RX → STM32 的 TX(发送端口)
- 用于接收 STM32 发回的数据(比如确认信息)。
-
VCC (电源)
- OpenMV 的 3.3V/5V → STM32 的 3.3V/5V(取决于你的 STM32 板供电电压)。
- 推荐使用 5V 给 OpenMV 供电。
📋 接线对照表
OpenMV 引脚 | STM32 引脚 | 说明 |
---|---|---|
VCC (5V) | 5V | 电源供电 |
GND | GND | 公共地线 |
TX (P4) | RX (PA10, USART1) | OpenMV → STM32 |
RX (P5) | TX (PA9, USART1) | STM32 → OpenMV |
⚠️ 注意事项
- 串口波特率要一致(这里配置的是 9600bps)。
- 如果使用 不同的串口(例如 STM32 USART2),只需要修改对应的 引脚号和代码。
- 不要忘记 共地,这是新手最容易忽略的问题。
视频可以参考:小破站 小陈学长电子实验室 欢迎关注三连 谢谢谢谢谢谢谢谢谢谢谢谢