aboutsummaryrefslogtreecommitdiff
path: root/src/examples/tobii_camera_calibration.py
blob: 0e621b5f69c4c2ec04bcdac5a6321e397cc875cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
#!/usr/bin/env python

"""
tobii_camera_calibration.py

Author: 
    - Théo de la Hogue, theo.de-la-hogue@enac.fr

This program:
    - Captures board pictures with a full displayed board inside
    - Outputs camera calibration data into a camera.json file

Reference:
    - https://automaticaddison.com/how-to-perform-pose-estimation-using-an-aruco-marker/
"""
import os
import time

from TobiiGlassesPro2 import TobiiController, TobiiVideo
from ArUcoMarkers import ArUcoBoard, ArUcoTracker, ArUcoCamera

import cv2 as cv

# tobii glasses ip address
ip_address = '192.168.1.10'

# manage export folder
current_folder = os.path.dirname(__file__)
export_folder = os.path.join(current_folder, '_export')
if not os.path.exists(export_folder):
    os.makedirs(export_folder)
    print(f'\'_export\' folder created')

# create tobii controller
tobii_controller = TobiiController.TobiiController(ip_address, 'ArGaze', 1)

# create tobii video thread
tobii_video_thread = TobiiVideo.TobiiVideoThread(tobii_controller)
tobii_video_thread.start()

# create aruco camera
aruco_camera = ArUcoCamera.ArUcoCamera()

# create aruco board
aruco_board = ArUcoBoard.ArUcoBoard('DICT_4X4_50', 7, 5, 5, 3) # 7 columns, 5 rows, square size (cm), marker size (cm)

# create aruco tracker
aruco_tracker = ArUcoTracker.ArUcoTracker('DICT_4X4_50', 6, aruco_camera) # aruco dictionaries, marker length (cm), camera

# start tobii glasses streaming
tobii_controller.start_streaming()

print("Camera calibration starts")
print("Waiting for calibration board...")

frame_width = 0
frame_height = 0

expected_markers_number = len(aruco_board.get_ids())
expected_corners_number = (aruco_board.get_size()[0] - 1 ) * (aruco_board.get_size()[1] - 1)

# capture frame with a full displayed board
while True:

    frame, frame_width, frame_height, frame_time, frame_pts = tobii_video_thread.read()

    # track all markers in the board
    aruco_tracker.track_board(frame, aruco_board, expected_markers_number)

    # draw only markers
    aruco_tracker.draw(frame)

    # draw current calibration data count
    cv.putText(frame, f'Capture: {aruco_camera.get_calibration_data_count()}', (50, 50), cv.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv.LINE_AA)
    cv.imshow('Tobii Camera Calibration', frame)

    # if all board corners are detected
    if aruco_tracker.get_board_corners_number() == expected_corners_number:

        # draw board corners to notify a capture is done
        aruco_tracker.draw_board(frame)

        # append data
        aruco_camera.store_calibration_data(aruco_tracker.get_board_corners(), aruco_tracker.get_board_corners_ids())

        cv.imshow(f'Tobii Camera Calibration', frame)

        time.sleep(2)

    # quit on 'Esc' command
    key = cv.waitKey(1)
    if key == 27:
        cv.destroyAllWindows()
        break

# stop tobii objects
tobii_video_thread.stop()

tobii_controller.stop_streaming()
tobii_controller.close()

print('\nCalibrating camera...')
aruco_camera.calibrate(aruco_board, frame_width, frame_height)

print('\nCalibration succeeded!')
print(f'\nRMS:\n{aruco_camera.get_rms()}')
print(f'\nCamera matrix:\n{aruco_camera.get_K()}')
print(f'\nDistortion coefficients:\n{aruco_camera.get_D()}')

aruco_camera.save_calibration_file(os.join(export_folder,'tobii_camera.json'))

print(f'\nCalibration data exported into tobii_camera.json file')