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)

阈值调参技巧

  1. 用 MaixVision 的「阈值编辑器」工具实时调参
  2. L 通道管亮度,A 通道管红绿,B 通道管蓝黄
  3. 增大 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/

看完本文后,你应该能:

  1. 写出 MaixCAM 上的 YOLO 检测程序
  2. 写出颜色追踪 + PID 程序
  3. 写出巡线程序
  4. 在 MaixPy 和 OpenCV 之间自由切换
  5. 理解 E 题的 AI+传统混合视觉 pipeline
  6. 按需查阅 API 文档扩展功能
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐