📌 项目背景与意义
据世界卫生组织统计,目前全球约有超4,300万盲人或严重视力受限者。他们在日常生活中面临着环境感知困难的问题,尤其是在陌生区域中行走,常会碰到诸如垃圾桶、台阶、自行车、车辆等障碍物。
传统的辅助工具如导盲杖或导盲犬虽然起到了基础避障作用,但信息传递有限。本项目旨在通过深度学习和语音辅助技术,为盲人提供一个可实时识别前方障碍物类型并通过语音播报提示的智能辅助系统。
🧩 技术路线与系统架构
整个系统采用“感知 → 理解 → 提示”三步闭环架构:
lua
复制编辑
+----------------------------+
| 摄像头或视频流采集模块 |
+----------------------------+
↓
+----------------------------+
| YOLOv8模型识别障碍物 |
+----------------------------+
↓
+----------------------------+
| 语音合成模块 (TTS) |
+----------------------------+
↓
+----------------------------+
| UI交互界面(启动/暂停) |
+----------------------------+
核心技术点包括:
- YOLOv8 检测目标类型和位置
- Python + OpenCV 实现视频实时处理
- pyttsx3 / edge-tts 合成语音提示
- PyQt5 实现界面按钮交互与信息显示
📁 参考数据集与标注说明
1. OpenImages Dataset(障碍物识别)
- 地址:https://storage.googleapis.com/openimages/web/index.html
- 标签推荐:
Bicycle
,Bench
,Trash can
,Car
,Stairs
,Person
,Door
- 数据量大,支持目标检测格式(YOLO或Pascal VOC)
2. Mapillary Vistas Dataset
- 高质量街景图像,适合模拟盲人步行环境
- 包含人、物体、道路、标识牌、栏杆等多类别目标
3. 自建障碍物数据集(推荐)
- 手机拍摄前方视角视频,如走路中遇到电动车、自行车、垃圾桶等
- 使用
LabelImg
标注成 YOLO 格式(txt)
4. 障碍物类别建议
建议定义的类别有:
txt
复制编辑
["person", "bicycle", "car", "trash_bin", "stairs", "pole", "barrier", "animal", "door"]
🚀 YOLOv8模型部署与障碍物检测
1. 安装依赖环境
bash
复制编辑
pip install ultralytics opencv-python pyttsx3 PyQt5
2. 加载YOLOv8模型
python
复制编辑
from ultralytics import YOLO
# 加载预训练模型(可替换为自己训练好的)
model = YOLO('yolov8n.pt') # 推荐使用 yolov8n 或 yolov8s
3. 视频流识别主逻辑
python
复制编辑
import cv2
def detect_and_annotate(frame):
results = model(frame)
annotated_frame = results[0].plot()
detected_classes = [model.names[int(cls)] for cls in results[0].boxes.cls]
return annotated_frame, detected_classes
🔊 语音提示模块(TTS)实现
1. 使用 pyttsx3
实时播报识别结果
python
复制编辑
import pyttsx3
engine = pyttsx3.init()
def speak_text(text):
engine.say(text)
engine.runAndWait()
2. 防止重复播报(设置冷却时间)
python
复制编辑
import time
last_spoken = {}
cooldown = 3 # 每类目标3秒内不重复播报
def speak_detected_objects(detected_classes):
current_time = time.time()
for cls in detected_classes:
if cls not in last_spoken or current_time - last_spoken[cls] > cooldown:
speak_text(f"前方有 {cls}")
last_spoken[cls] = current_time
🖥️ 完整UI交互界面设计(PyQt5)
提供上传视频或开启摄像头方式运行系统,语音自动提示。
python
复制编辑
from PyQt5.QtWidgets import QApplication, QLabel, QPushButton, QVBoxLayout, QWidget, QFileDialog
from PyQt5.QtGui import QPixmap, QImage
import sys
class BlindNavUI(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("BlindNavAssist - 盲人导航辅助系统")
self.resize(640, 480)
self.label = QLabel("系统未启动")
self.btn_start_camera = QPushButton("启动摄像头导航")
self.btn_upload_video = QPushButton("上传视频分析")
layout = QVBoxLayout()
layout.addWidget(self.label)
layout.addWidget(self.btn_start_camera)
layout.addWidget(self.btn_upload_video)
self.setLayout(layout)
self.btn_start_camera.clicked.connect(self.run_camera)
self.btn_upload_video.clicked.connect(self.upload_video)
def run_camera(self):
import threading
threading.Thread(target=self.camera_loop).start()
def upload_video(self):
file, _ = QFileDialog.getOpenFileName()
if file:
import threading
threading.Thread(target=self.video_loop, args=(file,)).start()
def video_loop(self, video_path):
cap = cv2.VideoCapture(video_path)
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
result_frame, classes = detect_and_annotate(frame)
speak_detected_objects(classes)
cv2.imshow("BlindNavAssist", result_frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
def camera_loop(self):
cap = cv2.VideoCapture(0)
while True:
ret, frame = cap.read()
if not ret:
break
result_frame, classes = detect_and_annotate(frame)
speak_detected_objects(classes)
cv2.imshow("BlindNavAssist", result_frame)
if cv2.waitKey(1) & 0xFF == 27:
break
cap.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
app = QApplication(sys.argv)
win = BlindNavUI()
win.show()
sys.exit(app.exec_())