从 OpenMV/K230/OpenCV 迁移到 MaixCAM,一页学会视觉模块开发# MaixCAM 视觉开发实战指南
·
MaixCAM 视觉开发实战指南
从 OpenMV/K230/OpenCV 迁移到 MaixCAM,一页学会视觉模块开发
1. 平台概述
1.1 你手上的设备
| 参数 | MaixCAM 2 (你的设备) | MaixCAM |
|---|---|---|
| 芯片 | SG2000 | K230 |
| CPU | ARM A53 @1GHz + RISC-V @700MHz | C908 双核 @1.6GHz + C906 @800MHz |
| NPU | ~1 TOPS | ~1 TOPS |
| 内存 | 512MB DDR3 | 512MB LPDDR3 |
| 默认摄像头 | SC2336 (1920×1080) | GC4653 (2560×1440) |
| WiFi | WiFi6 (2.4G/5G) | 2.4G WiFi |
1.2 和你熟悉的平台对比
| 特性 | OpenMV | K230 (nncase) | OpenCV (PC) | MaixPy |
|---|---|---|---|---|
| 语言 | MicroPython | C/MicroPython | C++/Python | MicroPython |
| AI推理 | 内置tf.模型 | nncase编译 | opencv-dnn | nn.YOLO等 |
| 传统CV | image模块 | cv库 | cv2.* | image模块 + cv2 |
| 颜色检测 | find_blobs ✅ | find_blobs ✅ | inRange+contours | find_blobs ✅ |
| 二维码 | find_qrcodes ✅ | find_qrcodes ✅ | QRCodeDetector | find_qrcodes ✅ |
| 巡线 | get_regression ✅ | get_regression ✅ | fitLine | get_regression ✅ |
| 圆检测 | find_circles ✅ | find_circles ✅ | HoughCircles | find_circles ✅ |
核心差异:MaixPy 的 image 模块 API 和 OpenMV 几乎一模一样,所以 OpenMV 代码迁移成本极低。同时 MaixPy 原生支持 OpenCV(import cv2),所以 K230 和 OpenCV 经验完全适用。
1.3 开发环境
三种方式把代码部署到设备:
# 方式1:MaixVision(推荐新手)- 图形化 IDE,连接 WiFi 后自动发现设备
# https://wiki.sipeed.com/maixpy/doc/zh/basic/maixvision.html
# 方式2:ADB 传输
adb push main.py /root/
# 方式3:scp 传输(设备需连 WiFi)
scp main.py root@192.168.x.x:/root/
2. 摄像头采集
2.1 基础模板
from maix import camera, display, app, time
import image
cam = camera.Camera(320, 240) # 宽×高
disp = display.Display()
while not app.need_exit():
img = cam.read()
disp.show(img)
print(f"FPS: {time.fps():.1f}")
2.2 分辨率与格式选择
# 常用分辨率
camera.Camera(320, 240) # QVGA — 高速追踪 (>80fps)
camera.Camera(640, 480) # VGA — 平衡画质/速度
camera.Camera(448, 448) # 正方形 — E题高分辨率模式
# 格式选择
from maix import image
cam = camera.Camera(320, 240, image.Format.FMT_RGB888) # RGB(默认,AI推理用)
cam = camera.Camera(320, 240, image.Format.FMT_BGR888) # BGR(OpenCV处理用)
cam = camera.Camera(320, 240, image.Format.FMT_GRAYSCALE) # 灰度(省内存快)
帧率优化核心公式:
像素越少 → 帧率越高。320×240 通常是最佳性价比分辨率。
2.3 缓冲策略
cam = camera.Camera(320, 240, buff_num=1) # 缓冲1帧 → 低延迟(适合追踪控制)
cam = camera.Camera(320, 240, buff_num=2) # 缓冲2帧 → 更高帧率(适合纯检测)
# AI模型双缓冲
detector = nn.YOLO11(model="...", dual_buff=True) # 帧率高,延迟多1帧
detector = nn.YOLO11(model="...", dual_buff=False) # 低延迟(追踪场景推荐)
2.4 手动白平衡与对比度
cam = camera.Camera(320, 240)
cam.awb_mode(camera.AwbMode.Manual) # 关闭自动白平衡
cam.set_wb_gain([0.134, 0.0625, 0.0625, 0.1139]) # R, GR, GB, B 增益
cam.constrast(80) # 对比度 0-100,提高有助于检测
3. 传统图像处理(对标 OpenMV image 模块)
重要:以下所有函数都和 OpenMV 用法一致,直接迁移即可。
3.1 颜色色块检测 — find_blobs()
from maix import camera, display, image
cam = camera.Camera(320, 240)
disp = display.Display()
# LAB 颜色阈值:[L_min, L_max, A_min, A_max, B_min, B_max]
# 常用颜色参考:
thresholds_red = [[0, 80, 40, 80, 10, 80]] # 红色
thresholds_green = [[0, 80, -120, -10, 0, 30]] # 绿色
thresholds_blue = [[0, 80, 30, 100, -120, -60]] # 蓝色
thresholds_yellow = [[0, 80, -10, 20, 40, 80]] # 黄色(参考)
thresholds_white = [[70, 100, -20, 20, -20, 20]] # 白色(参考)
thresholds_black = [[0, 30, -20, 20, -20, 20]] # 黑色(参考)
th = thresholds_green
while not app.need_exit():
img = cam.read()
blobs = img.find_blobs(th, area_threshold=1000, pixels_threshold=1000,
x_stride=2, y_stride=2) # stride加速
for b in blobs:
# 画外接矩形
img.draw_rect(b.x(), b.y(), b.w(), b.h(), image.COLOR_RED)
# 画角点
corners = b.corners()
for i in range(4):
img.draw_line(corners[i][0], corners[i][1],
corners[(i+1)%4][0], corners[(i+1)%4][1],
image.COLOR_GREEN)
# 画中心
img.draw_circle(b.cx(), b.cy(), 3, image.COLOR_BLUE, -1)
disp.show(img)
阈值调参技巧:
- 用 MaixVision 的「阈值编辑器」工具实时调参
- L 通道管亮度,A 通道管红绿,B 通道管蓝黄
- 增大
x_stride/y_stride可大幅加速(2或4)
3.2 巡线 — get_regression()
from maix import camera, display, image
cam = camera.Camera(320, 240)
disp = display.Display()
# 黑线阈值
th_black = [[0, 40, -20, 20, -20, 20]]
while not app.need_exit():
img = cam.read()
lines = img.get_regression(th_black, area_threshold=100)
for line in lines:
# 画出线段
img.draw_line(line.x1(), line.y1(), line.x2(), line.y2(),
image.COLOR_GREEN, 2)
# 获取线角度
theta = line.theta() # 0~180°
rho = line.rho()
# 转换到 [-90, 90] 范围
if theta > 90:
angle = 270 - theta
else:
angle = 90 - theta
img.draw_string(0, 0, f"theta: {theta:.1f} angle: {angle:.1f}",
image.COLOR_BLUE)
disp.show(img)
3.3 圆检测 — find_circles()
circles = img.find_circles(threshold=3000) # 阈值越高越严格
for c in circles:
img.draw_circle(c.x(), c.y(), c.r(), image.COLOR_RED, 2)
print(f"圆心: ({c.x()},{c.y()}) 半径: {c.r()} 强度: {c.magnitude()}")
3.4 矩形检测 — find_rects()
rects = img.find_rects(threshold=3000)
for r in rects:
img.draw_rect(r.x(), r.y(), r.w(), r.h(), image.COLOR_GREEN, 2)
corners = r.corners() # 四个角点
3.5 二维码与条码
# 二维码
qrcodes = img.find_qrcodes()
for q in qrcodes:
img.draw_rect(q.x(), q.y(), q.w(), q.h(), image.COLOR_RED)
print(f"QR: {q.payload()}")
# 条码
barcodes = img.find_barcodes()
for b in barcodes:
print(f"Barcode: {b.payload()}")
3.6 AprilTag 定位
tags = img.find_apriltags()
for tag in tags:
img.draw_rect(tag.x(), tag.y(), tag.w(), tag.h(), image.COLOR_RED)
img.draw_string(tag.x(), tag.y(), f"ID:{tag.id()}", image.COLOR_BLUE)
# 获取3D姿态信息
print(f"Tag ID:{tag.id()}, rotation: {tag.rotation()}")
3.7 边缘检测
from maix.image import EdgeDetector
img.find_edges(EdgeDetector.EDGE_CANNY, threshold=[50, 100])
3.8 绘图 API 速查
# 全部是 image.Image 的方法
img.draw_line(x0, y0, x1, y1, color, thickness=1)
img.draw_rect(x, y, w, h, color, thickness=1)
img.draw_circle(x, y, r, color, thickness=1)
img.draw_ellipse(cx, cy, rx, ry, color, thickness=1)
img.draw_cross(x, y, size, color, thickness=1)
img.draw_arrow(x0, y0, x1, y1, color, thickness=1)
img.draw_string(x, y, text, color, scale=1, thickness=1)
img.draw_image(x, y, other_img) # 叠图
img.draw_keypoints(points, color, size, line_thickness=1) # 画多点
# 颜色
image.COLOR_RED / GREEN / BLUE / WHITE / BLACK / YELLOW / CYAN / MAGENTA / ORANGE
image.Color.from_rgb(r, g, b) # 自定义RGB颜色
image.Color.from_rgba(r, g, b, a) # 自定义RGBA
4. AI 模型推理(对标 K230 nncase)
4.1 YOLO 检测完整模板(⚠️ 牢记这个模板)
from maix import camera, display, image, nn, app
# Step 1: 加载模型
detector = nn.YOLO11(model="/root/models/yolo11n.mud", dual_buff=True)
# 也可用:nn.YOLOv5(model="...") 或 nn.YOLOv8(model="...")
# Step 2: ⚠️ 摄像头分辨率必须匹配模型输入 ⚠️
cam = camera.Camera(detector.input_width(), # 通常是 320
detector.input_height(), # 通常是 320
detector.input_format()) # 模型需要的格式
disp = display.Display()
while not app.need_exit():
img = cam.read()
# Step 3: 推理
objs = detector.detect(img, conf_th=0.5, iou_th=0.45)
for obj in objs:
# obj.x, obj.y, obj.w, obj.h — 框坐标
# obj.class_id — 类别ID
# obj.score — 置信度
img.draw_rect(obj.x, obj.y, obj.w, obj.h, image.COLOR_RED)
label = f'{detector.labels[obj.class_id]}: {obj.score:.2f}'
img.draw_string(obj.x, obj.y, label, image.COLOR_RED)
disp.show(img)
4.2 AI 模型全景
| 任务 | 类 | 模型文件 | MaixHub下载 |
|---|---|---|---|
| 目标检测(轻量) | nn.YOLO11 |
yolo11n.mud |
maixhub.com |
| 目标检测(精度) | nn.YOLO11 |
yolo11s.mud |
maixhub.com |
| 实例分割 | nn.YOLO11 |
yolo11n_seg.mud |
maixhub.com |
| 姿态估计 | nn.YOLO11 |
yolo11n_pose.mud |
maixhub.com |
| 旋转框检测 | nn.YOLO11 |
yolo11n_obb.mud |
maixhub.com |
| YOLOv5检测 | nn.YOLOv5 |
yolov5s.mud |
maixhub.com |
| YOLOv8检测 | nn.YOLOv8 |
yolov8n.mud |
maixhub.com |
| 人脸检测(通用) | nn.FaceDetector |
face_detector.mud |
maixhub.com |
| 人脸+关键点 | nn.Retinaface |
retinaface.mud |
maixhub.com |
| 手部关键点 | nn.HandLandmarks |
hand_landmarks.mud |
maixhub.com |
| OCR | nn.PPOCR |
pp_ocr.mud |
maixhub.com |
4.3 自定义模型(MaixHub 训练)
1. 在 https://maixhub.com 上传数据集
2. 选择模型架构(YOLO11推荐)
3. 在线训练 → 下载 .mud 文件
4. 传到设备 /root/models/ 目录
4.4 设备检测适配
from maix import sys
device = sys.device_id() # "maixcam" 或 "maixcam2"
if device == "maixcam2":
# MaixCAM2 (你用的设备)
detector = nn.YOLO11(model="/root/models/yolo11n.mud")
else:
# MaixCAM
detector = nn.YOLO11(model="/root/models/yolo11n_legacy.mud")
5. OpenCV 集成(对标你熟悉的 cv2)
5.1 核心转换
import cv2
from maix import image
# MaixPy Image → numpy (OpenCV)
img_cv = image.image2cv(img_maix, ensure_bgr=False, copy=False)
# ensure_bgr: True=转BGR(OpenCV默认), False=保持原格式
# copy: True=拷贝数据(慢), False=零拷贝共享内存(快)
# 用OpenCV处理...
processed_cv = cv2.Canny(img_cv, 50, 150)
# numpy → MaixPy Image(需要显示时)
img_show = image.cv2image(processed_cv, bgr=True, copy=False)
5.2 E 题中用到的 OpenCV 操作
import cv2
import numpy as np
# 1. 自适应二值化(处理不均匀光照)
binary = cv2.adaptiveThreshold(gray_cv, 255,
cv2.ADAPTIVE_THRESH_MEAN_C,
cv2.THRESH_BINARY_INV, 27, 31)
# 2. 洪泛填充(填充背景)
h, w = binary.shape[:2]
mask = np.zeros((h+2, w+2), np.uint8)
cv2.floodFill(binary, mask, (2,2), 255, loDiff=5, upDiff=5, flags=4)
binary = cv2.bitwise_not(binary)
# 3. 轮廓查找与多边形逼近
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
largest = max(contours, key=cv2.contourArea)
epsilon = 0.02 * cv2.arcLength(largest, True)
approx = cv2.approxPolyDP(largest, epsilon, True)
# 4. 透视变换
M = cv2.getPerspectiveTransform(src_pts, dst_pts) # 正变换
M_inv = np.linalg.inv(M) # 逆变换
img_warped = cv2.warpPerspective(img_cv, M, (w, h)) # 应用
# 坐标映射回原图
original_pt = cv2.perspectiveTransform(points, M_inv)
# 5. 霍夫圆检测
circles = cv2.HoughCircles(img_gray, cv2.HOUGH_GRADIENT,
dp=1.2, minDist=minDist,
param1=100, param2=20,
minRadius=r_min, maxRadius=r_max)
# 6. 高斯模糊
blurred = cv2.GaussianBlur(img_cv, (5, 5), 0)
5.3 色域转换
gray_cv = cv2.cvtColor(img_cv, cv2.COLOR_RGB2GRAY) # RGB → 灰度
bgr_cv = cv2.cvtColor(img_cv, cv2.COLOR_RGB2BGR) # RGB → BGR
hsv_cv = cv2.cvtColor(img_cv, cv2.COLOR_RGB2HSV) # RGB → HSV
6. 经典视觉 Pipeline 模板
模板1:纯AI检测 🟢 最常用
Camera → YOLO.detect() → 画框 → 显示/输出
from maix import camera, display, image, nn, app
detector = nn.YOLO11(model="/root/models/yolo11n.mud")
cam = camera.Camera(detector.input_width(), detector.input_height(), detector.input_format())
disp = display.Display()
while not app.need_exit():
img = cam.read()
objs = detector.detect(img, conf_th=0.5, iou_th=0.45)
for obj in objs:
img.draw_rect(obj.x, obj.y, obj.w, obj.h, image.COLOR_RED)
disp.show(img)
模板2:AI检测 + 传统精确定位 🟡 E题核心模式
Camera → YOLO粗检测 → 裁切ROI → 传统CV精确定位 → 坐标输出
import cv2
from maix import camera, display, image, nn, app
detector = nn.YOLOv5(model="/root/models/model_3356.mud", dual_buff=True)
cam = camera.Camera(448, 448, detector.input_format())
disp = display.Display()
while not app.need_exit():
img = cam.read()
# Step 1: resize送AI检测
img_ai = img.resize(detector.input_width(), detector.input_height())
objs = detector.detect(img_ai, conf_th=0.5, iou_th=0.45)
if len(objs) > 0:
obj = objs[0] # 取最大目标
# Step 2: 裁切ROI
crop = img_ai.crop(obj.x - 12, obj.y - 12, obj.w + 24, obj.h + 24)
# Step 3: OpenCV精确处理
gray = crop.to_format(image.Format.FMT_GRAYSCALE)
gray_cv = image.image2cv(gray, False, False)
binary = cv2.adaptiveThreshold(gray_cv, 255,
cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY_INV, 27, 31)
# Step 4: 找轮廓... (具体算法见E题代码)
contours, _ = cv2.findContours(binary, cv2.RETR_EXTERNAL,
cv2.CHAIN_APPROX_SIMPLE)
if contours:
largest = max(contours, key=cv2.contourArea)
epsilon = 0.02 * cv2.arcLength(largest, True)
approx = cv2.approxPolyDP(largest, epsilon, True)
if len(approx) == 4:
# 找到四边形!计算中心...
M = cv2.moments(approx)
cx = int(M['m10'] / M['m00'])
cy = int(M['m01'] / M['m00'])
img.draw_circle(cx + obj.x, cy + obj.y, 5, image.COLOR_RED, -1)
disp.show(img)
模板3:颜色追踪 + PID 🟢
Camera → find_blobs → 计算偏移 → PID → 舵机
from maix import camera, display, image, app
cam = camera.Camera(320, 240)
disp = display.Display()
th_red = [[0, 80, 40, 80, 10, 80]]
center_x, center_y = 160, 120 # 画面中心
while not app.need_exit():
img = cam.read()
blobs = img.find_blobs(th_red, area_threshold=500, pixels_threshold=200)
if blobs:
b = blobs[0] # 取最大色块
err_x = b.cx() - center_x
err_y = b.cy() - center_y
img.draw_circle(b.cx(), b.cy(), 5, image.COLOR_RED, -1)
img.draw_line(b.cx(), b.cy(), center_x, center_y, image.COLOR_RED, 2)
# 把 err_x, err_y 送入 PID 控制舵机
print(f"err: ({err_x}, {err_y})")
img.draw_cross(center_x, center_y, 10, image.COLOR_GREEN)
disp.show(img)
模板4:巡线 🔵
Camera → get_regression → 获取线角度/偏移 → 控制
th_line = [[0, 40, -20, 20, -20, 20]] # 黑线
while not app.need_exit():
img = cam.read()
lines = img.get_regression(th_line, area_threshold=100)
if lines:
line = lines[0]
# 计算与垂直线(90°)的偏差
theta = line.theta()
angle = 270 - theta if theta > 90 else 90 - theta
# angle为负 → 线偏左 → 车向右转
# angle为正 → 线偏右 → 车向左转
img.draw_line(line.x1(), line.y1(), line.x2(), line.y2(), image.COLOR_GREEN, 3)
img.draw_string(0, 0, f"angle: {angle:.1f}", image.COLOR_BLUE, scale=2)
disp.show(img)
模板5:多目标跟踪 + 计数 🔴
Camera → YOLO检测 → ByteTracker跟踪 → 过线计数
关键模块:
tracker.ByteTracker()- 多目标跟踪器tracker.Object(x, y, w, h, class_id, score)- 检测结果转跟踪对象- 参考
source/maixpy/examples/vision/tracker/tracker_bytetrack_count.py
7. 性能优化
7.1 帧率与分辨率
| 分辨率 | 典型帧率(纯采集) | 帧率(+YOLO11n) | 适用场景 |
|---|---|---|---|
| 320×240 | ~120 fps | ~30 fps | 追踪、巡线 |
| 640×480 | ~60 fps | ~15 fps | 识别、OCR |
| 224×224 | ~150 fps | ~50 fps | 极限速度 |
7.2 加速技巧
# 1. YUV格式替代RGB(内存减半)
cam = camera.Camera(320, 240, image.Format.FMT_YVU420SP)
# 2. stride参数加速色块检测
img.find_blobs(th, x_stride=2, y_stride=2) # 每2像素采样一次
# 3. ROI限制搜索范围
img.find_blobs(th, roi=[x, y, w, h]) # 只在感兴趣区域搜索
# 4. 零拷贝转换(OpenCV互操作时)
img_cv = image.image2cv(img, ensure_bgr=False, copy=False) # copy=False是关键!
# 5. FPS测量
import time
while True:
print(f"FPS: {time.fps():.1f}") # MaixPy内置FPS计数器
7.3 dual_buff 选择原则
dual_buff=True → 高帧率,高延迟(~1帧) → 纯检测场景
dual_buff=False → 低帧率,低延迟 → 实时追踪/控制场景 ⚠️
8. 通信与控制
8.1 UART 二进制输出(发给主控MCU)
from maix import uart, pinmap
import struct
# MaixCAM2 UART4: TX=A21, RX=A22
pinmap.set_pin_function("A21", "UART4_TX")
pinmap.set_pin_function("A22", "UART4_RX")
serial = uart.UART("/dev/ttyS4", 115200)
# 发送检测结果(小端字节序)
obj = detected_objects[0]
data = struct.pack("<hhHHHf", # h=short, H=ushort, f=float
obj.x, obj.y, obj.w, obj.h,
obj.class_id, obj.score)
serial.write(data)
# 接收
# serial.read() 或 serial.set_callback(lambda data: ...)
8.2 CommProtocol(高层协议,推荐)
from maix import comm, protocol
import struct
p = comm.CommProtocol(buff_size=1024)
# 发送上报消息
body = struct.pack("<hh", err_x, err_y)
p.report(cmd=0x02, body=body)
# 接收请求
msg = p.get_msg()
if msg and msg.is_req:
if msg.cmd == 0x01:
p.resp_ok(msg.cmd, b'OK')
8.3 PWM 舵机
from maix import pwm, pinmap
# MaixCAM2: A18=PWM6, A19=PWM7
pinmap.set_pin_function("A19", "PWM7")
servo = pwm.PWM(7, freq=50, duty=7.5, enable=True) # 50Hz, 7.5%=~1.5ms(中位)
servo.duty(5.0) # 0.5ms → 0°
servo.duty(12.5) # 2.5ms → 180°
9. 快速开发检查清单
开始写一个视觉模块前,问自己:
- 分辨率选对了吗?(追踪320×240,识别640×480)
- 摄像头格式和模型输入格式一致吗?(
detector.input_format()) - AI模型 dual_buff 开关合适吗?(追踪关,检测开)
- 帧率测了吗?(
time.fps()) - MaixCAM vs MaixCAM2 适配了吗?(
sys.device_id()) - 调试信息只画必要的吗?(
draw_string很耗性能,~7ms)
10. 参考资料速查
| 资料 | 路径/链接 |
|---|---|
| MaixPy API文档 | docs/wiki/api/ |
| 官方示例 | source/maixpy/examples/vision/ |
| 完整项目 | source/maixpy/projects/ ⭐ |
| MaixHub模型库 | https://maixhub.com |
| Sipeed Wiki | https://wiki.sipeed.com/maixpy/ |
看完本文后,你应该能:
- 写出 MaixCAM 上的 YOLO 检测程序
- 写出颜色追踪 + PID 程序
- 写出巡线程序
- 在 MaixPy 和 OpenCV 之间自由切换
- 理解 E 题的 AI+传统混合视觉 pipeline
- 按需查阅 API 文档扩展功能
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)