VisageTrackerDemo

SimpleTracker.cpp
Go to the documentation of this file.
1 //doxygen
2 /*! \file */
3
4
5 #include "cv.h"
6 #include "highgui.h"
7 #include <stdio.h>
8 #include <unistd.h>
9 #include "visageVision.h"
10 #include "Common.h"
11 #include "term.h"
12 #include <math.h>
13 #include <sys/timeb.h>
14 #include "VisageDrawing.h"
15 #include "LicenseString.h"
16 #include <string>
17
18 using namespace VisageSDK;
19
20 VisageTracker *m_Tracker = 0;
21
22 IplImage *framePtr = 0;
23
24 const int MAX_FACES = 4;
25 static FaceData trackingData[MAX_FACES];
26
27 int *track_stat = 0;
28
29 CvCapture* capture;
30
31 long trackingTime;
32
33 //if user closes window used for displaying results, this will be set to 1 and tracking will stop
34 bool exitApp;
35
36 IplImage *imageBGRA;
37
38 /**
39 *
40 */
41 void flushInput(void)
42 {
43 int c;
44
45 do
46 {
47 c = getchar();
48 } while (c != '\n' && c != EOF);
49 }
50
51 /**
52 * Function for clearing console window.
53 */
54 void clearScreen(void)
55 {
56 if (!cur_term)
57 {
58 int result;
59 setupterm( NULL, STDOUT_FILENO, &result );
60
61 if (result <= 0) return;
62 }
63
64 putp( tigetstr( "clear" ) );
65 }
66
67 void displayResults()
68 {
69 //if user closes window used for displaying results, tracking will stop
70 if (!cvGetWindowHandle("SimpleTracker"))
71 {
72 exitApp = true;
73 return;
74 }
75
76 clearScreen();
77 printf("Tracking in progress!\n\n");
78
79 char *tstatus;
80
81 for (int i = 0; i < MAX_FACES; i++)
82 {
83 if (track_stat[i] == TRACK_STAT_OFF)
84 tstatus = "OFF";
85 }
86
87 for (int i = 0; i < MAX_FACES; i++)
88 {
89 if (track_stat[i] == TRACK_STAT_INIT)
90 tstatus = "INITIALIZING";
91 }
92
93 for (int i = 0; i < MAX_FACES; i++)
94 {
95 if (track_stat[i] == TRACK_STAT_RECOVERING)
96 tstatus = "RECOVERING";
97 }
98
99 for (int i = 0; i < MAX_FACES; i++)
100 {
101 if (track_stat[i] == TRACK_STAT_OK)
102 tstatus = "OK";
103 }
104
105 printf(" Tracking status: %s\n\n", tstatus);
106
107 static float eyeDistance = -1.0f;
108
109 // Example code for accessing specific feature points, in this case nose tip and eyes
110 if(track_stat[0] == TRACK_STAT_OK)
111 {
112 FDP *fp = trackingData[0].featurePoints3DRelative;
113 float nosex = fp->getFPPos(9,3)[0];
114 float nosey = fp->getFPPos(9,3)[1];
115 float nosez = fp->getFPPos(9,3)[2];
116 float lex = fp->getFPPos(3,5)[0];
117 float ley = fp->getFPPos(3,5)[1];
118 float lez = fp->getFPPos(3,5)[2];
119 float rex = fp->getFPPos(3,6)[0];
120 float rey = fp->getFPPos(3,6)[1];
121 float rez = fp->getFPPos(3,6)[2];
122 float eyedist = lex -rex;
123 int dummy = 0;
124 }
125
126 // display the frame rate, position and other info
127 float trackingFrameRate = trackingData[0].frameRate;
128
129 if (imageBGRA)
130 printf(" %4.1f FPS (track %ld ms) \n Resolution: input %dx%d\n\n",trackingFrameRate, trackingTime, framePtr->width, framePtr->height);
131
132 cvShowImage("SimpleTracker",imageBGRA);
133 cvWaitKey(10);
134
135 if (imageBGRA)
136 cvReleaseImage(&imageBGRA);
137 }
138
139
140 /**
141 * Function used for measuring tracker speed.
142 * Used for video synchronization (if flag video_file_sync is set to 1)
143 *
144 */
145 static long getCurrentTimeMs()
146 {
147 struct timeb timebuffer;
148 ftime( &timebuffer );
149
150 long clockTime = 1000 * (long)timebuffer.time + timebuffer.millitm;
151
152 return clockTime;
153 }
154
155
156 /**
157 * The main function for tracking from a video file.
158 * It is called when the 'v' is chosen.
159 *
160 */
161 void trackFromVideo(const char *strAviFile)
162 {
163 double frameTime;
164 int frameCount = 0;
165
166 //If the flag is set to 1 playback is synchronised by skipping video frames
167 //or introducing delay as needed, so the video file is played at its normal (or desired) speed (set variable targetFps to desired fps)
168 bool video_file_sync = true;
169
170 long currentTime;
171
172 //set to desired fps you wish to achieve from tracker
173 float targetFps = 30.0;
174 //float targetFps = cvGetCaptureProperty( capture, CV_CAP_PROP_FPS );
175
176 cvNamedWindow("SimpleTracker", CV_WINDOW_AUTOSIZE);
177 cvMoveWindow("SimpleTracker",100,100);
178
179 capture = cvCaptureFromFile(strAviFile);
180
181 if(!capture)
182 {
183 printf("Can't read video file.");
184 return;
185 }
186
187 // moment when video started
188 long startTime = getCurrentTimeMs();
189
190 //frame duration if video fps was equal to targetFps
191 frameTime = 1000.0/targetFps;
192
193 IplImage *logo = cvLoadImage("../Samples/Linux/data/images/logo.png", CV_LOAD_IMAGE_UNCHANGED);
194
195 //tracking is performed while user doesn't close window for displaying results
196 while(!exitApp)
197 {
198 if(!capture) break;
199
200 if (!cvGrabFrame( capture )) break;
201
202 frameCount++;
203
204 if (video_file_sync)
205 {
206 currentTime = getCurrentTimeMs();
207
208 //checking if tracker is too slow
209 while((currentTime-startTime) > frameTime*(1+frameCount) )
210 {
211 if( !cvGrabFrame( capture )) return; //end of stream
212
213 frameCount++;
214 currentTime = getCurrentTimeMs();
215 }
216
217 currentTime = getCurrentTimeMs();
218
219 //checking if tracker is too fast (we don't want to risk unnecessary delay so we allow some extra frames, that's why framecount-5)
220 while((currentTime-startTime) < frameTime*(frameCount-5))
221 {
222 sleep(0.001);
223 currentTime = getCurrentTimeMs();
224 }
225 }
226
227 if(!(framePtr = cvRetrieveFrame( capture ))) break;
228
229 long startTime = getCurrentTimeMs();
230 track_stat = m_Tracker->track(framePtr->width, framePtr->height, (const char*)framePtr->imageData, trackingData, VISAGE_FRAMEGRABBER_FMT_BGR, VISAGE_FRAMEGRABBER_ORIGIN_TL, framePtr->widthStep, frameTime*frameCount, MAX_FACES);
231 long endTime = getCurrentTimeMs();
232 trackingTime = endTime - startTime;
233
234 for (int i = 0; i < MAX_FACES; i++)
235 {
236 if (track_stat[i] == TRACK_STAT_OK)
237 {
238 VisageDrawing::drawResults((VsImage*)framePtr, &trackingData[i]);
239 }
240 }
241
242 imageBGRA = cvCreateImage(cvSize(framePtr->width, framePtr->height), IPL_DEPTH_8U, 4);
243 cvCvtColor(framePtr, imageBGRA, CV_BGR2BGRA);
244
245 if (logo)
246 {
247 VisageDrawing::drawLogo((VsImage*)imageBGRA, (VsImage*)logo);
248 }
249
250 displayResults();
251 }
252
253 cvReleaseCapture(&capture);
254 cvReleaseImage(&logo);
255 }
256
257
258 /**
259 * The main function for tracking from a video camera connected to the computer.
260 * It is called when the 'c' is chosen.
261 *
262 */
263 void trackFromCam()
264 {
265 double cam_width = 640;
266 double cam_height = 480;
267 double cam_device = 0;
268
269 cvNamedWindow("SimpleTracker", CV_WINDOW_AUTOSIZE);
270 cvMoveWindow("SimpleTracker",100,100);
271
272 capture = cvCaptureFromCAM( cam_device );
273 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_WIDTH, cam_width);
274 cvSetCaptureProperty(capture, CV_CAP_PROP_FRAME_HEIGHT, cam_height);
275 cvSetCaptureProperty(capture, CV_CAP_PROP_FPS, 30);
276
277 if(!capture )
278 {
279 printf("Can't initialize camera (OpenCV). Please check if your camera is installed properly.\n\n");
280 return;
281 }
282
283 IplImage *logo = cvLoadImage("../Samples/Linux/data/images/logo.png", CV_LOAD_IMAGE_UNCHANGED);
284 while(!exitApp)
285 {
286 if(!capture ) break;
287
288 if( !cvGrabFrame( capture )) break;
289
290 if(!(framePtr = cvRetrieveFrame( capture ))) break;
291
292 cvFlip(framePtr, framePtr, 1);
293 long startTime = getCurrentTimeMs();
294 track_stat = m_Tracker->track(framePtr->width, framePtr->height, (const char*)framePtr->imageData, trackingData, VISAGE_FRAMEGRABBER_FMT_BGR, VISAGE_FRAMEGRABBER_ORIGIN_TL, 0, -1, MAX_FACES);
295 long endTime = getCurrentTimeMs();
296 trackingTime = endTime - startTime;
297
298 for (int i= 0; i<MAX_FACES; i++)
299 {
300 if (track_stat[i] == TRACK_STAT_OK)
301 {
302 VisageDrawing::drawResults((VsImage*)framePtr, &trackingData[i]);
303 }
304 }
305
306 imageBGRA = cvCreateImage(cvSize(framePtr->width, framePtr->height), IPL_DEPTH_8U, 4);;
307 cvCvtColor(framePtr, imageBGRA, CV_BGR2BGRA);
308
309 if (logo)
310 {
311 VisageDrawing::drawLogo((VsImage*)imageBGRA, (VsImage*)logo);
312 }
313
314 displayResults();
315 }
316
317 cvReleaseCapture(&capture);
318 cvReleaseImage(&logo);
319 }
320
321 /*! \mainpage visage|SDK VisageTrackerDemo example project
322 *
323 * \htmlonly
324 * <table border="0">
325 * <tr>
326 * <td width="32"><a href="../../../../../bin/VisageTrackerDemo"><img src="../../../../../doc/images/run_sample.png" border=0 title="Run Sample (this may not work in all browsers, in such case please run VisageTrackerDemo from the visageSDK\bin folder.)"></a></td>
327 * <td width="32"><a href="../../../../../bin"><img src="../../../../../doc/images/open_bin_folder.png" border=0 title="Open Executable Folder (visageSDK\bin)"></a></td>
328 * <td width="32"><a href="../../../data"><img src="../../../../../doc/images/open_data_folder.png" border=0 title="Open Data Folder"></a></td>
329 * <td width="32"><a href="../../../data/video"><img src="../../../../../doc/images/open_folder.png" border=0 title="Open Video Folder"></a></td>
330 * <td width="32"><a href="../../../build"><img src="../../../../../doc/images/open_project_folder.png" border=0 title="Open Project Folder"></a></td>
331 * <td width="32"><a href="../../../source/VisageTrackerDemo"><img src="../../../../../doc/images/open_source_folder.png" border=0 title="Open Source Code Folder"></a></td>
332 * </tr>
333 * </table>
334 * \endhtmlonly
335 *
336 * \if REDHAT_DOXY
337 * \htmlonly
338 * <h2>Dependencies</h2>
339 *
340 * Prerequisites to building the sample project are:
341 * <ul>
342 * <li>You should have the Software Development Workstation version of RHEL6 (you can choose the version during the installation of RHEL6)</li>
343 * <li>OpenGL with dynamic libraries: GL, GLU (yum install mesa-libGL-devel mesa-libGLU-devel)</li>
344 * <li>GCC: gcc 7.0+ (sudo yum install gcc-c++)</li>
345 * <li>GTK+ 2.0 with dynamic library: gtk-x11-2.0 (yum install gtk2-devel)</li>
346 * <ul>
347 * <li> provided OpenCV library is built with GTK support</li>
348 * <li>libVision library also uses GTK to display error messages</li>
349 * </ul>
350 * <li>curses terminal control library (yum install ncurses-devel)</li>
351 * <li>FFMPEG with dynamic libraries: swscale, avformat.</li> <br>
352 * FFMPEG libraries which were previously installed using ATRPMS repository are now available on ATRPMS repository mirror server. In order to install them, please do the following steps:
353 * <ul>
354 * <li>1. Install RPM repository package (this step can be skipped if you already have ATRPMS repository installed):</li>
355 * <ul style="list-style-type:none">
356 * <li>$> sudo rpm -ivh <a href="http://ftp-stud.fht-esslingen.de/Mirrors/atrpms/dl.atrpms.net/el7-x86_64/atrpms/stable/atrpms-repo-7-7.el7.x86_64.rpm">http://ftp-stud.fht-esslingen.de/Mirrors/atrpms/dl.atrpms.net/el7-x86_64/atrpms/stable/atrpms-repo-7-7.el7.x86_64.rpm</a> </li>
357 * </ul>
358 * <li>2. Modify atrpms.repo as follows:</li>
359 * <ul style="list-style-type:none">
360 * <li>$> sudo sed -ri 's/baseurl=(.*)/baseurl=http:\/\/ftp-stud.fht-esslingen.de\/Mirrors\/atrpms\/dl.atrpms.net\/el7-x86_64\/atrpms\/stable/g' /etc/yum.repos.d/atrpms.repo </li>
361 * </ul>
362 * <li>3. Run the following command in terminal: </li>
363 * <ul style="list-style-type:none">
364 * <li>$> sudo yum-config-manager --enable atrpms </li>
365 * </ul>
366 * <li>4. Install FFMPEG libraries and create required symlinks:
367 * <ul style="list-style-type:none">
368 * <li>$> sudo yum install libavformat55.x86_64 </li>
369 * <li>$> sudo ln -s /usr/lib64/libavformat.so.55 /usr/lib64/libavformat.so </li>
370 * <li>$> sudo yum install libswscale2.x86_64 </li>
371 * <li>$> sudo ln -s /usr/lib64/libswscale.so.2 /usr/lib64/libswscale.so </li>
372 * <li>$> sudo ln -s /usr/lib64/libjpeg.so.62 /usr/lib64/libjpeg.so </li>
373 * <li>$> sudo ln -s /usr/lib64/libavutil.so.52 /usr/lib64/libavutil.so </li>
374 * <li>$> sudo ln -s /usr/lib64/libavcodec.so.55 /usr/lib64/libavcodec.so </li>
375 * </ul>
376 * </ul>
377 * </ul>
378 * \endhtmlonly
379 * \else
380 * \htmlonly
381 * <h2>Dependencies</h2>
382 *
383 * Prerequisites to building the sample project are:
384 * <ul>
385 * <li>g++ compiler (versions 4.7.x) (sudo apt-get install g++)</li>
386 * <li>OpenGL with dynamic libraries: GL, GLU (sudo apt-get install freeglut3-dev)</li>
387 * <li>OpenCV library (sudo apt-get install libopencv-dev)
388 * <li>Video4Linux library (sudo apt-get install libv4l-dev)</li>
389 * <li>GTK+ 2.0 with dynamic library: gtk-x11-2.0 (sudo apt-get install libgtk2.0-dev)</li>
390 * <li>curses terminal control library (sudo apt-get install libncurses5-dev)</li>
391 * <li>high level programming interface for IEEE1394 digital camera (sudo apt-get install libdc1394-22-dev)</li>
392 * </ul>
393 * </p>
394 * \endhtmlonly
395 * \endif
396 *
397 * \htmlonly
398 * <h2>Running prebuilt sample</h2>
399 * \endhtmlonly
400 *
401 * The VisageTrackerDemo example project demonstrates the following capabilities of visage|SDK:
402 * - real-time head/facial features tracking on multiple faces from video file or camera, with on-the-fly animation, based on the VisageSDK::VisageTracker tracker. Currently, tracking is limited to 4 faces, although this can be modified.
403 *
404 * To use the application:
405 *
406 * Run the './runTracker.sh' command from the terminal\n\n
407 * This is an intentionally simplified version of a tracking application, intended to be used by developers as
408 * an introduction. VisageTrackerDemo is a console application, with keyboard based choices made by the
409 * user. It then starts tracking and displays tracking status and numeric results in the console. Results are also visualized in an additional window as an overlay
410 * over the original image.
411 *
412 * Classes and methods that are important for detailed understanding how this
413 * sample project is implemented and how it used visage|SDK are:
414 * - main(): implements the main user interaction.
415 *
416 * \htmlonly
417 * <h2>Building the project</h2>
418 *
419 * <p>
420 * The VisageTrackerDemo sample project source file is located in the <a href="../../../source/VisageTrackerDemo">Samples/Linux/source/VisageTrackerDemo</a> subfolder of the visage|SDK for Linux folder.
421 * It is built using the provided Makefile located in <a href="../../../build/">Samples/Linux/build </a> subfolder.
422 * </p>
423 * The application needs to be built with license key in order to work properly. More information on how to obtain license key and include it in the application can be found
424 * in <a href="../../../../../doc/licensing.html"><em>Licensing</em></a> section of the documentation.
425
426 * \endhtmlonly
427 */
428
429 /**
430 * The simple tracker.
431 *
432 */
433 int main( int argc, const char* argv[] )
434 {
435 std::string videoFilename;
436 std::string cfgFile;
437 std::string dataPath = "../Samples/data/";
438 char source;
439
440 exitApp = false;
441
442 printf("\nSimple Tracker application\n\n");
443
444 if (argc > 1)
445 {
446 cfgFile = argv[1];
447 }
448 else
449 {
450 printf("Error: no configuration argument provided.\nUsage: %s <configuration_filename> [video_file_path]\nwhere video_file_path argument is optional.\n", argv[0]);
451 return 1;
452 }
453
454 if ((cfgFile == "NeuralNet.cfg") || (cfgFile == "Face Detector.cfg"))
455 {
456 printf("Error: not a valid configuration file.\n");
457 return 1;
458 }
459
460 printf("Track from (v)ideo or (c)am? ");
461 scanf("%c", &source); flushInput();
462
463 if (argc > 2)
464 {
465 videoFilename = argv[2];
466 }
467
468 if ((source == 'v') && (argc == 2))
469 {
470 printf("Error: for track from video functionality second argument should be a path to video file.\n");
471 return 1;
472 }
473
474 initializeLicenseManager(licenseKey.c_str());
475
476 cfgFile = dataPath + cfgFile;
477
478 m_Tracker = new VisageTracker(cfgFile.c_str());
479
480 switch (source)
481 {
482 case 'v':
483 trackFromVideo(videoFilename.c_str());
484 break;
485 case 'c':
486 trackFromCam();
487 break;
488 default:
489 printf("Wrong choice!\n");
490 break;
491 }
492
493 delete m_Tracker;
494 m_Tracker = 0;
495 capture = 0;
496
497 return 0;
498 }
VisageSDK::VisageTracker
main
int main(int argc, const char *argv[])
The simple tracker.
Definition: SimpleTracker.cpp:433
VisageSDK::FaceData::frameRate
float frameRate
VisageSDK::VisageTracker::track
virtual int * track(int frameWidth, int frameHeight, const char *p_imageData, FaceData *facedata, int format=VISAGE_FRAMEGRABBER_FMT_RGB, int origin=VISAGE_FRAMEGRABBER_ORIGIN_TL, int widthStep=0, long timeStamp=-1, int maxFaces=1)
trackFromCam
void trackFromCam()
The main function for tracking from a video camera connected to the computer.
Definition: SimpleTracker.cpp:263
VisageSDK
VisageSDK::FDP::getFPPos
const float * getFPPos(int group, int n) const
VisageSDK::FaceData
trackFromVideo
void trackFromVideo(const char *strAviFile)
The main function for tracking from a video file.
Definition: SimpleTracker.cpp:161
clearScreen
void clearScreen(void)
Function for clearing console window.
Definition: SimpleTracker.cpp:54
VisageSDK::FDP
VisageSDK::FaceData::featurePoints3DRelative
FDP * featurePoints3DRelative
VsImage