Usage example#

Here’s a quick example of how to pass 2D pupil detection results to pye3d (requires standalone 2D pupil detector installation). Alternatively, you can install the dependencies together with pye3d

pip install pye3d[examples]
 1import argparse
 2
 3import cv2
 4from pupil_detectors import Detector2D
 5
 6from pye3d.detector_3d import CameraModel, Detector3D, DetectorMode
 7
 8
 9def main(eye_video_path):
10    # create 2D detector
11    detector_2d = Detector2D()
12    # create pye3D detector
13    camera = CameraModel(focal_length=561.5, resolution=[400, 400])
14    detector_3d = Detector3D(camera=camera, long_term_mode=DetectorMode.blocking)
15    # load eye video
16    eye_video = cv2.VideoCapture(eye_video_path)
17    # read each frame of video and run pupil detectors
18    while eye_video.isOpened():
19        frame_number = eye_video.get(cv2.CAP_PROP_POS_FRAMES)
20        fps = eye_video.get(cv2.CAP_PROP_FPS)
21        ret, eye_frame = eye_video.read()
22        if ret:
23            # read video frame as numpy array
24            grayscale_array = cv2.cvtColor(eye_frame, cv2.COLOR_BGR2GRAY)
25            # run 2D detector on video frame
26            result_2d = detector_2d.detect(grayscale_array)
27            result_2d["timestamp"] = frame_number / fps
28            # pass 2D detection result to 3D detector
29            result_3d = detector_3d.update_and_detect(result_2d, grayscale_array)
30            ellipse_3d = result_3d["ellipse"]
31            # draw 3D detection result on eye frame
32            cv2.ellipse(
33                eye_frame,
34                tuple(int(v) for v in ellipse_3d["center"]),
35                tuple(int(v / 2) for v in ellipse_3d["axes"]),
36                ellipse_3d["angle"],
37                0,
38                360,  # start/end angle for drawing
39                (0, 255, 0),  # color (BGR): red
40            )
41            # show frame
42            cv2.imshow("eye_frame", eye_frame)
43            # press esc to exit
44            if cv2.waitKey(1) & 0xFF == 27:
45                break
46        else:
47            break
48    eye_video.release()
49    cv2.destroyAllWindows()
50
51
52if __name__ == "__main__":
53    parser = argparse.ArgumentParser()
54    parser.add_argument("eye_video_path")
55    args = parser.parse_args()
56    main(args.eye_video_path)