-
Notifications
You must be signed in to change notification settings - Fork 1
/
extract_calibration_from_video.m
172 lines (151 loc) · 7.26 KB
/
extract_calibration_from_video.m
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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
% Starburst Algorithm
%
% This source code is part of the starburst algorithm.
% Starburst algorithm is free; you can redistribute it and/or modify
% it under the terms of the GNU General Public License as published by
% the Free Software Foundation; either version 2 of the License, or
% (at your option) any later version.
%
% Starburst algorithm is distributed in the hope that it will be useful,
% but WITHOUT ANY WARRANTY; without even the implied warranty of
% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
% GNU General Public License for more details.
%
% You should have received a copy of the GNU General Public License
% along with cvEyeTracker; if not, write to the Free Software
% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
%
%
% Starburst Algorithm for Visible Spectrum Eye Tracking - Version 1.0.0
% Part of the openEyes ToolKit -- http://hcvl.hci.iastate.edu/openEyes
% Release Date:
% Authors : Dongheng Li <donghengli@gmail.com>
% Derrick Parkhurst <derrick.parkhurst@hcvl.hci.iastate.edu>
% Copyright (c) 2006
% All Rights Reserved.
function extract_calibration_from_video();
% This function extraction the data of calibration for eye tracker.
%
% The user need to specify the directory which contains the /Eye and /Scene image directory. The left
% and right mouse button can be used to browse the images. When the eye is fixing at one of the calibration
% point, the user can indicat the calibration point in the scene image and indicate the start point in
% the eye image. And then the program will highlight the pupil ellipse and the corneal reflection. After
% confirmation of the user, that calibration point correspondence is added. Finally, a file (calibration.mat)
% containing the calibration data and an image (calibration.jpg) of calibration point correspondences will
% be saved in the current directory automatically.
pname = uigetdir(pwd,'Select Dir to save calibration data');
eye_file = sprintf('%s/Eye/Eye_', pname);
scene_file = sprintf('%s/Scene/Scene_', pname);
calibration_data_name = sprintf('%s/calibration.mat', pname);
calibration_image_name = sprintf('%s/calibration.jpg', pname);
synch_eye_minus_scene = 3; %synchronize eye and scene image
start_frame = 205;
% Automatically get the frame number range
first_frame = get_first_or_last_frame_num(sprintf('%s/Eye/', pname), 'Eye_', 5, 'first');
last_frame = get_first_or_last_frame_num(sprintf('%s/Eye/', pname), 'Eye_', 5, 'last');
frame_index = start_frame;
frame_step = 5; % the frame step for browsing
Ie = read_gray_image(eye_file, frame_index+synch_eye_minus_scene);
Is = read_image(scene_file, frame_index);
handle = figure,
subplot(1,2,1); imshow(uint8(Is));
title({'Instruction:'; sprintf('left button=next %d frame', frame_step); ...
sprintf('right button=previous %d frame', frame_step); 'middle button=indicate calibration point in scene';});
subplot(1,2,2); imshow(uint8(Ie));
title(sprintf('frame %d (last frame:%d)', frame_index, last_frame));
fprintf(1,'Instruction:\n left button=next %d frame\n middle button=select calibration point\n right button=previous %d frame\n',frame_step,frame_step);
left_button=1;
middle_button=2;
right_button=3;
cal_frame = zeros(9,1);
cal_scene = zeros(9,2);
cal_ellipse = zeros(9,5);
cal_index = 1;
dis_step = 10;
browse_or_auto_next = 1; % indicator: 1-use mouse click to browse images; 0-auto browse next frame
first_cal = 1;
while cal_index <= 9,
if browse_or_auto_next == 1
[x, y, button] = ginput(1);
else
button = left_button;
browse_or_auto_next = 1;
end
if button == middle_button
cal_frame(cal_index) = frame_index;
cal_scene(cal_index, 1) = x;
cal_scene(cal_index, 2) = y;
hold on;
plot(x, y, 'g+');
title({'Instruction:'; 'Please click near limbus center in the eye image'});
[cx, cy] = ginput(1);
Ie = gaussian_smooth_image(Ie, 1.5);
[cal_ellipse(cal_index,:)] = detect_limbus_two_features(Ie, 15, cx, cy, -pi/5, pi/5, dis_step);
if uint16(cal_ellipse(cal_index,1)) <= 0 || uint16(cal_ellipse(cal_index, 2)) <= 0
title({'ERROR! Ellipse parameter:';
sprintf('major-minor axis(%4.1f,%4.1f); center(%4.1f,%4.1f); angle(%4.1f)', ...
cal_ellipse(cal_index,1), cal_ellipse(cal_index,2), cal_ellipse(cal_index,3), cal_ellipse(cal_index,4), cal_ellipse(cal_index,5))});
else
title(sprintf('Instruction:\n Left button=ellipse is correct\n Other wise=ellipse is wrong, selete another frame'));
plot(cal_ellipse(:,3), cal_ellipse(:,4), 'g+');
ellipse_a = cal_ellipse(cal_index,1);
ellipse_b = cal_ellipse(cal_index,2);
cx = cal_ellipse(cal_index,3);
cy = cal_ellipse(cal_index,4);
ellipse_theta = cal_ellipse(cal_index,5);
t = 0:pi/30:2*pi;
ex = cx + ellipse_a*cos(t);
ey = cy + ellipse_b*sin(t);
X = (ex-cx)*cos(ellipse_theta) + -(ey-cy)*sin(ellipse_theta) + cx;
Y = (ex-cx)*sin(ellipse_theta) + (ey-cy)*cos(ellipse_theta) + cy;
plot(X, Y, 'r');
[x, y, button] = ginput(1);
if button == 1
cal_index = cal_index+1;
else
cal_scene(cal_index,:) = zeros(1,2);
cal_ellipse(cal_index,:) = zeros(1,5);
end
browse_or_auto_next = 0;
end
hold off;
else
Is = [];
Ie = [];
if button == left_button
if frame_index+frame_step > last_frame
fprintf('ERROR! frame index exceed (%d-%d)\n', first_frame, last_frame);
title(sprintf('ERROR! frame index exceed (%d-%d)', first_frame, last_frame));
continue;
end
frame_index = frame_index+frame_step;
else
if frame_index-frame_step < first_frame
fprintf('ERROR! frame index exceed (%d-%d)\n', first_frame, last_frame);
title(sprintf('ERROR! frame index exceed (%d-%d)', first_frame, last_frame));
continue;
end
frame_index = frame_index-frame_step;
end;
Ie = read_gray_image(eye_file, frame_index+synch_eye_minus_scene);
Is = read_image(scene_file, frame_index);
subplot(1,2,2); imshow(uint8(Ie)); hold on;
if cal_index > 1
plot(cal_ellipse(:,3), cal_ellipse(:,4), 'g+');
end
title(sprintf('frame %d (last frame:%d)', frame_index, last_frame));
subplot(1,2,1); imshow(uint8(Is)); hold on;
if cal_index > 1
plot(cal_scene(:,1), cal_scene(:,2), 'g+');
end
title({'Instruction:'; sprintf('left button=next %d frame', frame_step); ...
sprintf('right button=previous %d frame', frame_step); 'middle button=indicate calibration point in scene';});
hold off;
end
end
save(sprintf('%s', calibration_data_name),'cal_scene', 'cal_ellipse', 'cal_frame');
print(handle, '-djpeg', sprintf('%s', calibration_image_name));
function [I] = read_gray_image(file, index);
I = double(rgb2gray(imread(sprintf('%s%05d.jpg', file, index))));
function [I] = read_image(file, index);
I = double(imread(sprintf('%s%05d.jpg', file, index)));