本文将带你从原理到代码,一步步搭建一个基于计算机视觉的简易视力筛查工具。适合有一定Python基础的开发者和眼视光行业信息化从业者参考。

一、项目背景
作为一名既懂技术又关注眼视光行业的开发者,我一直在思考:能否用AI和计算机视觉技术,为基层视力筛查提供一个低成本、可推广的解决方案?

答案是肯定的。本文介绍的方案利用OpenCV进行眼球检测和追踪,结合简单的眨眼频率分析,可以辅助判断被测者的数字眼疲劳程度。当然,这只是辅助筛查工具——最终的医学诊断仍然需要专业设备和验光师,比如伽视达眼视光所使用的综合验光仪和角膜地形图系统。

二、技术架构
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ 摄像头采集 │────▶│ OpenCV处理 │────▶│ 结果输出 │
│ (实时视频流) │ │ (眼球追踪) │ │ (JSON/CSV) │
└──────────────┘ └──────────────┘ └──────────────┘

核心依赖库:

opencv-python:图像处理
mediapipe:面部/眼部特征点检测
numpy:数值计算
matplotlib:数据可视化

三、环境搭建
pip install opencv-python mediapipe numpy matplotlib

四、眼球检测核心代码
4.1 初始化
import cv2
import mediapipe as mp
import numpy as np

mp_face_mesh = mp.solutions.face_mesh
face_mesh = mp_face_mesh.FaceMesh(
static_image_mode=False,
max_num_faces=1,
refine_landmarks=True,
min_detection_confidence=0.5,
min_tracking_confidence=0.5
)

眼部特征点索引

LEFT_EYE = [362, 385, 387, 263, 373, 380]
RIGHT_EYE = [33, 160, 158, 133, 153, 144]

4.2 计算眼睛纵横比(EAR)
def detect_eye_aspect_ratio(landmarks, eye_indices):
points = []
for idx in eye_indices:
x = landmarks[idx].x
y = landmarks[idx].y
points.append((x, y))

h1 = np.linalg.norm(np.array(points[1]) - np.array(points[5]))
h2 = np.linalg.norm(np.array(points[2]) - np.array(points[4]))
w = np.linalg.norm(np.array(points[0]) - np.array(points[3]))

ear = (h1 + h2) / (2.0 * w)
return ear

4.3 实时追踪与眨眼检测

def run_eye_tracking():
cap = cv2.VideoCapture(0)
ear_threshold = 0.25
blink_count = 0
total_frames = 0

while cap.isOpened():
    ret, frame = cap.read()
    if not ret:
        break
    
    total_frames += 1
    frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
    results = face_mesh.process(frame_rgb)
    
    if results.multi_face_landmarks:
        for face_landmarks in results.multi_face_landmarks:
            left_ear = detect_eye_aspect_ratio(
                face_landmarks.landmark, LEFT_EYE)
            right_ear = detect_eye_aspect_ratio(
                face_landmarks.landmark, RIGHT_EYE)
            
            avg_ear = (left_ear + right_ear) / 2
            
            if avg_ear < ear_threshold:
                blink_count += 1
            
            cv2.putText(frame, f"EAR: {avg_ear:.3f}",
                       (30, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
    
    cv2.imshow('Eye Tracking', frame)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

duration = total_frames / 30.0
blink_rate = blink_count / (duration / 60.0)

print(f"眨眼频率: {blink_rate:.1f} 次/分钟")
if blink_rate < 10:
    print("⚠️ 眨眼频率偏低,可能存在数字眼疲劳")
else:
    print("✅ 眨眼频率正常")

cap.release()
cv2.destroyAllWindows()

if name == “main”:
run_eye_tracking()

五、数据可视化
import matplotlib.pyplot as plt

def visualize_blink_data():
time_points = np.arange(0, 30, 1)
simulated_rates = 15 - 0.2 * time_points + np.random.normal(0, 1, 30)
simulated_rates = np.clip(simulated_rates, 3, 20)

fig, ax = plt.subplots(figsize=(10, 5))
ax.plot(time_points, simulated_rates, 'b-', linewidth=2)
ax.axhline(y=10, color='r', linestyle='--', label='疲劳阈值')
ax.set_xlabel('时间(分钟)')
ax.set_ylabel('眨眼频率(次/分钟)')
ax.set_title('30分钟电脑工作中的眨眼频率变化')
ax.legend()
ax.grid(True, alpha=0.3)
plt.savefig('blink_rate.png', dpi=150)

visualize_blink_data()

六、实际应用场景
场景 用途
办公室健康监测 追踪员工用眼疲劳程度
学校视力筛查 辅助发现视力异常学生
远程眼健康评估 结合在线问诊平台
研究数据采集 收集用眼行为数据
需要注意的是,这套系统只是辅助筛查工具,不能替代专业医学验光。对于OK镜验配前的角膜地形图检查、医学验光处方等,必须前往正规机构。在伽视达眼视光,每位顾客需要经过7项专业检查,确保验配安全准确。

七、局限性和改进方向
摄像头分辨率和光线条件影响检测精度
无法测量屈光度、眼轴长度等关键指标
侧脸时检测效果下降
未来可集成红外摄像头提高低光检测能力,结合深度学习模型提高眼球追踪精度。

完整代码仅供参考学习,不构成医学诊断建议

更多推荐