发布时间:2026-06-18 阅读量:77 来源: 米尔电子 发布人: bebop
随着人工智能技术的快速发展,视觉检测技术在医疗健康领域的应用越来越广泛。传统的视力检测需要专业医护人员操作,检测效率较低,且难以实现自动化。本项目基于瑞芯微RK3576开发板,设计并实现了一套智能视力检测系统,旨在提供一种便捷、高效的视力检测方案。RK3576是一款高性能ARM架构的开发板,搭载瑞芯微处理器,具备强大的AI推理能力,适合运行手势识别、图像处理等AI任务。

01
02

模块 | 功能描述 |
视频播放模块 | 开机播放引导视频,支持GStreamer硬件解码 |
手势识别模块 | 使用MediaPipe检测OK手势,作为测试启动信号 |
距离检测模块 | 通过串口读取红外测距传感器数据,检测用户距离 |
视力测试模块 | 随机显示E字方向,根据用户手势判断是否正确 |
语音播报模块 | 播放欢迎语音、测试指引、视力结果等 |
UI显示模块 | 使用PySide6显示视频、E字图片、状态信息 |

03
设备 | 型号/规格 | 用途 |
开发板 | 米尔RK3576 | 核心控制器,运行AI推理和业务逻辑 |
摄像头 | Intel RealSense D435 | 采集RGB图像用于手势识别 |
距离传感器 | TOF激光测距模块 | 检测用户与设备的距离(2cm10m) |
音频编解码 | ES8388 | 音频输出(通过ALSA驱动) |
显示器 | HDMI显示屏 | 显示UI和视力表 |
04
8 12 16 20│ │ │ │▼ ▼ ▼ ▼○───────────○───────────○───────────○ ← 食指、中指、无名指、小指│ │ │ │7 11 15 19│ │ │ │○───────────○───────────○───────────○│ │ │ │6 10 14 18│ │ │ │○───────────○───────────○───────────○│ │ │ │5 9 13 17│ │○───────────────────────○│ │4 13│ │○────┴───────────────────────┴────○│ │0 9│ │└────────────────────────────────┘(手腕)
# 手势识别关键代码 (hand_gesture_task.py)import mediapipe as mpimport numpy as npimport cv2# 初始化MediaPipe Handsmp_hands = mp.solutions.handshands = mp_hands.Hands( static_image_mode=False, # 视频流模式 max_num_hands=2, # 最多检测2只手 min_detection_confidence=0.7, # 检测置信度阈值 min_tracking_confidence=0.5 # 跟踪置信度阈值)def calculate_distance(p1, p2): """计算两个landmark之间的欧氏距离(归一化坐标)""" return ((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) ** 0.5def recognize_gesture(landmarks): """ 识别特殊手势:OK、NO(拳头) 返回: "OK", "NO", 或 None """ # 获取关键点 thumb_tip = landmarks[4] # 拇指尖 index_tip = landmarks[8] # 食指尖 middle_tip = landmarks[12] # 中指尖 ring_tip = landmarks[16] # 无名指尖 pinky_tip = landmarks[20] # 小指尖 wrist = landmarks[0] # 手腕 # === OK手势检测 === # 条件:拇指和食指接近,其他手指伸开 thumb_index_dist = calculate_distance(thumb_tip, index_tip) if thumb_index_dist < 0.05: # 检查中指是否伸开 if calculate_distance(middle_tip, wrist) > 0.3: return "OK" # === NO/拳头检测 === # 条件:所有指尖靠近手掌 tips = [index_tip, middle_tip, ring_tip, pinky_tip] all_close = True for tip in tips: if calculate_distance(tip, wrist) > 0.15: all_close = False break if all_close: return "NO" return Nonedef get_finger_direction(landmarks, h, w): """ 获取食指指向的方向 返回: "上", "下", "左", "右", "静止" """ # 食指近端关节(5)和指尖(8) x5, y5 = int(landmarks[5].x * w), int(landmarks[5].y * h) x8, y8 = int(landmarks[8].x * w), int(landmarks[8].y * h) dx = x8 - x5 dy = y8 - y5 threshold = 25 # 阈值,像素单位 # 判断是否静止 if abs(dx) < threshold and abs(dy) < threshold: return "静止" # 判断方向 if abs(dx) > abs(dy): return "右" if dx > 0 else "左" else: return "下" if dy > 0 else "上"def image_to_user_direction(img_dir): """ 将图像坐标系转换为用户视角方向 图像左→用户右,图像右→用户左 """ if img_dir == "左": return "右" elif img_dir == "右": return "左" else: return img_dir
def hand_gesture_worker(): """手势识别工作线程""" global current_hand_info, gesture_running # 1. 初始化RealSense摄像头 pipeline = rs.pipeline() config = rs.config() config.enable_stream(rs.stream.color, 640, 480, rs.format.bgr8, 15) pipeline.start(config) # 2. 主循环:持续处理每一帧 while gesture_running: # 获取彩色帧 frames = pipeline.wait_for_frames(timeout_ms=1000) color_frame = frames.get_color_frame() if not color_frame: continue # 转换为numpy数组 color_image = np.asanyarray(color_frame.get_data()) h, w = color_image.shape[:2] # BGR转RGB(MediaPipe需要RGB) rgb = cv2.cvtColor(color_image, cv2.COLOR_BGR2RGB) # 3. MediaPipe处理 results = hands.process(rgb) # 4. 解析结果 lines = [] if results.multi_hand_landmarks and results.multi_handedness: for hand_landmarks, handedness in zip( results.multi_hand_landmarks, results.multi_handedness ): # 获取左右手判断 mp_label = handedness.classification[0].label user_hand = "右手" if mp_label == "Left" else "左手" # 尝试识别特殊手势 gesture = recognize_gesture(hand_landmarks.landmark) if gesture: lines.append(f"[{user_hand}]{gesture}") else: # 获取食指方向 direction = get_finger_direction(hand_landmarks.landmark, h, w) # 转换视角 user_direction = image_to_user_direction(direction) lines.append(f"[{user_hand}]{user_direction}") # 更新全局状态 current_hand_info = "\n".join(lines) if lines else "未检测到手" time.sleep(0.1) # 控制帧率 # 5. 清理资源 pipeline.stop() hands.close()# GStreamer视频解码管道 (intro_video_player.py)pipeline_str = ( "filesrc location={video_path} ! " "qtdemux ! " "h264parse ! mppvideodec ! " # 瑞芯微硬件解码 "videoconvert ! video/x-raw,format=BGR ! " "appsink name=sink emit-signals=true")class TestState: # 系统状态 SYSTEM_STATE_IDLE = 0 # 系统空闲 SYSTEM_STATE_TESTING = 1 # 正在测试 # 应用状态 APP_STATE_WAITING_OK = 0 # 等待OK手势 APP_STATE_WAITING_HAND_OK = 1 # 等待举手 APP_STATE_TESTING = 2 # 正在测试 APP_STATE_SHOWING_RESULT = 3 # 显示结果
# 串口读取距离数据 (main.py)def _read_distance(self): try: if self.serial_port and self.serial_port.in_waiting: data = self.serial_port.readline() if data.startswith(b'D:'): distance = int(data[2:].strip()) return distance except Exception as e: print(f"读取距离失败:{e}") return -105
问题 | 原因分析 | 解决方案 |
视频无法播放 | mp4v编码不支持 | 使用H.264编码重新转换视频 |
音频无声音 | 采样率不匹配(24kHz mono) | 转换为44.1kHz stereo |
手势识别不稳定 | 光照条件影响 | 调整检测阈值,增加置信度 |
距离传感器读数为0 | 串口波特率不匹配 | 改为115200波特率 |
测试结果不准确 | 左右手方向判断错误 | 修正手势方向与E字方向的映射关系 |
视频画面无法清除 | 停止时回调递归 | 添加stopping标志防止重复调用 |
E字符不显示 | 停止视频后未显示char_label | 在_start_vision_test中添加显示逻辑 |
06
07
参数 | 数值 |
代码总量 | 3092行 |
视频解码分辨率 | 640x480 |
手势识别帧率 | 30fps |
距离检测精度 | ±10mm |
语音采样率 | 44.1kHz |
测试时间 | 约2-3分钟/次 |
08
RK3576-Pro/├── main.py # 主程序入口 (942行)├── ui_vision_test.py # UI界面 (241行)├── intro_video_player.py # 视频播放器 (618行)├── hand_gesture_task.py # 手势识别 (187行)├── generate_custom_audio.py # 音频生成脚本 (95行)├── pic/ # E字视力表图片│ ├── up.png│ ├── down.png│ ├── left.png│ └── right.png├── custom_audio/ # 语音文件│ ├── welcome.wav│ ├── switch_right_hand.wav│ ├── result_*.wav│ └── ...└── videos/ # 视频文件 └── intro_guide.mp4
09
# 安装Python依赖pip install pyside6 mediapipe pygame numpy opencv-python# 安装系统依赖apt-get install gstreamer1.0-tools gstreamer1.0-plugins-base \gstreamer1.0-plugins-good alsa-utils
python3 main.py
10

在数字化、智能化浪潮席卷全球的当下,元器件产业的每一次技术突破,都在为现代社会的信息化演进注入强劲动能。
我爱方案网推荐YSN8563低功耗RTC芯片,全面适配执法记录仪全场景需求,实现设备低功耗长续航
CMOS方波和Clipped Sine Wave两者虽同为单端输出,但在电气特性、应用场景上存在本质差异
可编程时钟芯片是一类能通过软件指令或硬件引脚配置,动态改变输出时钟频率、相位、信号格式等参数的大规模集成电路
基于RK3576高性能开发板,正式推出一套面向生产级的【ROS2 SLAM建图与自主导航】全栈开源实战方案,能帮助工程师从仿真到实体项目快速量产