image — 机器视觉
image 是 OpenMV 机器视觉的核心模块。它提供 Image 图像对象,用来保存内存中的像素,并进行绘制、滤波、变换和特征提取;还提供检测结果对象,以及阈值、直方图、统计量等辅助对象。
摄像头的设置与采集由 csi 负责,采集得到的图像交给 image 处理。例如,img = csi0.snapshot() 得到一帧图像后,可以调用 img.find_blobs(...) 查找色块,再利用返回的结果进行判断或绘图。
本页以 H7 Plus / OV5640、固件 5.0.1(OPENMV4P) 为范围。模块名 image 小写,类名 Image 大写;image.Image、image.ImageIO、image.Blob 等名称保持官方拼写,关键点匹配类 kptmatch 按官方保留小写。
获取图像
可以通过以下四种方式在 RAM 中获得 Image 对象:
- 从摄像头实时采集。 调用
csi.CSI.snapshot(),把下一帧捕获到帧缓冲区;返回的Image引用这块缓冲区。 - 从文件加载。 把文件路径传给
Image构造函数,例如image.Image("/sdcard/photo.jpg")。支持 BMP、PPM/PGM、JPEG、PNG,以及 OpenMV 的ImageIO录制格式。 - 从 ndarray 加载。 把形状为
(h, w)或(h, w, 3)的 float32 数组传给Image构造函数。数组中0.0–255.0范围的像素值分别转换为 GRAYSCALE 或 RGB565 图像。这可以把ml的张量输出或ulab的处理结果转回可绘制的图像。 - 新建空图像缓冲区。 指定尺寸与像素格式,例如
image.Image(320, 240, image.RGB565)。可以从空图像开始绘制,也可以把它用作图像运算的临时缓冲区。
文件路径、数组和宽高参数代表不同的构造方式;使用时选择其中一种。完整构造签名和图像操作方法见下方的 Image 类参考。
像素格式
像素格式决定内存占用、处理开销和可用算法。构造图像或设置摄像头格式时,使用 BINARY、GRAYSCALE、RGB565、BAYER、YUV422、JPEG 或 PNG 常量。
| 格式 | 存储方式 | 使用与限制 |
|---|---|---|
BINARY | 1 bit/像素 | 占用最小,常用于阈值与形态学处理,通常不直接由传感器采集。 |
GRAYSCALE | 8 bit/像素,即 1 字节 | 对应 YUV422 的 Y 通道;对 AprilTag、边缘检测、光流等多数视觉算法处理较快。 |
RGB565 | 16 bit/像素,即 2 字节 | 红色 5 位、绿色 6 位、蓝色 5 位,是默认彩色格式。 |
BAYER | 8 bit/像素 | 传感器原始 Bayer 排列数据,适合自行去马赛克,或先用较少内存保存更多像素、需要时再转换。多数图像处理方法不能直接使用。 |
YUV422 | 16 bit/像素,即 2 字节 | 4:2:2 色度抽样,每对像素按 Y1, U, Y2, V 打包;适合直接处理色度信息,但只有部分方法支持。 |
JPEG / PNG | 压缩缓冲区,大小随内容变化 | 适合存储与传输。进行逐像素操作前,先调用 Image.to_grayscale() 或 Image.to_rgb565() 转换。 |
例如,320 × 240 图像有 76800 个像素。仅计算像素数据,GRAYSCALE 需要约 75 KiB,RGB565 需要约 150 KiB;这里没有计入对象和其他缓冲区的开销。
处理结果
检测与特征提取方法会返回结果对象。例如,Image.find_blobs() 返回 Blob 列表,Image.find_apriltags() 返回 AprilTag 列表。可以逐项读取检测结果的中心、包围框、面积、编码值等信息,再用于控制逻辑,或交给 Image.draw_rectangle()、Image.draw_string() 等方法绘制。
图像对象和检测结果对象用途不同:img 保存像素,检测结果描述这次处理发现了什么。某种结果有哪些属性、哪些操作返回列表,应以对应类的参考为准,不能把旧版结果方法写法与新版属性写法混用。
色彩空间辅助函数
image 提供二值、灰度、RGB、LAB、YUV 之间的单个像素值转换函数。它们适合在 Python 中换算阈值或调色板条目,例如把一个 RGB 颜色转换为 LAB 值。
这些函数只转换一个值,不会修改整张图像。整图转换应使用 Image 的 to_* 方法,避免在 Python 循环中逐像素调用辅助函数。
类
以下保留官方的 18 个类索引,链接进入官方 5.0.1 独立类参考。Image 的 find_blobs() 等属于类方法,不是下方的 30 个模块级函数。独立类页可能涵盖其他板卡特性,使用时仍须遵守 OPENMV4P 的功能限制。
| 类 | 主要用途与参考 |
|---|---|
Image | 图像对象,保存像素并执行图像处理 |
ImageIO | 图像序列的读写与录制 |
HaarCascade | Haar 级联特征描述符 |
Similarity | 图像相似度结果 |
Histogram | 直方图 |
Percentile | 百分位结果 |
Threshold | 阈值结果 |
Statistics | 图像统计结果 |
Blob | 色块检测结果 |
Line | 直线结果 |
Circle | 圆形结果 |
Rect | 矩形结果 |
QRCode | 二维码检测结果 |
AprilTag | AprilTag 检测结果 |
DataMatrix | Data Matrix 检测结果 |
BarCode | 条形码检测结果 |
Displacement | 位移估计结果 |
kptmatch | 关键点匹配结果 |
色彩空间转换函数
下面的 X_to_Y 函数接收一个源色彩空间中的值,返回目标色彩空间中的值。调用时加上模块名,例如 image.rgb_to_lab((255, 0, 0))。
| 色彩空间 | 参数或返回值的形式与范围 |
|---|---|
| 二值 | int,0–1 |
| 灰度 | int,0–255 |
| RGB | (r, g, b) 元组,每个分量为 0–255 的整数 |
| LAB | (l, a, b) 元组,L 为 0–100,A、B 为 −128–127 |
| YUV | (y, u, v) 元组,Y 为 0–255,U、V 为 −128–127 |
注意,辅助函数接收的 RGB 是三个 8 位分量的元组,不是打包后的 RGB565 整数。签名中的 Tuple[int, int, int] 表示三个整数构成的元组,-> 后是返回类型。
binary_to_grayscale()
image.binary_to_grayscale(value: int) -> int
将 value 中的二值整数转换为灰度整数并返回。输入与输出的形式、范围见上表。
binary_to_rgb()
image.binary_to_rgb(value: int) -> Tuple[int, int, int]
将 value 中的二值整数转换为 RGB 元组并返回。输入与输出的形式、范围见上表。
binary_to_lab()
image.binary_to_lab(value: int) -> Tuple[int, int, int]
将 value 中的二值整数转换为 LAB 元组并返回。输入与输出的形式、范围见上表。
binary_to_yuv()
image.binary_to_yuv(value: int) -> Tuple[int, int, int]
将 value 中的二值整数转换为 YUV 元组并返回。输入与输出的形式、范围见上表。
grayscale_to_binary()
image.grayscale_to_binary(value: int) -> int
将 value 中的灰度整数转换为二值整数并返回。输入与输出的形式、范围见上表。
grayscale_to_rgb()
image.grayscale_to_rgb(value: int) -> Tuple[int, int, int]
将 value 中的灰度整数转换为 RGB 元组并返回。输入与输出的形式、范围见上表。
grayscale_to_lab()
image.grayscale_to_lab(value: int) -> Tuple[int, int, int]
将 value 中的灰度整数转换为 LAB 元组并返回。输入与输出的形式、范围见上表。
grayscale_to_yuv()
image.grayscale_to_yuv(value: int) -> Tuple[int, int, int]
将 value 中的灰度整数转换为 YUV 元组并返回。输入与输出的形式、范围见上表。
rgb_to_binary()
image.rgb_to_binary(value: Tuple[int, int, int]) -> int
将 value 中的 RGB 元组转换为二值整数并返回。输入与输出的形式、范围见上表。
rgb_to_grayscale()
image.rgb_to_grayscale(value: Tuple[int, int, int]) -> int
将 value 中的 RGB 元组转换为灰度整数并返回。输入与输出的形式、范围见上表。
rgb_to_lab()
image.rgb_to_lab(value: Tuple[int, int, int]) -> Tuple[int, int, int]
将 value 中的 RGB 元组转换为 LAB 元组并返回。输入与输出的形式、范围见上表。
rgb_to_yuv()
image.rgb_to_yuv(value: Tuple[int, int, int]) -> Tuple[int, int, int]
将 value 中的 RGB 元组转换为 YUV 元组并返回。输入与输出的形式、范围见上表。
lab_to_binary()
image.lab_to_binary(value: Tuple[int, int, int]) -> int
将 value 中的 LAB 元组转换为二值整数并返回。输入与输出的形式、范围见上表。
lab_to_grayscale()
image.lab_to_grayscale(value: Tuple[int, int, int]) -> int
将 value 中的 LAB 元组转换为灰度整数并返回。输入与输出的形式、范围见上表。
lab_to_rgb()
image.lab_to_rgb(value: Tuple[int, int, int]) -> Tuple[int, int, int]
将 value 中的 LAB 元组转换为 RGB 元组并返回。输入与输出的形式、范围见上表。
lab_to_yuv()
image.lab_to_yuv(value: Tuple[int, int, int]) -> Tuple[int, int, int]
将 value 中的 LAB 元组转换为 YUV 元组并返回。输入与输出的形式、范围见上表。
yuv_to_binary()
image.yuv_to_binary(value: Tuple[int, int, int]) -> int
将 value 中的 YUV 元组转换为二值整数并返回。输入与输出的形式、范围见上表。
yuv_to_grayscale()
image.yuv_to_grayscale(value: Tuple[int, int, int]) -> int
将 value 中的 YUV 元组转换为灰度整数并返回。输入与输出的形式、范围见上表。
yuv_to_rgb()
image.yuv_to_rgb(value: Tuple[int, int, int]) -> Tuple[int, int, int]
将 value 中的 YUV 元组转换为 RGB 元组并返回。输入与输出的形式、范围见上表。
yuv_to_lab()
image.yuv_to_lab(value: Tuple[int, int, int]) -> Tuple[int, int, int]
将 value 中的 YUV 元组转换为 LAB 元组并返回。输入与输出的形式、范围见上表。
特征描述子函数
HaarCascade()
image.HaarCascade(path: str, stages: int = -1) -> Cascade
加载 Haar 级联,返回供 Image.find_features() 使用的 Cascade 句柄。
| 参数 | 说明 |
|---|---|
path | 字符串 "frontalface" 或 "eye" 加载固件 ROM 内置的人脸或眼睛级联;也可以填写自定义 .cascade 二进制文件的路径,该文件由 OpenMV 级联转换工具生成。 |
stages | 检测时计算的级联层数,默认 -1 使用文件中的全部层。减少层数可以加快检测,但会增加误检。 |
image.HaarCascade("frontalface") 是加载检测器,并不会执行人脸检测;实际检测由图像的 find_features() 方法完成。
load_descriptor()
image.load_descriptor(path: str) -> kp_desc | lbp_desc
从 path 指向的文件加载描述子并返回。文件内部的类型标记决定恢复哪类对象:
- ORB 关键点描述子(
kp_desc):先通过Image.find_keypoints()提取,再由image.save_descriptor()保存。 - LBP 描述子(
lbp_desc):先通过Image.find_lbp()提取,再由image.save_descriptor()保存。
path 应指向已经保存的 OpenMV 描述子文件,不能用普通照片路径代替。
save_descriptor()
image.save_descriptor(descriptor: kp_desc | lbp_desc, path: str) -> None
将 descriptor(ORB 关键点或 LBP 描述子)序列化到 path 指定的文件,使用 OpenMV 描述子文件格式;返回 None。
之后可以用 image.load_descriptor(path) 重新加载同一文件。保存的是特征描述子,不是原始图像。
match_descriptor()
image.match_descriptor(descriptor0, descriptor1, threshold: int = 85, filter_outliers: bool = False) -> int | kptmatch
匹配两个同类型的描述子,不能把 ORB 与 LBP 混合传入。
| 参数 | 说明 |
|---|---|
descriptor0、descriptor1 | 两个待比较的描述子;均为 LBP,或均为 ORB 关键点描述子。 |
threshold | ORB 匹配阈值,范围 0–100,默认 85。原文规定:数值越小越严格,会拒绝较弱的最近邻匹配。 |
filter_outliers | 是否对匹配关键点启用类似 RANSAC 的离群点剔除,默认 False。两幅图之间预期只有一个刚性变换时可启用;关键点来自多个物体时应关闭。 |
返回值随描述子类型变化:
- 两个 LBP 描述子:返回整数汉明距离,越小越相似。
- 两个 ORB 描述子:返回描述匹配关键点群的
kptmatch;如果没有匹配通过阈值,则返回None。
原文签名写作 int | kptmatch,但原文正文同时说明可能返回 None,这里保留并明确这一差异。使用 ORB 结果前,应先判断它是否为 None。
阈值与匹配结果不是同一个数:按原文规则,把 ORB 的 threshold 从 85 降到 70 会收紧匹配条件;LBP 返回的汉明距离则是比较后的结果,不能直接当作这个阈值。
色块几何辅助函数
以下函数接收 Image.find_blobs() 返回的一个 Blob,在需要时计算额外的几何信息。它们是模块级函数,例如 image.get_solidity(blob),不是 Blob 的成员方法;不调用时,基础色块查找流程不承担这部分计算开销。
get_solidity()
image.get_solidity(blob: blob) -> float
计算色块的实心度:blob.pixels / convex_hull_area,即色块像素数除以凸包面积。
返回 0–1 的浮点数;1.0 表示色块完全填满自己的凸包。例如,色块有 600 个像素,凸包面积为 1000,实心度就是 0.6。
get_convexity()
image.get_convexity(blob: blob) -> float
计算色块的凸度:convex_hull_perimeter / blob.perimeter,即凸包周长除以色块周长。
返回 0–1 的浮点数;1.0 表示完全凸的色块。它比较的是周长,与上一个函数比较面积的实心度不同。
get_major_axis_line()
image.get_major_axis_line(blob: blob) -> line
返回沿色块主轴方向的 Line 对象。这里的主轴是色块最小面积旋转矩形的两条主轴中较长的一条。
get_minor_axis_line()
image.get_minor_axis_line(blob: blob) -> line
返回沿色块次轴方向的 Line 对象。这里的次轴是色块最小面积旋转矩形的两条主轴中较短的一条。
get_enclosing_circle()
image.get_enclosing_circle(blob: blob) -> circle
返回包围该色块的 Circle 对象。原文只说明它包围色块,没有把它定义为最小包围圆。
get_enclosed_ellipse()
image.get_enclosed_ellipse(blob: blob) -> Tuple[int, int, int, int, int]
返回五元组 (cx, cy, a, b, rotation),描述色块最小面积旋转矩形的内切椭圆。
| 元素 | 含义 |
|---|---|
cx、cy | 椭圆中心的像素坐标,整数。 |
a、b | 两个半轴的像素长度,整数;不是完整轴长。 |
rotation | 椭圆旋转角度,单位为度,整数。 |
这是普通元组,不是带命名属性的 attrtuple;只能通过索引或元组解包读取。例如 ellipse[0] 是中心横坐标,不能写作 ellipse.cx。
常量
以下常量的类型均为 int,使用时带上 image. 前缀。常量名用于选择格式或算法,不在这里写死其数值;某些常量只存在于启用了相应功能的固件中。
像素格式
传给 Image 构造函数的 pixformat,或 csi.CSI.pixformat()。
| 常量 | 说明 |
|---|---|
image.BINARY | 1 bit/像素的位图,体积最小;用于阈值与形态学处理,通常不直接由传感器采集。 |
image.GRAYSCALE | 8 bit/像素,即每像素 1 字节。对 AprilTag、边缘检测、光流等多数视觉算法处理较快。 |
image.RGB565 | 16 bit/像素,红 5 位、绿 6 位、蓝 5 位,是默认彩色格式。 |
image.BAYER | 8 bit/像素的传感器原始 Bayer 数据;多数图像处理方法不可直接使用。适合按需去马赛克或节省存储像素所需的内存。 |
image.YUV422 | 4:2:2 色度抽样,每像素 2 字节,每对像素按 Y1, U, Y2, V 打包。只有部分图像处理方法直接支持。 |
image.JPEG | JPEG 压缩缓冲区;逐像素操作前先用 Image.to_grayscale() 或 Image.to_rgb565() 转换。 |
image.PNG | PNG 压缩缓冲区;逐像素操作前先用 Image.to_grayscale() 或 Image.to_rgb565() 转换。 |
调色板
用于 Image.to_rainbow()、Image.to_ironbow()、Image.draw_image() 的 color_palette 参数,把灰度图像映射为彩色。本页不使用热成像或事件传感器专用的摄像头调色板设置。
| 常量 | 说明 |
|---|---|
image.PALETTE_RAINBOW | 平滑的彩虹色轮,OpenMV 热成像的默认调色板。 |
image.PALETTE_IRONBOW | 非线性的铁红调色板,模拟 FLIR Lepton 热成像取景器的显示效果。 |
缩放模式
传给 Image.draw_image()、Image.scale() 或类似缩放方法的 hint 参数。
| 常量 | 说明 |
|---|---|
image.AREA | 缩小时使用区域平均;放大时使用最近邻。 |
image.BILINEAR | 双线性缩放;缩小时使用子采样。 |
image.BICUBIC | 双三次缩放,质量高于 BILINEAR,但更慢;缩小时使用子采样。 |
绘图提示
以下标志可以按位或组合后传给 Image.draw_image() 的 hint 参数,例如 image.HMIRROR | image.VFLIP。
| 常量 | 说明 |
|---|---|
image.VFLIP | 绘制时垂直翻转源图像。 |
image.HMIRROR | 绘制时水平镜像源图像。 |
image.TRANSPOSE | 绘制时转置源图像,交换 x/y。 |
image.CENTER | 让源图像在目标中居中;显式 x/y 偏移改为相对中心,而不是相对左上角。 |
image.EXTRACT_RGB_CHANNEL_FIRST | 在缩放之前提取 RGB 通道;未设置时在缩放之后提取。 |
image.APPLY_COLOR_PALETTE_FIRST | 在缩放之前应用调色板;未设置时在缩放之后应用。 |
image.SCALE_ASPECT_KEEP | 保持宽高比,把源图像完整放入目标区域;比例不同时会留边。 |
image.SCALE_ASPECT_EXPAND | 保持宽高比并填满目标区域;比例不同时会裁切。 |
image.SCALE_ASPECT_IGNORE | 忽略宽高比,把源图像缩放到填满目标区域。 |
image.BLACK_BACKGROUND | 告知透明度混合流程目标已知为全黑,从而跳过目标像素回读,加快刚清空缓冲区上的透明效果。 |
image.ROTATE_90 | VFLIP | TRANSPOSE 的快捷组合,顺时针旋转 90 度。 |
image.ROTATE_180 | HMIRROR | VFLIP 的快捷组合,旋转 180 度。 |
image.ROTATE_270 | HMIRROR | TRANSPOSE 的快捷组合,顺时针旋转 270 度。 |
JPEG 色度抽样
写入 JPEG 时,传给 Image.to_jpeg()、Image.compress() 或 Image.save() 的 subsampling 参数。
| 常量 | 说明 |
|---|---|
image.JPEG_SUBSAMPLING_AUTO | 根据 JPEG 质量设置自动选择色度抽样方式。 |
image.JPEG_SUBSAMPLING_444 | 强制 4:4:4,不压缩色度采样。 |
image.JPEG_SUBSAMPLING_422 | 强制 4:2:2;向不能正确处理 4:2:0 的第三方播放器传输 MJPEG 时,原文推荐使用此项。 |
image.JPEG_SUBSAMPLING_420 | 强制 4:2:0 色度抽样。 |
模板匹配
传给 Image.find_template() 的 search 参数。
| 常量 | 说明 |
|---|---|
image.SEARCH_EX | 穷举搜索,评估 ROI 内每个位置;最慢,但保证找到最佳匹配。 |
image.SEARCH_DS | 菱形搜索,从粗到细,比 SEARCH_EX 快得多;对于高度自相似的模板,可能错过全局最优匹配。 |
边缘检测
传给 Image.find_edges() 的 algorithm 参数。
| 常量 | 说明 |
|---|---|
image.EDGE_CANNY | Canny 检测:梯度幅值、非极大值抑制、滞后阈值处理。质量较高,但更慢。 |
image.EDGE_SIMPLE | 对高通滤波结果做阈值处理。更快,但边缘比 EDGE_CANNY 更粗、噪声更多。 |
ORB 角点检测
传给 Image.find_keypoints() 的 corner_detector 参数。
| 常量 | 说明 |
|---|---|
image.CORNER_AGAST | AGAST 角点检测,比 CORNER_FAST 更慢,但关键点更稳定。 |
AprilTag 家族
可以按位或组合后传给 Image.find_apriltags() 的 families 参数。每个家族由独立的固件构建选项控制;不支持的家族常量在运行时不存在,不能把它当作值为零的常量。
| 常量 | 说明 |
|---|---|
image.TAG36H11 | 36h11 家族,587 个独立 ID,最多 4 位纠错;最常见的家族。 |
条形码制式
Image.find_barcodes() 返回的条形码结果通过 BarCode.type 报告以下类型。这里使用属性 type,不是旧版方法 type()。
| 常量 | 说明 |
|---|---|
image.EAN2 | EAN-2 附加条形码。 |
image.EAN5 | EAN-5 附加条形码。 |
image.EAN8 | EAN-8 条形码。 |
image.UPCE | UPC-E 条形码。 |
image.ISBN10 | ISBN-10 条形码。 |
image.UPCA | UPC-A 条形码。 |
image.EAN13 | EAN-13 条形码。 |
image.ISBN13 | ISBN-13 条形码。 |
image.I25 | 交叉二五码(Interleaved 2-of-5)。 |
image.DATABAR | GS1 DataBar 条形码。 |
image.DATABAR_EXP | GS1 DataBar Expanded 条形码。 |
image.CODABAR | Codabar 条形码。 |
image.CODE39 | Code 39 条形码。 |
image.CODE93 | Code 93 条形码。 |
image.CODE128 | Code 128 条形码。 |
H7 Plus 的功能边界
OPENMV4P 的官方配置启用了图像读写、PNG、二维码、AprilTag、条形码、Haar、LBP 与关键点等功能。AprilTag 家族只启用 TAG36H11,关键点检测器启用 AGAST;其他家族及 FAST 不列作本板选择。深度图和 GENX320 专用调色板不属于原配 OV5640 的使用范围,PDF417 解码器未实现,也不列为可用类型。
软件图像格式不等于摄像头可直接输出的格式。例如二值图通过图像处理得到,PNG 可由文件解码或编码得到;不要把这些常量直接套进 cam.pixformat()。高分辨率 JPEG 适合存储,常规识别先使用灰度或 RGB565 图像,留出算法工作内存。