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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
#!/usr/bin/env python
import argparse
import os
import time
from argaze.TobiiGlassesPro2 import TobiiController, TobiiVideo
from argaze.ArUcoMarkers import ArUcoMarkersDictionary, ArUcoBoard, ArUcoTracker, ArUcoCamera
import cv2 as cv
def main():
"""
Captures board pictures and finally outputs camera calibration data into a .json file.
- Export and print a calibration board using
- Place the calibration board in order to view it entirely on screen and move the camera in many configurations (orientation and distance) : the script will automatically take pictures. Do this step with a good lighting and a clear background.
- Once enough pictures have been captured (~20), press Esc key then, wait for the camera calibration processing.
- Finally, check rms parameter: it should be between 0. and 1. if the calibration succeeded (lower is better).
### Reference:
- [Camera calibration using ArUco marker tutorial](https://automaticaddison.com/how-to-perform-camera-calibration-using-opencv/)
"""
# manage arguments
parser = argparse.ArgumentParser(description=main.__doc__.split('-')[0])
parser.add_argument('columns', metavar='COLS_NUMBER', type=int, default=7, help='number of columns')
parser.add_argument('rows', metavar='ROWS_NUMBER', type=int, default=5, help='number of rows')
parser.add_argument('square_size', metavar='SQUARE_SIZE', type=float, default=5, help='square size (cm)')
parser.add_argument('marker_size', metavar='MARKER_SIZE', type=float, default=3, help='marker size (cm)')
parser.add_argument('-t', '--tobii_ip', metavar='TOBII_IP', type=str, default=None, help='tobii glasses ip')
parser.add_argument('-o', '--output', metavar='OUT', type=str, default='camera.json', help='destination filepath')
parser.add_argument('-d', '--dictionary', metavar='DICT', type=ArUcoMarkersDictionary.ArUcoMarkersDictionary, default='DICT_ARUCO_ORIGINAL', help='aruco marker dictionnary (DICT_4X4_50, DICT_4X4_100, DICT_4X4_250, DICT_4X4_1000, DICT_5X5_50, DICT_5X5_100, DICT_5X5_250, DICT_5X5_1000, DICT_6X6_50, DICT_6X6_100, DICT_6X6_250, DICT_6X6_1000, DICT_7X7_50, DICT_7X7_100, DICT_7X7_250, DICT_7X7_1000, DICT_ARUCO_ORIGINAL, DICT_APRILTAG_16h5, DICT_APRILTAG_25h9, DICT_APRILTAG_36h10, DICT_APRILTAG_36h11)')
args = parser.parse_args()
# Create tobii controller (with auto discovery network process if no ip argument is provided)
print("Looking for a Tobii Glasses Pro 2 device ...")
try:
tobii_controller = TobiiController.TobiiController(args.tobii_ip)
print(f'Tobii Glasses Pro 2 device found at {tobii_controller.address} address.')
except ConnectionError as e:
print(e)
exit()
# Setup camera at 25 fps to work on Full HD video stream
tobii_controller.set_video_freq_25()
# Enable tobii video stream
tobii_video_stream = tobii_controller.enable_video_stream()
# Create aruco camera
aruco_camera = ArUcoCamera.ArUcoCamera()
# Create aruco board
aruco_board = ArUcoBoard.ArUcoBoard(args.dictionary, args.columns, args.rows, args.square_size, args.marker_size)
# Create aruco tracker
aruco_tracker = ArUcoTracker.ArUcoTracker(args.dictionary, args.marker_size, aruco_camera)
# Start tobii glasses streaming
tobii_controller.start_streaming()
print("Camera calibration starts")
print("Waiting for calibration board...")
expected_markers_number = aruco_board.markers_number
expected_corners_number = aruco_board.corners_number
# Capture loop
try:
while tobii_video_stream.is_alive():
# capture frame with a full displayed board
video_ts, video_frame = tobii_video_stream.read()
# track all markers in the board
aruco_tracker.track_board(video_frame.matrix, aruco_board, expected_markers_number)
# draw only markers
aruco_tracker.draw_tracked_markers(video_frame.matrix)
# draw current calibration data count
cv.putText(video_frame.matrix, f'Capture: {aruco_camera.calibration_data_count}', (50, 50), cv.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2, cv.LINE_AA)
cv.imshow('Tobii Camera Calibration', video_frame.matrix)
# if all board corners are detected
if aruco_tracker.board_corners_number == expected_corners_number:
# draw board corners to notify a capture is done
aruco_tracker.draw_board(video_frame.matrix)
# append data
aruco_camera.store_calibration_data(aruco_tracker.board_corners, aruco_tracker.board_corners_ids)
cv.imshow('Tobii Camera Calibration', video_frame.matrix)
# close window using 'Esc' key
if cv.waitKey(1) == 27:
break
# exit on 'ctrl+C' interruption
except KeyboardInterrupt:
pass
# stop frame display
cv.destroyAllWindows()
# Stop tobii glasses streaming
tobii_controller.stop_streaming()
print('\nCalibrating camera...')
aruco_camera.calibrate(aruco_board, video_frame.width, video_frame.height)
print('\nCalibration succeeded!')
print(f'\nRMS:\n{aruco_camera.rms}')
print(f'\nDimensions:\n{video_frame.width}x{video_frame.height}')
print(f'\nCamera matrix:\n{aruco_camera.K}')
print(f'\nDistortion coefficients:\n{aruco_camera.D}')
aruco_camera.save_calibration_file(args.output)
print(f'\nCalibration data exported into {args.output} file')
if __name__ == '__main__':
main()
|