
本文详解如何在 Raspberry Pi 上基于 TensorFlow Lite Object Detection 模型实现“检测到人时触发红框高亮+蜂鸣报警”,重点解决 DetectionResult 对象不可迭代的常见错误,并提供完整可运行的修复代码与最佳实践。
本文详解如何在 raspberry pi 上基于 tensorflow lite object detection 模型实现“检测到人时触发红框高亮+蜂鸣报警”,重点解决 `detectionresult` 对象不可迭代的常见错误,并提供完整可运行的修复代码与最佳实践。
在使用 tflite_support.task.vision.ObjectDetector 进行实时目标检测时,一个典型需求是:当模型识别出特定类别(如 "person")时,立即触发报警——例如播放提示音、在视频画面上绘制醒目的红色边框。然而,初学者常因误读 API 结构而遭遇 TypeError: 'DetectionResult' object is not iterable 错误。该错误的根本原因在于:detector.detect() 返回的是 DetectionResult 实例,而非直接可遍历的检测列表;其真实检测结果需通过 .detections 属性访问。
✅ 正确访问检测结果
DetectionResult 是一个封装类,包含 detections(List[Detection])、rotation 等字段。必须显式访问 .detections 才能安全迭代:
# ❌ 错误写法(导致 TypeError)
for obj in detection_result:
if obj.class_name == "person":
...
# ✅ 正确写法
for detection in detection_result.detections:
if detection.categories[0].label == alarm_label: # 注意:类别信息在 categories[0]
alarm_triggered = True
alarm_sound.play()
break # 可选:检测到即触发,避免重复播放? 补充说明:detection.categories 是一个列表(即使只设 max_results=1),每个元素为 Category 对象,含 label(字符串标签)、score(置信度)。因此应使用 detection.categories[0].label 而非 detection.class_name(该属性不存在,属常见误解)。
✅ 完整修复后的核心逻辑段(整合进原 run() 函数)
# ...(初始化部分保持不变)
while cap.isOpened():
success, image = cap.read()
if not success:
sys.exit('ERROR: Unable to read from webcam.')
counter += 1
image = cv2.flip(image, 1)
rgb_image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
input_tensor = vision.TensorImage.create_from_array(rgb_image)
detection_result = detector.detect(input_tensor)
# ✅ 正确解析 detections 并触发报警
alarm_triggered = False
for detection in detection_result.detections:
# 确保 detection 至少有一个 category
if detection.categories and detection.categories[0].label == alarm_label:
alarm_triggered = True
# 避免连续帧重复播放(可选防抖)
if not hasattr(alarm_sound, '_playing') or not alarm_sound.get_busy():
alarm_sound.play()
break
# 可视化:绘制红框边框(全屏高亮)
if alarm_triggered:
cv2.rectangle(image, (0, 0), (width, height), (0, 0, 255), thickness=4)
# 绘制检测框与标签(调用 utils.visualize,它内部已处理 detection_result.detections)
image = utils.visualize(image, detection_result)
# FPS 计算与显示(保持不变)
if counter % fps_avg_frame_count == 0:
end_time = time.time()
fps = fps_avg_frame_count / (end_time - start_time)
start_time = time.time()
cv2.putText(image, f'FPS = {fps:.1f}', (left_margin, row_size),
cv2.FONT_HERSHEY_PLAIN, font_size, text_color, font_thickness)
cv2.imshow('object_detector', image)
if cv2.waitKey(1) == 27: # ESC 退出
break
cap.release()
cv2.destroyAllWindows()⚠️ 注意事项与优化建议
- 音频资源准备:确保 alarm1.wav 文件存在且格式兼容(推荐 16-bit PCM WAV,采样率 ≤ 44.1kHz),并提前测试 pygame.mixer.Sound() 加载是否成功。
- 报警防抖:直接每帧播放声音会导致刺耳连续蜂鸣。建议增加状态判断(如 alarm_sound.get_busy())或引入最小触发间隔(如 time.time() - last_alarm_time > 1.0)。
-
性能优化(Raspberry Pi 4):
- 使用 --enableEdgeTPU + Coral USB Accelerator 可显著提速;
- 降低输入分辨率(如 --frameWidth 320 --frameHeight 240);
- 设置 num_threads=2 避免多线程调度开销。
- 标签匹配健壮性:实际模型输出的 label 可能含空格或大小写差异(如 "Person"),建议统一转小写比对:detection.categories[0].label.lower() == alarm_label.lower()。
- 边界绘制增强:除全屏红框外,也可仅高亮检测框本身(utils.visualize 已内置绘制逻辑),或叠加半透明红色遮罩层提升视觉冲击力。
通过修正 detection_result.detections 的访问方式,并结合轻量级音视频反馈设计,即可在树莓派上稳定部署低延迟的人体入侵报警系统——兼顾实用性与工程严谨性。

















