1. MaixCam开发板的人脸识别与串口通信实战
最近在折腾MaixCam这块AI视觉开发板,发现它的人脸识别功能配合串口通信特别适合做智能门禁、考勤机这类项目。板子自带高性能K210芯片,跑人脸检测模型能到30FPS以上,通过串口发送识别结果给主控板的方案既稳定又省资源。今天就把我这段时间的踩坑经验和完整实现方案分享给大家。
MaixCam最大的优势在于把摄像头、屏幕和算力集成在一块板子上,开发者不用再头疼外设兼容性问题。我实测下来,它的人脸检测模型在室内光照下识别率能达到95%以上,通过串口发送坐标和ID信息给STM32这类主控板,延迟可以控制在50ms以内。下面从硬件连接、模型部署到协议设计,我会把每个环节的注意事项都交代清楚。
2. 硬件准备与环境搭建
2.1 MaixCam开发板特性说明
这块板子核心是双核64位RISC-V K210处理器,带硬件AI加速器(KPU),最高能跑0.8TOPS算力。板载OV7740摄像头(30万像素)和2.4寸LCD屏幕,最关键的是自带USB转串口芯片CH340,省去了额外买转换模块的麻烦。我对比过其他视觉开发板,MaixCam在功耗和性价比上优势明显——跑满人脸检测整板功耗才1.2W,用移动电源都能供电。
注意:新到手的板子要先短接背面BOOT引脚再上电,才能进入固件烧录模式。我第一次用没注意这个细节,折腾了半天才发现是驱动没装好。
2.2 开发环境配置步骤
官方推荐用MaixPy IDE,基于VSCode魔改的专用版本。安装时要注意:
- 到MaixHub官网下载最新版IDE(v0.4.2以上)
- 安装CH340驱动(Mac用户需要手动信任驱动)
- 连接板子后,在IDE右下角选择正确的串口号
测试环境是否正常:
python复制import sensor
sensor.reset()
print(sensor.get_fb().size()) # 应输出屏幕分辨率(320*240)
如果报错"No module named 'sensor'",说明固件版本太旧。更新固件要用kflash_gui工具,选择最新带kmodel支持的bin文件(如maixcam_v0.6.2.bin),波特率设到1500000能加快烧录速度。
3. 人脸识别模型部署
3.1 模型选择与优化
官方提供了三种预训练模型:
- 轻量版face_detect(80KB,仅检测)
- 通用版face_recognize(350KB,带5点特征)
- 高精度版face_landmark(1.2MB,68点特征)
我建议先用轻量版测试性能:
python复制import KPU as kpu
task = kpu.load(0x300000) # 加载flash中的模型
kpu.set_outputs(task, 0, 1, 1, 7) # 设置输出层格式
实测发现输入图像缩放到224x224时,推理速度最快(约15ms)。如果画面中人脸较小,可以改用160x120分辨率,但要注意最小检测人脸设为20x20:
python复制sensor.set_framesize(sensor.QVGA) # 320x240
sensor.set_windowing((224, 224)) # 中央裁剪
3.2 识别结果处理技巧
模型输出的数据结构要注意解析:
- 坐标值是0~1的归一化数值
- 置信度score大于0.8才判定为有效人脸
- 多人脸场景下用NMS(非极大值抑制)避免重复框
这里有个优化点——把浮点运算转为整型能提升速度:
python复制def parse_det_result(output):
faces = []
for i in range(output[0]): # 人脸数量
x = int(output[7*i+1] * 224) # 转为像素坐标
y = int(output[7*i+2] * 224)
w = int(output[7*i+3] * 224)
h = int(output[7*i+4] * 224)
if output[7*i+5] > 0.8: # 置信度筛选
faces.append((x,y,w,h))
return faces
4. 串口通信协议设计
4.1 数据帧格式定义
和STM32通信建议采用自定义协议,格式如下:
code复制帧头(2B) | 长度(1B) | 命令字(1B) | 数据(NB) | 校验(1B) | 帧尾(2B)
0xAA55 LEN CMD DATA SUM 0x55AA
具体到人脸数据,我设计了两类指令:
- 实时坐标指令(CMD=0x01):
python复制# 数据结构:X坐标(2B) | Y坐标(2B) | 宽度(2B) | 高度(2B) b'\xAA\x55\x08\x01\x00\x80\x00\x60\x00\x40\x00\x30\xXX\x55\xAA' - 识别结果指令(CMD=0x02):
python复制# 数据结构:ID(1B) | 置信度(1B) | 姓名长度(1B) | 姓名(UTF8) b'\xAA\x55\x0A\x02\x01\x5F\x03\xE5\xBC\xA0\xXX\x55\xAA'
4.2 波特率与流控设置
实测发现115200波特率下连续发送会出现丢帧,推荐改用460800:
python复制from machine import UART
uart = UART(UART.UART1, 460800, 8, 0, 1, timeout=100)
如果主控板不支持高速波特率,可以:
- 添加硬件流控(RTS/CTS)
- 改用数据压缩(如Base64编码坐标值)
- 降低发送频率(如每3帧发一次数据)
5. 完整实现代码解析
5.1 主程序流程图
- 初始化摄像头和LCD
- 加载KPU模型
- 进入主循环:
- 捕获图像 → 推理 → 解析结果
- 绘制检测框到LCD
- 通过串口发送数据
- 接收主控板指令(如拍照存档)
5.2 关键代码片段
python复制import json
from fpioa_manager import fm
# 引脚映射(根据板子版本调整)
fm.register(35, fm.fpioa.UART1_TX, force=True)
fm.register(34, fm.fpioa.UART1_RX, force=True)
def send_face_data(uart, faces):
for i, (x,y,w,h) in enumerate(faces):
# 转为字节数据(大端序)
data = bytearray([x>>8, x&0xFF, y>>8, y&0xFF])
# 计算校验和
checksum = sum(data) & 0xFF
# 组装完整帧
frame = b'\xAA\x55\x04\x01' + data + bytes([checksum]) + b'\x55\xAA'
uart.write(frame)
while True:
img = sensor.snapshot()
outputs = kpu.forward(task, img)[:] # 获取推理结果
faces = parse_det_result(outputs)
# 显示检测框
for rect in faces:
img.draw_rectangle(rect, color=(0,255,0))
# 串口发送
if len(faces) > 0:
send_face_data(uart, faces)
6. 典型问题排查指南
6.1 串口通信异常
| 现象 | 排查步骤 | 解决方案 |
|---|---|---|
| 接收乱码 | 1. 用逻辑分析仪抓波形 2. 检查两端波特率 3. 测试TX/RX交叉连接 |
改用固定波特率 添加起始位检测代码 |
| 数据截断 | 1. 检查帧长度字段 2. 测量电源电压 3. 查看缓冲区大小 |
增加帧间隔时间 减小单帧数据量 |
| 校验失败 | 1. 打印原始十六进制 2. 重算校验和 3. 检查字节序 |
改用CRC8校验 统一使用小端序 |
6.2 人脸识别不准
- 漏检问题:调整
set_contrast(3)提升对比度,或改用set_auto_gain(True) - 误检问题:在kpu.run_yolo2()后添加置信度过滤,如
if obj.score() < 0.7: continue - 速度慢:关闭LCD实时显示,用
sensor.skip_frames(2)跳帧处理
7. 性能优化技巧
-
内存管理:定期调用
gc.collect()避免内存泄漏,特别是在持续运行场景下 -
多任务处理:用
_thread模块创建独立线程处理串口通信,避免阻塞主循环:
python复制import _thread
def uart_thread():
while True:
if uart.any():
data = uart.read()
process_cmd(data)
_thread.start_new_thread(uart_thread, ())
- 模型量化:用nncase工具将float32模型转为int8,体积缩小4倍,速度提升2倍:
bash复制./nncase --target k210 --dataset images/ quantize face_model.tflite face_model.kmodel
- 电源优化:关闭未用外设降低功耗
python复制sensor.shutdown(False) # 关闭摄像头
lcd.display_off() # 关闭背光
这套方案已经用在我们的智能快递柜项目上,连续运行三个月没出过问题。最后提醒下,MaixCam的GPIO驱动能力较弱,直接接继电器要加三极管放大电路。如果要做产品化,建议用隔离式串口模块保护核心板。