矩形检测
实验原理
本实验使用 cv_lite 提供的矩形检测接口 ,在摄像头采集的图像上实时检测矩形,并用 openmv 的绘图接口将检测到的矩形框绘制出来。其底层实现沿用 OpenCV 经典的“多边形拟合 + 角度约束”矩形检测思路,输入为通过 to_numpy_ref() 零拷贝获取的 ulab.numpy.ndarray:灰度图调用 cv_lite.grayscale_find_rectangles,彩色图调用 cv_lite.rgb888_find_rectangles。
基本思路
矩形是一种“四边形且四个角均接近直角”的特殊多边形,因此检测矩形可以转化为:先从图像中提取闭合轮廓,再把轮廓近似为多边形,最后筛选出“顶点数为 4、面积足够大、各内角接近 90°”的那些多边形。具体流程如下:
- 预处理与边缘提取:先做高斯模糊(核大小
gaussian_blur_size)去噪,再用 Canny(双阈值canny_thresh1/canny_thresh2)得到二值边缘图;彩色图会在多通道上分别求梯度再合并,以充分利用颜色信息; - 轮廓提取:对边缘图做
findContours,得到所有闭合轮廓; - 多边形拟合:对每条轮廓用 Douglas-Peucker 算法(
approxPolyDP)做折线逼近,逼近精度epsilon = 轮廓周长 × approx_epsilon。approx_epsilon越小,拟合越精细、越能保留细节顶点;越大则越容易被简化为少顶点多边形; - 几何筛选:保留满足以下条件的轮廓--
- 拟合后顶点数为 4;
- 面积大于
area_min_ratio × 图像总面积,过滤过小的噪声块; - 计算相邻两条边夹角的余弦并取最大值,若其绝对值小于
max_angle_cos,则认为四个角都接近直角,判定为矩形。max_angle_cos越小,要求越严格(越接近标准矩形);
- 输出:每个检测到的矩形以其外接矩形
[x, y, w, h](左上角坐标与宽高)返回,所有矩形扁平拼接为[x0, y0, w0, h0, x1, y1, w1, h1, ...]。
角度余弦判别
判断四边形是否为矩形的关键是各内角是否为 90°。对相邻两条边向量 、,其余弦为:
当 时 。因此算法计算每个顶点处相邻边的余弦,取其最大绝对值,只要它小于阈值 max_angle_cos,就认为四个角都足够接近直角。max_angle_cos 越小,允许的角度 偏差越小,检出越严格。
cv_lite 的封装与数据流
cv_lite 的矩形检测接口接收 ulab.numpy.ndarray,返回扁平的矩形参数列表:
- 通过
img.to_numpy_ref()以零拷贝方式取得输入图像的 ndarray 引用,灰度图为单通道、彩色图为 RGB888 三通道; - 灰度图直接进入检测流程;RGB888 图在多通道上求梯度以利用颜色信息;
- 返回值
rects为[x, y, w, h, ...],每 4 个元素描述一个矩形,用 openmv 的img.draw_rectangle()在原图上绘制后再显示。
由于 ndarray 与 image 共享同一块内存,整个“采集 -> 检测 -> 绘制 -> 显示”链路无需额外拷贝,因此相比 openmv 原生 find_rectangles 有明显的速度优势(参见 cv_lite 概述中的速度对比)。
代码解析
两个示例(灰度图与彩色图)的处理流程基本一致,区别在于像素格式、调用的检测函数、绘制颜色及个别参数默认值。下面按关键步骤进行解析。
导入模块
import cv_lite # cv_lite 扩展模块
import ulab.numpy as np # MicroPython NumPy 类库
from media.sensor import * # 摄像头接口
from media.display import * # 显示接口
from media.media import * # 媒体资源管理器
cv_lite:提供grayscale_find_rectangles/rgb888_find_rectangles等基于 OpenCV 的加速接口;ulab.numpy:MicroPython 下的类 NumPy 库,to_numpy_ref()返回的 ndarray 即为该类型,作为 cv_lite 的输入;media.sensor/media.display/media.media:openmv 风格的摄像头、显示与媒体管理接口,负责采集与显示。