1. 项目概述与核心需求拆解
“运动目标控制与自动追踪系统”,这个题目一出来,很多参加过电赛或者做过类似项目的朋友应该会心一笑。它本质上是一个典型的“感知-决策-控制”闭环系统,而视觉部分,就是这个系统的“眼睛”和一部分“大脑”。题目要求系统能够识别特定的运动目标,并控制云台或执行机构(比如小车、机械臂)实现对目标的自动追踪。这听起来像是电影里的场景,但在今天,用一块K210这样的嵌入式AI芯片,加上一些开源算法,完全可以在赛场上实现。
这个题目的难点和魅力在于它的综合性。它绝不仅仅是调通一个图像识别算法那么简单。你需要考虑在资源受限的嵌入式平台上(K210算力有限,内存也小),如何稳定、快速、准确地完成从图像采集、目标检测、到坐标解算、再到与主控(如STM32)通信的完整链路。任何一个环节的延迟或抖动,都会在最终的追踪效果上被放大。所以,做这个题目,你实际上是在搭建一个微型的、实时的机器视觉系统。
视觉部分的核心任务可以拆解为三个层次:“看得见”、“认得准”、“传得快”。
- 看得见:指的是图像采集的稳定性和预处理的有效性。摄像头选型、安装、图像去畸变、白平衡、曝光调整,这些基础工作决定了后续算法能在一个多“干净”的数据上工作。
- 认得准:特指运动目标的检测与识别。这里又分两种情况:如果目标是形状、颜色有显著特征的(比如电赛常出的红色小球、特定图案的卡片),那么传统数字图像处理(OpenCV那一套)结合K210的硬件加速可能就够了;如果目标更复杂(比如特定的人、动物),那就需要用到轻量级的神经网络模型,在K210上部署运行。
- 传得快:指的是将识别结果(通常是目标在图像中的像素坐标、大小、类别等信息)以极低的延迟、稳定的格式发送给主控单片机。这里涉及到通信协议的设计(如串口自定义协议)、数据打包、以及可能的滤波算法(比如卡尔曼滤波预测目标位置,减少抖动)。
适合谁来参考这篇内容呢?首先是备战电赛E题或类似题目的同学,这是最直接的。其次是任何想学习如何在嵌入式设备上实现实时机器视觉的爱好者,无论是做智能小车、追踪云台还是简单的机械臂抓取,这里的思路和踩坑经验都是相通的。即使你只对其中一部分感兴趣,比如K210的模型部署或者OpenMV的用法,也能找到对应的干货。
2. 视觉系统整体方案设计与选型考量
接到题目,第一步不是急着写代码,而是定方案。方案选型直接决定了你后续开发的难度上限和性能天花板。对于电赛这种有时间限制的竞赛,选择一个成熟、稳定、社区支持好的方案至关重要。
2.1 核心硬件平台:为什么是K210?
K210在这类题目中几乎是“标配”,这不是没有道理的。它是一颗双核64位RISC-V CPU,但最核心的是它内置了KPU(神经网络处理器)和APU(音频处理器)。对于视觉任务,KPU是灵魂。它支持卷积、批归一化、激活函数等操作的硬件加速,能让你在极低的功耗下(典型值300mW),实时运行一些轻量级神经网络模型,比如MobileNetV1/YOLOv2的变种,进行人脸检测、物体分类等。
与传统的“STM32+OpenMV”或者“树莓派+摄像头”方案相比,K210的优势非常明显:
- 性价比与集成度:一颗芯片搞定图像采集、AI推理和基础控制逻辑,无需额外的Linux系统,启动速度快,系统更简单可靠。
- 功耗与实时性:专为边缘AI设计,功耗远低于树莓派,且推理过程是硬件加速,延迟确定性强,适合对实时性要求高的追踪场景。
- 开发生态:虽然有嘉楠科技官方SDK、MaixPy(MicroPython)等多种开发方式,但社区围绕MaixPy和诸如“MaixHub”模型平台构建了丰富的资源,很多现成的目标检测模型可以一键部署。
当然,它也有局限。KPU对模型结构有特定要求(需要是KModel格式),内存(8MB)限制了输入图像分辨率和模型复杂度,双核CPU的主频(400MHz)在处理复杂图像算法时也可能成为瓶颈。因此,我们的方案设计必须“量体裁衣”。
2.2 软件框架选择:MicroPython vs C SDK
这是第二个关键抉择。主流有两种路径:
- MaixPy(MicroPython):上手极快,语法简单,交互式开发调试方便。官方和社区提供了大量高层API,例如
image.find_blobs(找色块)、kpu.load(加载模型)等,让你用十几行代码就能跑起一个视觉程序。对于电赛这种追求快速原型的场景,MaixPy往往是首选。 - 官方C SDK(Kendryte IDE):性能更高,对硬件底层控制更精细,内存管理更自主。如果你需要榨干K210的每一分性能,或者要实现非常定制化的图像预处理流水线,C语言是更优选择。但开发调试周期长,对参赛者的C语言和嵌入式功底要求高。
我的建议是:对于绝大多数电赛队伍,优先选择MaixPy。它的开发效率优势在紧张的比赛周期中是决定性的。我们完全可以通过优化代码结构、合理使用硬件加速模块(如FFT、AI)来弥补解释型语言的速度损失。本文后续的实操也将基于MaixPy展开。
2.3 目标检测算法选型:传统图像处理 vs 神经网络
这是技术路线的核心分岔口,需要根据题目给出的具体目标来决定。
方案A:传统数字图像处理(OpenCV算法思想)
- 适用场景:目标具有鲜明的、可与背景分离的颜色特征(如红色小球、绿色激光点)或形状特征(如黑色矩形框、圆形图案)。
- 实现方法:
- 颜色阈值化:将RGB图像转换到HSV颜色空间,针对目标的颜色范围(如红色的H值范围)设置阈值,得到二值图像。
- 形态学操作:对二值图像进行腐蚀、膨胀,消除噪点,连接断裂区域。
- 轮廓查找与筛选:找出所有轮廓,根据面积、周长、宽高比、圆形度等几何特征,筛选出最可能是目标的轮廓。
- 位置计算:计算选中轮廓的最小外接矩形或中心点,得到像素坐标。
- 优点:算法简单,计算量极小,在K210上可以跑到很高的帧率(>50fps),稳定性好,可预测性强。
- 缺点:对环境光线变化敏感,如果背景中出现颜色相近的干扰物,容易误判。
方案B:轻量级神经网络(基于KPU)
- 适用场景:目标特征复杂,颜色形状不唯一(如特定的人、动物、交通标志),或者需要同时识别多个不同类别的目标。
- 实现方法:
- 模型准备:使用YOLO、MobileNet-SSD等框架,在自己的数据集或公开数据集上训练一个轻量级目标检测模型,然后通过NNCase等工具转换为K210支持的
.kmodel格式。 - 模型部署:在MaixPy中使用
kpu模块加载kmodel,设置输入分辨率(通常是224x224或320x240),进行前向推理。 - 结果解析:解析KPU输出的检测结果,通常包括类别ID、置信度、边界框坐标。需要将这些坐标从模型输入尺度映射回原始图像尺度。
- 模型准备:使用YOLO、MobileNet-SSD等框架,在自己的数据集或公开数据集上训练一个轻量级目标检测模型,然后通过NNCase等工具转换为K210支持的
- 优点:识别能力强,抗干扰能力好,对光线变化相对鲁棒,能处理复杂目标。
- 缺点:开发周期长(需要数据采集、标注、训练、转换),模型会占用大量内存,帧率相对较低(可能只有5-15fps),对芯片发热有一定影响。
实操心得:在电赛环境中,除非题目明确要求识别复杂物体,否则优先考虑传统方案。它的稳定性和高帧率对于需要快速响应的追踪系统来说是无价的。你可以用神经网络作为备选或辅助方案,比如先用颜色筛选出候选区域,再用一个微型的分类网络确认是不是目标,这样可以平衡速度和精度。
3. 核心模块实现与代码级详解
方案定好,我们就进入具体的实现环节。这里我以一个典型的“追踪色块(比如红色小球)”场景为例,用MaixPy进行分步拆解。假设我们的硬件是Sipeed Maix Dock(K210开发板)搭配一颗OV2640摄像头。
3.1 硬件连接与环境初始化
首先确保硬件连接正确。摄像头通常通过DVP接口与K210连接,在Maix Dock上一般是插接好的。串口用于调试和与STM32通信,注意TX、RX要交叉连接。
import sensor, image, time, lcd from machine import UART from fpioa_manager import fm # 1. 初始化LCD(如果有的话,用于实时预览) lcd.init() # 2. 初始化摄像头 sensor.reset() # 复位摄像头 sensor.set_pixformat(sensor.RGB565) # 设置像素格式,RGB565是彩色,处理速度快 sensor.set_framesize(sensor.QVGA) # 设置分辨率:320x240。更高的分辨率如VGA(640x480)会降低帧率。 sensor.skip_frames(time = 2000) # 跳过开始几帧,等待摄像头稳定 sensor.set_auto_gain(False) # 关闭自动增益(重要!) sensor.set_auto_whitebal(False) # 关闭自动白平衡(重要!) # 可以手动设置增益和白平衡,确保颜色稳定 # sensor.set_auto_exposure(False, exposure_us=5000) # 手动曝光在某些光照下有用 # 3. 初始化串口,用于与STM32通信 fm.register(6, fm.fpioa.UART1_RX, force=True) # 根据板子实际引脚映射 fm.register(7, fm.fpioa.UART1_TX, force=True) uart = UART(UART.UART1, 115200, 8, 0, 1, timeout=1000, read_buf_len=4096) clock = time.clock() # 创建一个时钟对象来跟踪FPS关键参数解析:
sensor.set_framesize(sensor.QVGA):选择QVGA(320x240)是平衡帧率和识别精度的常见选择。分辨率越高,处理耗时越长。对于追踪一个色块,QVGA足够。sensor.set_auto_gain(False)和sensor.set_auto_whitebal(False):这是颜色追踪稳定的关键!自动功能会让摄像头根据环境光动态调整,导致你设定的颜色阈值失效。必须关闭,并可能在比赛现场根据光线微调。UART初始化:波特率115200是常用值。timeout和read_buf_len根据通信数据量调整。
3.2 图像采集与颜色阈值化
接下来是核心的图像处理循环。
# 定义红色的阈值。HSV颜色空间比RGB更接近人眼对颜色的感知。 # 在HSV中,Hue(色调)范围是0-180(OpenCV中),Saturation(饱和度)和Value(明度)是0-255。 # 红色在HSV环的两端,所以通常需要两个区间。 red_thresholds = [(30, 80, 15, 80, 15, 80)] # 这是一个示例,需要实际调试! # 格式通常是 (L_H, L_S, L_V, H_H, H_S, H_V) 即低值和高值。 while(True): clock.tick() # 开始计时 img = sensor.snapshot() # 抓取一帧图像 # 方法1:使用 find_blobs 直接找色块(最常用) blobs = img.find_blobs([red_thresholds], pixels_threshold=50, area_threshold=50, merge=True) # pixels_threshold: 像素点数阈值,过滤噪点 # area_threshold: 面积阈值 # merge: 合并相邻的色块 if blobs: # 假设我们找面积最大的那个色块 max_blob = max(blobs, key=lambda b: b.area()) # 在图像上画框,可视化(调试用) img.draw_rectangle(max_blob.rect(), color=(0, 255, 0)) img.draw_cross(max_blob.cx(), max_blob.cy(), color=(0, 255, 0)) # 计算目标在图像中的归一化坐标(-1到1之间),方便发送给云台控制器 img_width = img.width() img_height = img.height() target_x = (max_blob.cx() - img_width / 2) / (img_width / 2) # 范围[-1, 1],中心为0 target_y = (max_blob.cy() - img_height / 2) / (img_height / 2) # 范围[-1, 1],中心为0 # 打包数据,准备发送。例如,发送“X0.75Y-0.12\n” data_to_send = "X{:.2f}Y{:.2f}\n".format(target_x, target_y) uart.write(data_to_send) else: # 没有找到目标,可以发送一个特定指令,比如让云台停止或缓慢扫描 uart.write("X0.00Y0.00\n") # 或者发送一个搜索指令 # 在LCD上显示图像和FPS(调试用) img.draw_string(0, 0, "FPS:%.1f" % clock.fps(), color=(255,0,0)) lcd.display(img)调试技巧:如何确定颜色阈值?MaixPy IDE通常有一个“阈值编辑器”工具。你可以先运行一个简单的脚本实时显示摄像头画面,然后用取色工具框选目标区域,它会自动给出HSV的阈值范围。在现场,务必在比赛场地实际的光照条件下重新校准阈值。
3.3 与STM32的通信协议设计
通信的稳定性和解析效率直接影响系统响应。设计一个简单高效的协议很重要。
协议示例(自定义ASCII协议):
- 数据帧格式:
[帧头][数据X][分隔符][数据Y][帧尾] - 例如:
“X0.75Y-0.12\n”- 帧头:
X - 数据X:
0.75(浮点数,字符串形式) - 分隔符:
Y - 数据Y:
-0.12 - 帧尾:
\n(换行符,作为帧结束标志)
- 帧头:
在STM32端(以HAL库为例)的解析代码逻辑:
// 假设使用串口中断接收 uint8_t rx_buffer[32]; uint8_t rx_index = 0; float target_x = 0, target_y = 0; void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) { if(huart->Instance == USART1) { uint8_t rx_char = rx_buffer[rx_index]; if(rx_char == '\n') { // 检测到帧尾 rx_buffer[rx_index] = '\0'; // 字符串结束符 // 解析数据,例如使用sscanf if(sscanf((char*)rx_buffer, "X%fY%f", &target_x, &target_y) == 2) { // 成功解析,更新控制器的目标值 // PID_Update(target_x, target_y); } rx_index = 0; // 重置索引 } else if(rx_index < sizeof(rx_buffer)-1) { rx_index++; } else { rx_index = 0; // 防止溢出 } HAL_UART_Receive_IT(huart, &rx_buffer[rx_index], 1); // 重新开启中断接收下一个字符 } }为什么用\n作帧尾?因为它是一个不可见的控制字符,在正常数据中几乎不会出现,可以可靠地标识一帧结束。比用特定数据字节更简单。
3.4 进阶处理:滤波与预测
直接发送原始的检测坐标会导致云台控制抖动严重,因为视觉检测存在噪声。我们需要引入滤波算法。
最简单的移动平均滤波:
# 在循环外初始化 filter_window_size = 5 x_history = [0] * filter_window_size y_history = [0] * filter_window_size history_index = 0 # 在找到目标后,更新历史记录并计算平均值 x_history[history_index] = target_x y_history[history_index] = target_y history_index = (history_index + 1) % filter_window_size filtered_x = sum(x_history) / filter_window_size filtered_y = sum(y_history) / filter_window_size # 发送 filtered_x, filtered_y更优的选择——卡尔曼滤波:对于匀速或匀加速运动的物体,卡尔曼滤波能很好地预测下一时刻的位置,从而补偿处理延迟,让追踪更平滑。虽然MaixPy上实现完整的卡尔曼滤波稍复杂,但对于有能力的队伍,这是一个巨大的加分项。其核心思想是利用运动模型预测位置,再与视觉测量值进行加权融合,得到最优估计。
4. 神经网络模型部署流程详解(备选方案)
当传统方法不适用时,就需要上神经网络。这里简述从训练到部署的完整流程。
4.1 模型训练与转换
- 数据采集与标注:使用摄像头拍摄目标在不同角度、距离、光照下的图片,至少几百张。使用LabelImg等工具标注出目标边界框,生成PASCAL VOC格式的XML文件或YOLO格式的txt文件。
- 选择与训练模型:由于K210的KPU支持有限,通常选择:
- YOLOv2 Tiny:检测精度和速度平衡较好,社区转换教程多。
- MobileNetV1-SSD:轻量化,适合小目标检测。 使用PyTorch或TensorFlow(Keras)框架在PC上进行训练。重点在于模型要足够小,输入尺寸常用224x224或320x240。
- 模型转换:使用NNCase工具链。这是一个将训练好的模型(如ONNX、TFLite)转换为KModel的命令行工具。转换过程可能会遇到算子不支持、量化精度损失等问题,需要仔细查阅NNCase文档和社区案例。
4.2 MaixPy加载与推理
import KPU as kpu import gc # 加载模型 task = kpu.load("/sd/your_model.kmodel") # 模型放在SD卡中 # 设置模型输入形状 anchor = (1.08, 1.19, 3.42, 4.41, 6.63, 11.38, 9.42, 5.11, 16.62, 10.52) # YOLO的anchor,需要根据训练时配置 kpu.init_yolo2(task, 0.5, 0.3, 5, anchor) # 阈值0.5,NMS阈值0.3,5个anchor while(True): img = sensor.snapshot() # 运行推理 objects = kpu.run_yolo2(task, img) if objects: for obj in objects: # 绘制检测框 img.draw_rectangle(obj.rect()) # 获取坐标信息 x, y, w, h = obj.rect() target_x = (x + w//2 - img.width()/2) / (img.width()/2) target_y = (y + h//2 - img.height()/2) / (img.height()/2) # ... 发送数据 ... else: # 未检测到目标 pass gc.collect() # K210内存小,定期垃圾回收很重要注意事项:神经网络模型推理会消耗大量内存。务必在代码中定期调用
gc.collect()进行垃圾回收,否则很快会内存溢出导致程序崩溃。同时,模型加载后,会常驻内存,不要再进行动态加载/卸载。
5. 系统联调与性能优化实战
当视觉模块单独工作稳定后,就要和STM32主控联调,并优化整个系统的性能。
5.1 帧率与延迟优化
追踪系统的实时性至关重要。你需要测量并优化两个关键指标:视觉处理帧率(FPS)和端到端延迟(从目标移动,到云台开始响应的时间)。
测量FPS:上面的代码中已经用
clock.fps()在计算。确保在最终比赛代码中移除或禁用LCD显示,因为显示操作非常耗时,可能使FPS下降一半以上。优化FPS:
- 降低分辨率:从QVGA降到QQVGA(160x120),处理速度会成倍提升。对于不远的目标,可能够用。
- 减少处理区域(ROI):如果目标大致出现在画面某个区域,可以只对那一部分图像进行处理。
img.crop()出一个区域再处理。 - 简化算法:在保证识别率的前提下,减少形态学操作次数,简化轮廓分析的逻辑。
- 关闭调试功能:移除所有
draw_rectangle,draw_string,lcd.display等函数。 - 使用硬件加速:K210的FPIOA、FFT等模块可以加速特定运算,但MaixPy高层API可能封装了,底层优化需要深入C层。
测量与降低延迟:
- 通信延迟:提高串口波特率(如921600),确保数据帧尽可能短。
- 处理流水线:尝试使用双缓冲或多线程(虽然MaixPy对多线程支持有限)。一个核心用于图像采集和预处理,另一个核心用于算法处理和通信。
- 预测算法:如前所述,使用卡尔曼滤波预测下一帧位置,可以抵消一部分处理延迟的影响。
5.2 稳定性与鲁棒性提升
系统在现场必须稳定运行数小时。以下措施能极大提升稳定性:
- 防丢帧与异常处理:在
while循环中加入异常捕获,防止某次图像处理异常导致整个程序崩溃。try: img = sensor.snapshot() # ... 处理过程 ... except Exception as e: print("Error:", e) continue - 看门狗:如果使用MaixPy的C模块或自己写C代码,可以启用硬件看门狗,在程序卡死时自动复位。
- 电源管理:K210全速运行时会发热。确保供电充足(5V/2A以上),必要时加装小型散热片。电压不稳会导致摄像头采集花屏或芯片复位。
- 环境光适应性:如果比赛场地光照可能变化,可以考虑:
- 自动曝光/增益算法:虽然我们关闭了自动模式,但可以自己写一个简单的算法,定期根据图像整体亮度调整
sensor.set_auto_exposure的参数。 - 动态阈值:根据图像统计信息(如平均亮度、颜色直方图)动态微调颜色阈值。
- 多阈值切换:准备几套针对不同光照条件的阈值参数,通过一个光敏电阻或摄像头图像平均亮度来判断并切换。
- 自动曝光/增益算法:虽然我们关闭了自动模式,但可以自己写一个简单的算法,定期根据图像整体亮度调整
5.3 与STM32的协同调试
- 约定握手协议:上电后,K210和STM32可以互相发送一个就绪信号(如
READY\n),确保双方通信链路正常后再开始传输数据。 - 增加心跳包:除了目标数据,定期(如每秒一次)发送一个心跳包(如
HEART\n)。STM32如果一段时间收不到心跳,可以判断视觉模块异常,进入安全模式(如云台回中)。 - 数据校验:在自定义协议中加入简单的校验和,例如将数据X和Y的字节相加取低8位,附在帧尾。STM32解析后验算,校验失败则丢弃该帧。
- 联合调试:最好能实时观察K210发送的数据和STM32解析后的数据。可以让STM32将收到的坐标通过另一个串口打印到电脑,或者用无线模块发回电脑,与K210的原始数据对比。
6. 现场调试清单与常见问题排坑指南
到了比赛现场,时间紧迫,心态容易慌。按照一个清晰的清单来调试,可以事半功倍。
6.1 上电前检查清单
- [ ]硬件连接:摄像头排线是否插紧?串口线TX/RX是否接反?电源线是否牢固?
- [ ]电源:使用万用表测量供电电压是否稳定在5V左右?电流能力是否足够(建议2A以上)?
- [ ]SD卡:如果模型放在SD卡,卡是否格式化为FAT32?模型文件路径在代码中是否正确?
6.2 上电后调试步骤
- 基础功能测试:先运行一个最简单的摄像头预览程序,确认LCD或通过IDE能正常看到图像。
- 颜色阈值校准:在比赛场地实际光照下,使用阈值编辑器重新标定颜色阈值。注意不同距离下颜色可能会有变化,最好在追踪范围内多取几个点求平均。
- 单独测试视觉:断开与STM32的通信,让视觉程序只识别并在图像上画框,同时打印坐标到串口终端。观察识别是否稳定,帧率是否达标。
- 单独测试控制:让STM32程序运行,通过电脑串口手动发送模拟的坐标数据(如
X0.5Y0.0\n),观察云台是否能正确运动到相应位置。 - 系统联调:连接两者,进行慢速追踪测试。观察是否有抖动、延迟、丢失目标的情况。
6.3 常见问题与解决方案速查表
| 问题现象 | 可能原因 | 排查步骤与解决方案 |
|---|---|---|
| 摄像头无图像/花屏 | 1. 摄像头排线接触不良。 2. 电源功率不足。 3. 传感器初始化代码错误。 | 1. 重新插拔排线。 2. 更换更大功率电源(5V2A以上)。 3. 检查 sensor.reset()和set_pixformat等参数,尝试降低分辨率。 |
| 颜色识别不稳定,时有时无 | 1. 自动白平衡/增益未关闭。 2. 环境光变化。 3. 阈值设置不合理。 | 1. 确认代码中已设置sensor.set_auto_gain(False)和sensor.set_auto_whitebal(False)。2. 固定光源,或实现动态阈值/多阈值。 3. 在现场重新校准阈值,适当放宽阈值范围。 |
| 帧率(FPS)过低 | 1. LCD显示未关闭。 2. 图像分辨率过高。 3. 算法过于复杂。 4. 内存不足频繁GC。 | 1. 注释掉lcd.display(img)和所有draw函数。2. 降低 set_framesize。3. 简化图像处理流程。 4. 减少全局变量,及时释放大对象,手动 gc.collect()。 |
| 串口通信数据乱码或丢失 | 1. 波特率不匹配。 2. 接线错误(TX/RX反)。 3. 未处理接收缓冲区溢出。 4. 地线未共地。 | 1. 检查K210和STM32代码中的波特率设置是否一致。 2. 交换TX和RX线序。 3. 在STM32端增加接收超时和缓冲区清空机制。 4. 确保K210和STM32的GND连接在一起。 |
| 追踪时云台抖动严重 | 1. 视觉坐标噪声大。 2. 通信延迟或丢包。 3. STM32端PID参数不合适。 | 1. 在K210端增加移动平均或卡尔曼滤波。 2. 提高波特率,优化通信协议,增加校验。 3. 调整STM32的PID控制器的P、I、D参数,降低P值,增加微分项D来抑制振荡。 |
| 目标快速移动时丢失 | 1. 视觉处理帧率太低。 2. 无预测算法。 3. 云台响应速度慢。 | 1. 全力优化视觉帧率(见5.1节)。 2. 实现简单的线性预测或卡尔曼滤波。 3. 检查云台电机驱动能力,提高控制频率。 |
| 程序运行一段时间后死机 | 1. 内存泄漏。 2. 芯片过热。 3. 看门狗未启用。 | 1. 检查代码中是否有循环内不断创建大对象(如列表、图像),使用gc.mem_free()监控内存。2. 加强散热,降低主频( kpu.set_clocks)。3. 考虑使用C SDK并启用硬件看门狗。 |
| 神经网络模型检测不到目标 | 1. 模型转换错误。 2. 输入图像预处理不一致。 3. 置信度阈值过高。 | 1. 用PC端工具验证原始模型和转换后模型在相同输入下的输出是否一致。 2. 确保训练和部署时,图像的归一化、缩放方式完全一致。 3. 降低 kpu.init_yolo2中的阈值参数。 |
最后,再分享一个临场经验:比赛时,准备一个“应急模式”的代码版本。这个版本可以牺牲一些精度和功能,但绝对稳定。比如,当主算法因为光线突变失效时,可以一键切换到仅追踪最大亮斑或最简单色块的模式,先让系统动起来,保住基础分。把复杂的自适应算法作为加分项,而不是赌注。硬件上,多带几根排线、备用摄像头和电源模块,这些小东西往往是救命稻草。视觉部分调试时,耐心比什么都重要,一遍遍微调参数,观察现象,理解数据流,当你看到云台稳稳锁住运动目标的那一刻,所有的折腾都值了。