目标检测检测辅助吸抛吸尘器,作为概念级项目目前可以吸走小纸片😭,目标检测也只训练了小纸片。但是作为小型玩具玩一玩还是可以的,所以本篇教程分为基础功能和概念进阶两个版本。只有完成了基础功能才可以进行进阶操作😊,但是别担心,基础版本主播也是拿随手可及的东西拼凑的,大家也可以根据实际情况进行修改。
步骤1 基础班材料准备
尼龙过滤网(主播在网上买的3元一米宽左右)
矿泉水瓶(0元)
6cm散热风扇 12V (4元)
4节5号电池盒带盖带开关(2.5元)
3.7V尖头大容量锂电池 4个(12元)
闲置旧舵机(0元)
以下内容可被替代
3D打印底座
3D打印通风道
3D打印滑轨与连杆
木制垫片
螺丝若干
步骤2 基础版组装过程
1.先连接风扇与通风管道,然后将整体连接到底板。
2.切割矿泉水瓶,用橡皮筋捆住滤网。
3.连接矿泉水瓶和滑块连杆组合,并用螺丝锁住舵机臂。
4.舵机连接垫块。
5.选择合适位置,令风扇与矿泉水瓶平行。
6.风扇连接电池盒然后将电池盒粘贴到底板下方。
(风扇线与电池盒的连接处要用绝缘胶带缠一圈,防止直接连接正负极烧毁电路)
到目前为止,基本的功能就可以实现了。
步骤3 进阶版组装过程
进阶版需要用到以下材料
行空板m10
外接摄像头
100欧电阻
小灯泡
1.将摄像头和小灯泡连接矿泉水瓶和行空板,小灯泡连接小卡片p22接口,摄像头连接usb接口。
2.用mind+上传程序和模型训练文件。
(想训练其他杂物识别可以用mind+目标检测训练模型)

3.如果想移动使用,可以用充电宝连接。
注意:1.不要将垃圾吹到他人身上,会引起他人不适。
2.不要用手碰运行中的风扇扇叶,会很疼。
# -*- coding: UTF-8 -*-
# MindPlus V2 - 优化识别速度 + 调试输出
import os
import time
import cv2
import threading
import queue
import sys
import traceback
os.environ["QT_QPA_FONTDIR"] = "/usr/share/fonts"
os.environ["OPENCV_LOG_LEVEL"] = "OFF"
from model_mp_io import ImageReader
from pinpong.board import Board, Pin
from model_mp_io import ImageWriter
from pinpong.extension.unihiker import *
from model_mp_core import ObjectDetectionInference
# ==================== 初始化 ====================
try:
Board().begin()
p_p22_out = Pin(Pin.P22, Pin.OUT)
p_p22_out.write_digital(0)
# 摄像头配置:分辨率 160x120(可手动调低为 128x96 或 96x72 以提升速度)
image_reader = ImageReader(source=1)
image_reader.set_resolution(320, 320) # 可根据需要改为 128,96 或 96,72
if hasattr(image_reader, 'cap'):
image_reader.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1)
# 加载模型
inference = ObjectDetectionInference(
get_asset_path_by_name("best.onnx"),
get_asset_path_by_name("data.yaml")
)
detection_img_output = ImageWriter()
# 设置显示窗口大小
cv2.namedWindow("AI", cv2.WINDOW_NORMAL)
cv2.resizeWindow("AI", 640, 480)
print("初始化成功")
except Exception as e:
print(f"初始化失败: {e}")
traceback.print_exc()
sys.exit(1)
# ==================== 线程间队列 ====================
frame_queue = queue.Queue(maxsize=2)
result_queue = queue.Queue(maxsize=1)
stop_event = threading.Event()
# ==================== 摄像头读取线程 ====================
def capture_thread():
while not stop_event.is_set():
try:
img = image_reader.read_frame()
if img is not None:
if frame_queue.full():
try:
frame_queue.get_nowait()
except queue.Empty:
pass
frame_queue.put(img)
except Exception as e:
print(f"摄像头读取异常: {e}")
traceback.print_exc()
time.sleep(0.01)
# ==================== 检测线程(高间隔,低频率) ====================
frame_counter = 0
detect_interval = 10 # 每10帧检测一次,大幅降低推理频率
def detect_thread():
global frame_counter
while not stop_event.is_set():
try:
img = frame_queue.get(timeout=1)
if frame_counter % detect_interval == 0:
# 执行推理
result = inference.inference(img)
if not isinstance(result, dict) or 'result' not in result:
print(f"推理结果格式错误: {result}")
else:
# 打印检测结果(调试用)
detections = result.get('result', [])
if len(detections) > 0:
print(f"检测到 {len(detections)} 个物体")
for det in detections:
# 尝试获取标签和置信度
label = det.get('label') or det.get('class') or det.get('name', 'unknown')
conf = det.get('confidence') or det.get('score', 0)
print(f" {label}: {conf:.2f}")
# 更新结果队列
while not result_queue.empty():
result_queue.get_nowait()
result_queue.put(result)
frame_counter += 1
except queue.Empty:
continue
except Exception as e:
print(f"推理异常: {e}")
traceback.print_exc()
time.sleep(0.1)
threading.Thread(target=capture_thread, daemon=True, name="Capture").start()
threading.Thread(target=detect_thread, daemon=True, name="Detect").start()
# ==================== 自定义绘图函数(兼容多种键名) ====================
def draw_detections(img, result):
"""
鲁棒的绘图函数,兼容不同键名
"""
img_copy = img.copy()
for det in result.get('result', []):
# 获取边界框
bbox = det.get('bbox')
if bbox is None:
continue
x1, y1, x2, y2 = map(int, bbox)
# 获取标签
label = det.get('label') or det.get('class') or det.get('name', '?')
# 获取置信度
conf = det.get('confidence') or det.get('score', 0)
# 绘制矩形框
cv2.rectangle(img_copy, (x1, y1), (x2, y2), (0, 255, 0), 1)
# 绘制标签文字
text = f"{label}: {conf:.2f}" if conf else label
cv2.putText(img_copy, text, (x1, y1-5), cv2.FONT_HERSHEY_SIMPLEX, 0.3, (0, 255, 0), 1)
return img_copy
# ==================== 主线程:显示和控制 ====================
last_display_result = {'result': []}
frame_count = 0
try:
while True:
# 获取最新检测结果
if not result_queue.empty():
try:
last_display_result = result_queue.get_nowait()
except queue.Empty:
pass
# 获取最新帧
try:
img = frame_queue.get_nowait()
except queue.Empty:
time.sleep(0.001)
continue
# 使用自定义绘图函数(更稳定)
try:
img_with_boxes = draw_detections(img, last_display_result)
except Exception as e:
print(f"绘图异常: {e}")
traceback.print_exc()
img_with_boxes = img
# 缩放显示
display_size = (640, 480)
img_to_show = cv2.resize(img_with_boxes, display_size, interpolation=cv2.INTER_NEAREST)
cv2.imshow("AI", img_to_show)
key = cv2.waitKey(1) & 0xFF
if key == ord('q'):
break
# GPIO 控制
try:
p_p22_out.write_digital(1 if len(last_display_result.get('result', [])) > 0 else 0)
except Exception as e:
print(f"GPIO控制异常: {e}")
frame_count += 1
time.sleep(0.005)
except KeyboardInterrupt:
print("用户中断")
except Exception as e:
print(f"主循环异常: {e}")
traceback.print_exc()
finally:
stop_event.set()
time.sleep(0.2)
cv2.destroyAllWindows()
print("程序退出")附件

返回首页
回到顶部

评论