1 /* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
3 * This header file contains C functions that can be used to quickly integrate
4 * VOT challenge support into your C or C++ tracker.
6 * Copyright (c) 2015, VOT Committee
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions are met:
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.
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.
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.
34 #ifndef _VOT_TOOLKIT_H
35 #define _VOT_TOOLKIT_H
43 #define VOT_READ_BUFFER 2024
45 // Newer compilers support interactive checks for headers, otherwise we have to enable TraX support manually
47 # if __has_include("trax.h")
58 // Alternative getline implementation for Windows compatibility
59 size_t _getline(char **lineptr, size_t *n, FILE *stream) {
66 if (lineptr == NULL) {
86 bufptr = (char *) malloc(128);
94 if ((p - bufptr) > (size - 1)) {
96 bufptr = (char *) realloc(bufptr, size);
112 return p - bufptr - 1;
115 // Define VOT_OPENCV after including OpenCV core header to enable better OpenCV support
116 #ifdef __OPENCV_CORE_HPP__
120 #ifndef VOT_RECTANGLE
125 typedef struct vot_region {
131 void vot_region_release(vot_region** region) {
132 if (!(*region)) return;
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);
158 vot_region* vot_region_copy(const vot_region* region) {
159 vot_region* copy = vot_region_create(region->count);
161 for (i = 0; i < region->count; i++) {
162 copy->x[i] = region->x[i];
163 copy->y[i] = region->y[i];
169 typedef struct vot_region {
176 void vot_region_release(vot_region** region) {
178 if (!(*region)) return;
186 vot_region* vot_region_create() {
187 vot_region* region = (vot_region*) malloc(sizeof(vot_region));
195 vot_region* vot_region_copy(const vot_region* region) {
196 vot_region* copy = vot_region_create();
199 copy->width = region->width;
200 copy->height = region->height;
207 vot_region* _parse_region(char* buffer) {
210 float* numbers = (float*) malloc(sizeof(float) * (strlen(buffer) / 2));
211 char* pch = strtok(buffer, ",");
215 numbers[i] = (float) atof(pch);
216 pch = strtok(NULL, ",");
223 // Check if region is actually a rectangle and convert it
226 region = vot_region_create(4);
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];
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];
245 region = vot_region_create(count);
247 for (i = 0; i < count; i++) {
248 region->x[i] = numbers[i*2];
249 region->y[i] = numbers[i*2+1];
252 region->count = count;
259 region = vot_region_create();
261 // Check if the input region is actually a polygon and convert it
265 float bottom = FLT_MIN;
266 float left = FLT_MAX;
267 float right = FLT_MIN;
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]);
278 region->width = right - left;
279 region->height = bottom - top;
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];
311 vot_region_release(&_region);
314 VOTRegion(const vot_region* region) {
315 _region = vot_region_copy(region);
319 VOTRegion(int count) {
320 _region = vot_region_create(count);
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; }
331 _region = vot_region_create();
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; }
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; }
346 VOTRegion& operator= (const VOTRegion &source) {
353 if (this->_region->count != source.count()) {
354 vot_region_release(&(this->_region));
355 this->_region = vot_region_create(source.count());
358 for (int i = 0; i < source.count(); i++) {
359 set(i, source.get_x(i), source.get_y(i));
364 set_x(source.get_x());
365 set_y(source.get_y());
366 set_width(source.get_width());
367 set_height(source.get_height());
376 VOTRegion(const cv::Rect& rectangle) {
378 _region = vot_region_create(4);
380 _region = vot_region_create();
385 void set(const cv::Rect& rectangle) {
389 if (_region->count != 4) {
390 vot_region_release(&(this->_region));
391 _region = vot_region_create(4);
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);
403 set_width(rectangle.width);
404 set_height(rectangle.height);
410 void get(cv::Rect& rectangle) const {
415 float bottom = FLT_MIN;
416 float left = FLT_MAX;
417 float right = FLT_MIN;
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]);
428 rectangle.width = right - left;
429 rectangle.height = bottom - top;
432 rectangle.x = get_x();
433 rectangle.y = get_y();
434 rectangle.width = get_width();
435 rectangle.height = get_height();
441 void operator= (cv::Rect& rectangle) {
442 this->get(rectangle);
455 void operator<< (VOTRegion &source, const cv::Rect& rectangle) {
456 source.set(rectangle);
459 void operator>> (const VOTRegion &source, cv::Rect& rectangle) {
460 source.get(rectangle);
463 void operator<< (cv::Rect& rectangle, const VOTRegion &source) {
464 source.get(rectangle);
467 void operator>> (const cv::Rect& rectangle, VOTRegion &source) {
468 source.set(rectangle);
477 _region = vot_initialize();
484 const VOTRegion region() {
485 return VOTRegion(_region);
488 void report(const VOTRegion& region) {
490 vot_report(region._region);
494 const string frame() {
496 const char* result = vot_frame();
501 return string(result);
505 return vot_end() != 0;
511 vot_region* vot_initialize();
515 const char* vot_frame();
517 void vot_report(vot_region* region);
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;
532 vot_region** _vot_result;
536 trax_handle* _trax_handle;
537 char _trax_image_buffer[VOT_READ_BUFFER];
541 vot_region* _trax_to_region(const trax_region* _trax_region) {
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]));
549 trax_region* _region_to_trax(const vot_region* region) {
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]);
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));
565 trax_region* _region_to_trax(const vot_region* region) {
566 return trax_region_create_rectangle(region->x, region->y, region->width, region->height);
579 # define VOT_PREFIX(FUN) VOT::FUN
581 # define VOT_PREFIX(FUN) FUN
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.
590 vot_region* VOT_PREFIX(vot_initialize)() {
596 _vot_sequence_position = 0;
597 _vot_sequence_size = 0;
600 if (getenv("TRAX")) {
601 trax_configuration config;
602 trax_image* _trax_image = NULL;
603 trax_region* _trax_region = NULL;
608 config.format_region = TRAX_REGION_POLYGON;
610 config.format_region = TRAX_REGION_RECTANGLE;
612 config.format_image = TRAX_IMAGE_PATH;
613 _trax_handle = trax_server_setup(config, NULL);
615 response = trax_server_wait(_trax_handle, &_trax_image, &_trax_region, NULL);
617 assert(response == TRAX_INITIALIZE);
619 strcpy(_trax_image_buffer, trax_image_get_path(_trax_image));
621 trax_server_reply(_trax_handle, _trax_region, NULL);
623 vot_region* region = _trax_to_region(_trax_region);
625 trax_region_release(&_trax_region);
626 trax_image_release(&_trax_image);
632 inputfile = fopen("region.txt", "r");
633 imagesfile = fopen("images.txt", "r");
636 fprintf(stderr, "Initial region file (region.txt) not available. Stopping.\n");
641 fprintf(stderr, "Image list file (images.txt) not available. Stopping.\n");
646 size_t linesiz = sizeof(char) * VOT_READ_BUFFER;
647 char* linebuf = (char*) malloc(sizeof(char) * VOT_READ_BUFFER);
649 _getline(&linebuf, &linesiz, inputfile);
650 vot_region* region = _parse_region(linebuf);
655 _vot_sequence = (char**) malloc(sizeof(char*) * j);
659 if ((linelen = _getline(&linebuf, &linesiz, imagesfile))<1)
662 if ((linebuf)[linelen - 1] == '\n') {
663 (linebuf)[linelen - 1] = '\0';
666 if (_vot_sequence_size == j) {
668 _vot_sequence = (char**) realloc(_vot_sequence, sizeof(char*) * j);
671 _vot_sequence[_vot_sequence_size] = (char *) malloc(sizeof(char) * (strlen(linebuf) + 1));
673 strcpy(_vot_sequence[_vot_sequence_size], linebuf);
675 _vot_sequence_size++;
680 _vot_result = (vot_region**) malloc(sizeof(vot_region*) * _vot_sequence_size);
686 * Stores results to the result file and frees memory. This function should be
687 * called at the end of the tracking program.
689 void VOT_PREFIX(vot_quit)() {
695 trax_cleanup(&_trax_handle);
700 FILE *outputfile = fopen("output.txt", "w");
702 for (i = 0; i < _vot_sequence_position; i++) {
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");
712 fprintf(outputfile, "%f,%f,%f,%f\n", _vot_result[i]->x, _vot_result[i]->y, _vot_result[i]->width, _vot_result[i]->height);
714 vot_region_release(&(_vot_result[i]));
720 for (i = 0; i < _vot_sequence_size; i++)
721 free(_vot_sequence[i]);
732 * Returns the file name of the current frame. This function does not advance
733 * the current position.
735 const char* VOT_PREFIX(vot_frame)() {
740 trax_image* _trax_image = NULL;
741 trax_region* _trax_region = NULL;
743 if (_vot_sequence_position == 0) {
744 _vot_sequence_position++;
745 return _trax_image_buffer;
748 response = trax_server_wait(_trax_handle, &_trax_image, &_trax_region, NULL);
750 if (response != TRAX_FRAME) {
755 strcpy(_trax_image_buffer, trax_image_get_path(_trax_image));
756 trax_image_release(&_trax_image);
758 return _trax_image_buffer;
763 if (_vot_sequence_position >= _vot_sequence_size)
766 return _vot_sequence[_vot_sequence_position];
771 * Used to report position of the object. This function also advances the
774 void VOT_PREFIX(vot_report)(vot_region* region) {
778 trax_region* _trax_region = _region_to_trax(region);
779 trax_server_reply(_trax_handle, _trax_region, NULL);
780 trax_region_release(&_trax_region);
785 if (_vot_sequence_position >= _vot_sequence_size)
788 _vot_result[_vot_sequence_position] = vot_region_copy(region);
789 _vot_sequence_position++;
792 int VOT_PREFIX(vot_end)() {
798 if (_vot_sequence_position >= _vot_sequence_size)