]> rtime.felk.cvut.cz Git - hercules2020/kcf.git/blob - vot_trax.h
Remove debug printf
[hercules2020/kcf.git] / vot_trax.h
1 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
2 /*
3  * This header file contains C functions that can be used to quickly integrate
4  * VOT challenge support into your C or C++ tracker.
5  *
6  * Copyright (c) 2015, VOT Committee
7  * All rights reserved.
8  * 
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met: 
11
12  * 1. Redistributions of source code must retain the above copyright notice, this
13  *    list of conditions and the following disclaimer. 
14  * 2. Redistributions in binary form must reproduce the above copyright notice,
15  *    this list of conditions and the following disclaimer in the documentation
16  *    and/or other materials provided with the distribution. 
17
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
22  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  * 
29  * The views and conclusions contained in the software and documentation are those
30  * of the authors and should not be interpreted as representing official policies, 
31  * either expressed or implied, of the FreeBSD Project.
32  */
33
34 #ifndef _VOT_TOOLKIT_H
35 #define _VOT_TOOLKIT_H
36
37 #include <stdlib.h>
38 #include <stdio.h>
39 #include <string.h>
40 #include <ctype.h>
41 #include <assert.h>
42
43 #define VOT_READ_BUFFER 2024
44
45 // Newer compilers support interactive checks for headers, otherwise we have to enable TraX support manually
46 #ifdef __has_include
47 #  if __has_include("trax.h")
48 #    include <trax.h>
49 #    define VOT_TRAX
50 #  endif
51 #else
52 #  ifdef TRAX
53 #    include <trax.h>
54 #    define VOT_TRAX
55 #  endif
56 #endif
57
58 // Alternative getline implementation for Windows compatibility
59 size_t _getline(char **lineptr, size_t *n, FILE *stream) {
60
61     char *bufptr = NULL;
62     char *p = bufptr;
63     size_t size;
64     int c;
65
66     if (lineptr == NULL) {
67         return -1;
68     }
69
70     if (stream == NULL) {
71         return -1;
72     }
73
74     if (n == NULL) {
75         return -1;
76     }
77
78     bufptr = *lineptr;
79     size = *n;
80
81     c = fgetc(stream);
82     if (c == EOF) {
83         return -1;
84     }
85     if (bufptr == NULL) {
86         bufptr = (char *) malloc(128);
87         if (bufptr == NULL) {
88                 return -1;
89         }
90         size = 128;
91     }
92     p = bufptr;
93     while(c != EOF) {
94         if ((p - bufptr) > (size - 1)) {
95                 size = size + 128;
96                 bufptr = (char *) realloc(bufptr, size);
97                 if (bufptr == NULL) {
98                         return -1;
99                 }
100         }
101         *p++ = c;
102         if (c == '\n') {
103                 break;
104         }
105         c = fgetc(stream);
106     }
107
108     *p++ = '\0';
109     *lineptr = bufptr;
110     *n = size;
111
112     return p - bufptr - 1;
113 }
114
115 // Define VOT_OPENCV after including OpenCV core header to enable better OpenCV support
116 #ifdef __OPENCV_CORE_HPP__
117 #  define VOT_OPENCV
118 #endif
119
120 #ifndef VOT_RECTANGLE
121 #define VOT_POLYGON
122 #endif
123
124 #ifdef VOT_POLYGON
125 typedef struct vot_region {
126     float* x;
127     float* y;
128     int count;
129 } vot_region;
130
131 void vot_region_release(vot_region** region) {
132     if (!(*region)) return;
133
134     if ((*region)->x) {
135         free((*region)->x);
136         (*region)->x = NULL;
137     }
138     if ((*region)->y) {
139         free((*region)->y);
140         (*region)->y = NULL;
141     }
142
143     free(*region);
144
145     *region = NULL;
146 }
147
148 vot_region* vot_region_create(int n) {
149     vot_region* region = (vot_region*) malloc(sizeof(vot_region));
150     region->x = (float *) malloc(sizeof(float) * n);
151     region->y = (float *) malloc(sizeof(float) * n);
152     memset(region->x, 0, sizeof(float) * n);
153     memset(region->y, 0, sizeof(float) * n);
154     region->count = n;
155     return region;
156 }
157
158 vot_region* vot_region_copy(const vot_region* region) {
159     vot_region* copy = vot_region_create(region->count);
160     int i;
161     for (i = 0; i < region->count; i++) {
162         copy->x[i] = region->x[i];
163         copy->y[i] = region->y[i];
164     }
165     return copy;
166 }
167
168 #else
169 typedef struct vot_region {
170     float x;
171     float y;
172     float width;
173     float height;
174 } vot_region;
175
176 void vot_region_release(vot_region** region) {
177
178     if (!(*region)) return;
179
180     free(*region);
181
182     *region = NULL;
183
184 }
185
186 vot_region* vot_region_create() {
187     vot_region* region = (vot_region*) malloc(sizeof(vot_region));
188     region->x = 0;
189     region->y = 0;
190     region->width = 0;
191     region->height = 0;
192     return region;
193 }
194
195 vot_region* vot_region_copy(const vot_region* region) {
196     vot_region* copy = vot_region_create();
197     copy->x = region->x;
198     copy->y = region->y;
199     copy->width = region->width;
200     copy->height = region->height;
201     return copy;
202 }
203
204
205 #endif
206
207 vot_region* _parse_region(char* buffer) {
208
209     int i;
210     float* numbers = (float*) malloc(sizeof(float) * (strlen(buffer) / 2));
211         char* pch = strtok(buffer, ",");
212
213     for (i = 0; ; i++) {
214         if (!pch) break;
215         numbers[i] = (float) atof(pch); 
216                 pch = strtok(NULL, ",");
217     }
218
219     vot_region* region;
220
221 #ifdef VOT_POLYGON
222     {
223         // Check if region is actually a rectangle and convert it
224         if (i == 4) {
225
226             region = vot_region_create(4);
227
228                         region->count = 4;
229
230                         region->x[0] = numbers[0];
231                         region->x[1] = numbers[0] + numbers[2];
232                         region->x[2] = numbers[0] + numbers[2];
233                         region->x[3] = numbers[0];
234
235                         region->y[0] = numbers[1];
236                         region->y[1] = numbers[1];
237                         region->y[2] = numbers[1] + numbers[3];
238                         region->y[3] = numbers[1] + numbers[3];
239
240
241         } else {
242             int count = i / 2;
243             assert(count >= 3);
244
245             region = vot_region_create(count);
246
247             for (i = 0; i < count; i++) {
248                 region->x[i] = numbers[i*2];
249                 region->y[i] = numbers[i*2+1];
250             }
251
252             region->count = count;
253         }
254     }
255 #else
256     {
257         assert(i > 3);
258
259         region = vot_region_create();
260
261         // Check if the input region is actually a polygon and convert it
262         if (i > 6) {
263             int j;
264                     float top = FLT_MAX;
265                     float bottom = FLT_MIN;
266                     float left = FLT_MAX;
267                     float right = FLT_MIN;
268
269                     for (j = 0; j < i / 2; j++) {
270                             top = MIN(top, numbers[j * 2 + 1]);
271                             bottom = MAX(bottom, numbers[j * 2 + 1]);
272                             left = MIN(left, numbers[j * 2]);
273                             right = MAX(right, numbers[j * 2]);
274                     }
275
276                 region->x = left;
277                 region->y = top;
278                 region->width = right - left;
279                 region->height = bottom - top;
280
281         } else {
282             region = vot_region_create();
283             region->x = numbers[0];
284             region->y = numbers[1];
285             region->width = numbers[2];
286             region->height = numbers[3];
287         }
288     }
289 #endif
290
291     free(numbers);
292
293     return region;
294 }
295
296 #ifdef __cplusplus
297
298 #include <string>
299 #include <fstream>
300 #include <iostream>
301
302 using namespace std;
303
304 class VOT;
305
306 class VOTRegion {
307     friend class VOT;
308 public:
309
310     ~VOTRegion() {
311         vot_region_release(&_region);
312     }
313
314     VOTRegion(const vot_region* region) {
315         _region = vot_region_copy(region);
316     }
317
318 #ifdef VOT_POLYGON
319     VOTRegion(int count) {
320         _region = vot_region_create(count);
321     }
322
323     void set(int i, float x, float y) { assert(i >= 0 && i < _region->count); _region->x[i] = x; _region->y[i] = y; }
324     float get_x(int i) const { assert(i >= 0 && i < _region->count); return _region->x[i]; } 
325     float get_y(int i) const { assert(i >= 0 && i < _region->count); return _region->y[i]; }
326     int count() const { return _region->count; }
327
328 #else
329
330     VOTRegion() {
331         _region = vot_region_create();
332     }
333
334     float get_x() const { return _region->x; }
335     float get_y() const { return _region->y; }
336     float get_width() const { return _region->width; }
337     float get_height() const { return _region->height; }
338
339     float set_x(float x) { return _region->x = x; }
340     float set_y(float y) { return _region->y = y; }
341     float set_width(float width) { return _region->width = width; }
342     float set_height(float height) { return _region->height = height; }
343
344 #endif
345
346     VOTRegion& operator= (const VOTRegion &source) {
347
348         if (this == &source)
349             return *this;
350
351 #ifdef VOT_POLYGON
352
353         if (this->_region->count != source.count()) {
354             vot_region_release(&(this->_region));
355             this->_region = vot_region_create(source.count());
356         }
357
358         for (int i = 0; i < source.count(); i++) {
359             set(i, source.get_x(i), source.get_y(i));
360         }
361
362 #else
363
364         set_x(source.get_x());
365         set_y(source.get_y());
366         set_width(source.get_width());
367         set_height(source.get_height());
368
369 #endif
370
371         return *this;
372     }
373
374 #ifdef VOT_OPENCV
375
376     VOTRegion(const cv::Rect& rectangle) {
377 #ifdef VOT_POLYGON
378         _region = vot_region_create(4);
379 #else
380         _region = vot_region_create();
381 #endif
382         set(rectangle);
383     }
384
385     void set(const cv::Rect& rectangle) {
386
387 #ifdef VOT_POLYGON
388
389         if (_region->count != 4) {
390             vot_region_release(&(this->_region));
391             _region = vot_region_create(4);
392         }
393
394             set(0, rectangle.x, rectangle.y);
395             set(1, rectangle.x + rectangle.width, rectangle.y);
396             set(2, rectangle.x + rectangle.width, rectangle.y + rectangle.height);
397             set(3, rectangle.x, rectangle.y + rectangle.height);
398
399 #else
400
401         set_x(rectangle.x);
402         set_y(rectangle.y);
403         set_width(rectangle.width);
404         set_height(rectangle.height);
405
406 #endif
407
408     }
409
410     void get(cv::Rect& rectangle) const {
411
412 #ifdef VOT_POLYGON
413
414             float top = FLT_MAX;
415             float bottom = FLT_MIN;
416             float left = FLT_MAX;
417             float right = FLT_MIN;
418
419             for (int j = 0; j < _region->count; j++) {
420                     top = MIN(top, _region->y[j]);
421                     bottom = MAX(bottom, _region->y[j]);
422                     left = MIN(left, _region->x[j]);
423                     right = MAX(right, _region->x[j]);
424             }
425
426         rectangle.x = left;
427         rectangle.y = top;
428         rectangle.width = right - left;
429         rectangle.height = bottom - top;
430 #else
431
432         rectangle.x = get_x();
433         rectangle.y = get_y();
434         rectangle.width = get_width();
435         rectangle.height = get_height();
436
437 #endif
438
439     }
440
441     void operator= (cv::Rect& rectangle) {
442         this->get(rectangle);
443     }
444
445 #endif
446
447 protected:
448
449     vot_region* _region;
450
451 };
452
453 #ifdef VOT_OPENCV
454
455 void operator<< (VOTRegion &source, const cv::Rect& rectangle) {
456     source.set(rectangle);
457 }
458
459 void operator>> (const VOTRegion &source, cv::Rect& rectangle) {
460     source.get(rectangle);
461 }
462
463 void operator<< (cv::Rect& rectangle, const VOTRegion &source) {
464     source.get(rectangle);
465 }
466
467 void operator>> (const cv::Rect& rectangle, VOTRegion &source) {
468     source.set(rectangle);
469 }
470
471
472 #endif
473
474 class VOT {
475 public:
476     VOT() {
477         _region = vot_initialize(); 
478     }
479
480     ~VOT() {
481         vot_quit();
482     }
483
484     const VOTRegion region() { 
485         return VOTRegion(_region);
486     }
487
488     void report(const VOTRegion& region) {
489
490         vot_report(region._region);
491
492     }
493
494     const string frame() {
495
496         const char* result = vot_frame();
497
498         if (!result)
499             return string();
500
501         return string(result);
502     }
503
504     bool end() {
505         return vot_end() != 0;
506     }
507
508
509 private:
510
511     vot_region* vot_initialize();
512
513     void vot_quit();
514
515     const char* vot_frame();
516
517     void vot_report(vot_region* region);
518
519     int vot_end();
520
521     vot_region* _region;
522
523 #endif
524
525     // Current position in the sequence
526     int _vot_sequence_position;
527     // Size of the sequence
528     int _vot_sequence_size;
529     // List of image file names
530     char** _vot_sequence;
531     // List of results
532     vot_region** _vot_result;
533
534 #ifdef VOT_TRAX
535
536     trax_handle* _trax_handle;
537     char _trax_image_buffer[VOT_READ_BUFFER];
538
539 #ifdef VOT_POLYGON
540
541 vot_region* _trax_to_region(const trax_region* _trax_region) {
542     int i;
543     int count = trax_region_get_polygon_count(_trax_region);
544     vot_region* region = vot_region_create(count);
545     for (i = 0; i < count; i++)
546         trax_region_get_polygon_point(_trax_region, i, &(region->x[i]), &(region->y[i]));
547     return region;
548 }
549 trax_region* _region_to_trax(const vot_region* region) {
550     int i;
551     trax_region* _trax_region = trax_region_create_polygon(region->count);
552     assert(trax_region_get_type(_trax_region) == TRAX_REGION_POLYGON);
553     for (i = 0; i < region->count; i++)
554         trax_region_set_polygon_point(_trax_region, i, region->x[i], region->y[i]);
555     return _trax_region;
556 }
557 #else
558
559 vot_region* _trax_to_region(const trax_region* _trax_region) {
560     vot_region* region = vot_region_create();
561     assert(trax_region_get_type(_trax_region) == TRAX_REGION_RECTANGLE);
562     trax_region_get_rectangle(_trax_region, &(region->x), &(region->y), &(region->width), &(region->height));
563     return region;
564 }
565 trax_region* _region_to_trax(const vot_region* region) {
566     return trax_region_create_rectangle(region->x, region->y, region->width, region->height);
567 }
568
569 #endif
570 #endif
571
572 #ifdef __cplusplus
573
574 };
575
576 #endif
577
578 #ifdef __cplusplus
579 #  define VOT_PREFIX(FUN) VOT::FUN
580 #else
581 #  define VOT_PREFIX(FUN) FUN
582 #endif
583
584
585 /**
586  * Reads the input data and initializes all structures. Returns the initial 
587  * position of the object as specified in the input data. This function should
588  * be called at the beginning of the program.
589  */
590 vot_region* VOT_PREFIX(vot_initialize)() {
591
592     int j;
593     FILE *inputfile;
594     FILE *imagesfile;
595
596     _vot_sequence_position = 0;
597     _vot_sequence_size = 0;
598
599 #ifdef VOT_TRAX
600     if (getenv("TRAX")) {
601         trax_configuration config;
602         trax_image* _trax_image = NULL;
603         trax_region* _trax_region = NULL;
604         _trax_handle = NULL;
605         int response;
606
607         #ifdef VOT_POLYGON
608         config.format_region = TRAX_REGION_POLYGON;
609         #else
610         config.format_region = TRAX_REGION_RECTANGLE;
611         #endif
612         config.format_image = TRAX_IMAGE_PATH;
613         _trax_handle = trax_server_setup(config, NULL);
614
615         response = trax_server_wait(_trax_handle, &_trax_image, &_trax_region, NULL);
616
617         assert(response == TRAX_INITIALIZE);
618
619         strcpy(_trax_image_buffer, trax_image_get_path(_trax_image));
620
621         trax_server_reply(_trax_handle, _trax_region, NULL);
622
623         vot_region* region = _trax_to_region(_trax_region);
624
625         trax_region_release(&_trax_region);
626         trax_image_release(&_trax_image);
627         
628         return region;
629     }
630 #endif
631
632     inputfile = fopen("region.txt", "r");
633     imagesfile = fopen("images.txt", "r");
634
635     if (!inputfile) {
636         fprintf(stderr, "Initial region file (region.txt) not available. Stopping.\n");
637         exit(-1);
638     }
639
640     if (!imagesfile) {
641         fprintf(stderr, "Image list file (images.txt) not available. Stopping.\n");
642         exit(-1);
643     }
644
645     int linelen;
646     size_t linesiz = sizeof(char) * VOT_READ_BUFFER;
647     char* linebuf = (char*) malloc(sizeof(char) * VOT_READ_BUFFER);
648     
649     _getline(&linebuf, &linesiz, inputfile);
650     vot_region* region = _parse_region(linebuf);
651
652     fclose(inputfile);
653
654     j = 32;
655     _vot_sequence = (char**) malloc(sizeof(char*) * j);
656
657     while (1) {
658
659         if ((linelen = _getline(&linebuf, &linesiz, imagesfile))<1)
660             break;
661
662         if ((linebuf)[linelen - 1] == '\n') {
663             (linebuf)[linelen - 1] = '\0';
664         }
665
666         if (_vot_sequence_size == j) {
667             j += 32;
668             _vot_sequence = (char**) realloc(_vot_sequence, sizeof(char*) * j);
669         }
670
671         _vot_sequence[_vot_sequence_size] = (char *) malloc(sizeof(char) * (strlen(linebuf) + 1));
672
673         strcpy(_vot_sequence[_vot_sequence_size], linebuf);
674
675         _vot_sequence_size++;
676     }
677
678     free(linebuf);
679
680     _vot_result = (vot_region**) malloc(sizeof(vot_region*) * _vot_sequence_size);
681
682     return region;
683 }
684
685 /**
686  * Stores results to the result file and frees memory. This function should be 
687  * called at the end of the tracking program.
688  */
689 void VOT_PREFIX(vot_quit)() {
690
691     int i;
692
693 #ifdef VOT_TRAX
694     if (_trax_handle) {
695         trax_cleanup(&_trax_handle);
696         return;
697     }
698 #endif
699
700     FILE *outputfile = fopen("output.txt", "w");
701
702     for (i = 0; i < _vot_sequence_position; i++) {
703 #ifdef VOT_POLYGON
704         {
705             int j;
706             fprintf(outputfile, "%f,%f", _vot_result[i]->x[0], _vot_result[i]->y[0]); 
707             for (j = 1; j < _vot_result[i]->count; j++)
708                 fprintf(outputfile, ",%f,%f", _vot_result[i]->x[j], _vot_result[i]->y[j]); 
709             fprintf(outputfile, "\n"); 
710         }
711 #else
712         fprintf(outputfile, "%f,%f,%f,%f\n", _vot_result[i]->x, _vot_result[i]->y, _vot_result[i]->width, _vot_result[i]->height); 
713 #endif
714         vot_region_release(&(_vot_result[i]));
715     }
716
717     fclose(outputfile);
718
719     if (_vot_sequence) {
720         for (i = 0; i < _vot_sequence_size; i++)
721             free(_vot_sequence[i]);
722
723         free(_vot_sequence);
724     }
725
726     if (_vot_result)
727         free(_vot_result);
728
729 }
730
731 /**
732  * Returns the file name of the current frame. This function does not advance 
733  * the current position.
734  */
735 const char* VOT_PREFIX(vot_frame)() {
736
737 #ifdef VOT_TRAX
738     if (_trax_handle) {
739         int response;
740         trax_image* _trax_image = NULL;
741         trax_region* _trax_region = NULL;
742
743         if (_vot_sequence_position == 0) {
744             _vot_sequence_position++;
745             return _trax_image_buffer;
746         }
747
748         response = trax_server_wait(_trax_handle, &_trax_image, &_trax_region, NULL);
749
750         if (response != TRAX_FRAME) {
751             vot_quit();
752             exit(0);
753         }
754
755         strcpy(_trax_image_buffer, trax_image_get_path(_trax_image));
756         trax_image_release(&_trax_image);
757
758         return _trax_image_buffer;
759
760     }
761 #endif
762
763     if (_vot_sequence_position >= _vot_sequence_size)
764         return NULL;
765
766     return _vot_sequence[_vot_sequence_position];
767
768 }
769
770 /**
771  * Used to report position of the object. This function also advances the
772  * current position.
773  */
774 void VOT_PREFIX(vot_report)(vot_region* region) {
775
776 #ifdef VOT_TRAX
777     if (_trax_handle) {
778         trax_region* _trax_region = _region_to_trax(region);
779         trax_server_reply(_trax_handle, _trax_region, NULL);
780         trax_region_release(&_trax_region);
781         return;
782     }
783 #endif
784
785     if (_vot_sequence_position >= _vot_sequence_size)
786         return;
787         
788     _vot_result[_vot_sequence_position] = vot_region_copy(region);
789     _vot_sequence_position++;
790 }
791
792 int VOT_PREFIX(vot_end)() {
793
794 #ifdef VOT_TRAX
795     return 0;
796 #endif
797
798     if (_vot_sequence_position >= _vot_sequence_size)
799         return 1;
800         
801     return 0;
802 }
803
804 #endif
805