基于Python的眼动追踪交互系统实现与创新应用

在人机交互(HCI)领域,眼动追踪技术正从实验室走向真实场景。它不仅能用于心理学研究、用户行为分析,还广泛应用于无障碍设计、游戏控制和虚拟现实(VR)交互中。本文将通过 Python + OpenCV + Tobii Pro SDK 实现一个轻量级但功能完整的实时眼动追踪系统,并展示如何将其集成到图形界面中,打造“视线驱动”的交互体验。


一、核心原理简述

眼动追踪的核心是识别眼球运动方向并映射为屏幕坐标。我们使用摄像头捕捉用户眼部图像,通过特征点检测(如瞳孔中心、角膜反射光斑)计算注视点位置。该过程可分为三个阶段:

  1. 预处理:去噪、增强对比度;
    1. 特征提取:定位瞳孔与角膜反射点;
    1. 坐标映射:根据校准数据转换为屏幕坐标。
      外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

⚠️ 注意:实际部署需硬件支持(如Tobii Eye Tracker),此处使用普通USB摄像头模拟。


二、环境准备与依赖安装

pip install opencv-python numpy matplotlib tobii-research

若你没有专业眼动设备,可先用开源工具 pytouigaze-tracking 模拟简单模型;若已有设备,则直接调用 tobii_research 提供的API获取原始数据流。


三、代码实现:基础眼动追踪模块

以下是一个完整的 Python 示例,包含摄像头初始化、瞳孔检测与屏幕坐标映射逻辑:

import cv2
import numpy as np

class EyeTracker:
    def __init__(self):
            self.cap = cv2.VideoCapture(0)
                    self.face_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_frontalface_default.xml')
                            self.eye_cascade = cv2.CascadeClassifier(cv2.data.haarcascades + 'haarcascade_eye.xml')
    def preprocess_frame(self, frame):
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
                    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
                            return blurred
    def detect_eyes(self, frame):
            faces = self.face_cascade.detectMultiScale(frame, 1.1, 4)
                    for (x, y, w, h) in faces:
                                roi_gray = frame[y:y+h, x:x+w]
                                            eyes = self.eye_cascade.detectMultiScale(roi_gray)
                                                        for (ex, ey, ew, eh) in eyes:
                                                                        # 返回眼睛ROI区域
                                                                                        eye_roi = roi_gray[ey:ey+eh, ex:ex+ew]
                                                                                                        return eye_roi
                                                                                                                return None
    def calculate_gaze_point(self, eye_image):
            # 简化版本:假设瞳孔位于图像中心偏移处
                    h, w = eye_image.shape[:2]
                            center_x, center_y = w // 2, h // 2
                                    # 模拟瞳孔偏移(实际应由机器学习或几何算法得出)
                                            offset_x = int(np.random.normal(0, 5))
                                                    offset_y = int(np.random.normal(0, 5))
                                                            gaze_x = center_x + offset_x
                                                                    gaze_y = center_y + offset_y
                                                                            return (gaze_x, gaze_y)
    def run(self):
            while True:
                        ret, frame = self.cap.read()
                                    if not ret:
                                                    break
                                                                
                                                                            preprocessed = self.preprocess_frame(frame)
                                                                                        eye_roi = self.detect_eyes(preprocessed)
                                                                                                    
                                                                                                                if eye_roi is not None:
                                                                                                                                gaze_coords = self.calculate_gaze_point(eye_roi)
                                                                                                                                                3 将相对坐标映射到屏幕(简化)
                                                                                                                                                                screen_x = int(gaze_coords[0] * 800 / eye_roi.shape[1])
                                                                                                                                                                                screen_y = int(gaze_coords[1] * 600 / eye_roi.shape[0])
                                                                                                                                                                                                
                                                                                                                                                                                                                # 在原图中标记注视点
                                                                                                                                                                                                                                cv2.circle(frame, (screen_x, screen_y), 10, (0, 255, 0), -1)
                                                                                                                                                                                                                                                cv2.putText(frame, f"Gaze: ({screen_x}, {screen_y})", 
                                                                                                                                                                                                                                                                            (50, 50), cv2.FONT_HERSHEY_SimplEX, 1, (0, 255, 0), 2)
            cv2.imshow("Eye Tracking Demo", frame)
                        if cv2.waitKey(1) & 0xFF == ord('q'):
                                        break
                                                
                                                        self.cap.release()
                                                                cv2.destroyAllWindows()
if __name__ == "__main__":
    tracker = eyeTracker()
        tracker.run()
        ```
---

### 四、进阶优化建议(适合CSDN读者拓展)

#### ✅ 校准机制(Calibration)
- 让用户盯着屏幕上不同位置的点(如十字标记),记录对应的眼部特征偏移。
- - 建立映射函数:`屏幕坐标 = f(瞳孔位置)`,可用线性回归或神经网络拟合。
#### ✅ 多摄像头融合
- 使用两个摄像头分别采集左右眼,提升精度与鲁棒性(尤其在遮挡情况下)。
#### ✅ 与GUI结合(Tkinter / PyQt)
```python
from tkinter import Tk, Canvas

root = Tk()
canvas = Canvas(root, width=800, height=600)
canvas.pack()

# 在主循环中更新canvas内容,实现“视线点击”效果
def update_gaze():
    canvas.delete("all")
        canvas.create_oval(gaze_x-10, gaze_y-10, gaze_x+10, gaze_y=10, fill="red")
            root.after930, update_gaze)
update_gaze()
root.mainloop()

五、典型应用场景举例

应用场景 技术价值
残8障人士辅助输入* 只靠眨眼即可操作电脑,替代鼠标键盘
广告点击率分析 分析用户是否真正关注某个按钮或文字
教育测评系统 判断学生注意力集中程度,动态调整教学节奏
VR/AR沉浸式交互 自然地“看哪点哪”,无需手柄

六、常见问题及解决方案

问题 解决方案
镜头模糊导致无法准确识别瞳孔 增加照明光源,使用红外补光灯
用户移动造成误判 引入姿态估计模块,稳定视野
不同光照环境下性能下降 加入自适应阈值分割(如Otsu方法)

此项目不仅可用于教学演示,也可作为智能终端开发的基础原型。如果你希望进一步接入真实设备(如Tobii Eyetracker 4C),只需替换摄像头部分为SDK接口调用,其余逻辑几乎无需改动。

现在就开始动手试试吧!让计算机“读懂你的眼神”。

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐