You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

649 lines
16 KiB

/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
/*
* This header file contains C functions that can be used to quickly integrate
* VOT challenge support into your C or C++ tracker.
*
* Copyright (c) 2017, VOT Committee
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* The views and conclusions contained in the software and documentation are those
* of the authors and should not be interpreted as representing official policies,
* either expressed or implied, of the FreeBSD Project.
*/
#ifndef _VOT_TOOLKIT_H
#define _VOT_TOOLKIT_H
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <trax.h>
#define VOT_READ_BUFFER 2024
#define _CRT_SECURE_NO_WARNINGS
// Define VOT_OPENCV after including OpenCV core header to enable better OpenCV support
#if defined(__OPENCV_CORE_HPP__) || defined(OPENCV_CORE_HPP)
# define VOT_OPENCV
#endif
#ifndef VOT_RECTANGLE
#define VOT_POLYGON
#endif
typedef struct vot_image {
#ifdef VOT_RGBD
char color[VOT_READ_BUFFER];
char depth[VOT_READ_BUFFER];
#elif defined(VOT_IR)
char ir[VOT_READ_BUFFER];
#elif defined(VOT_RGBT)
char color[VOT_READ_BUFFER];
char ir[VOT_READ_BUFFER];
#else
char color[VOT_READ_BUFFER];
#endif
} vot_image;
#ifdef VOT_POLYGON
typedef struct vot_region {
float* x;
float* y;
int count;
} vot_region;
void vot_region_release(vot_region** region) {
if (!(*region)) return;
if ((*region)->x) {
free((*region)->x);
(*region)->x = NULL;
}
if ((*region)->y) {
free((*region)->y);
(*region)->y = NULL;
}
free(*region);
*region = NULL;
}
vot_region* vot_region_create(int n) {
vot_region* region = (vot_region*) malloc(sizeof(vot_region));
region->x = (float *) malloc(sizeof(float) * n);
region->y = (float *) malloc(sizeof(float) * n);
memset(region->x, 0, sizeof(float) * n);
memset(region->y, 0, sizeof(float) * n);
region->count = n;
return region;
}
vot_region* vot_region_copy(const vot_region* region) {
vot_region* copy = vot_region_create(region->count);
int i;
for (i = 0; i < region->count; i++) {
copy->x[i] = region->x[i];
copy->y[i] = region->y[i];
}
return copy;
}
#else
typedef struct vot_region {
float x;
float y;
float width;
float height;
} vot_region;
void vot_region_release(vot_region** region) {
if (!(*region)) return;
free(*region);
*region = NULL;
}
vot_region* vot_region_create() {
vot_region* region = (vot_region*) malloc(sizeof(vot_region));
region->x = 0;
region->y = 0;
region->width = 0;
region->height = 0;
return region;
}
vot_region* vot_region_copy(const vot_region* region) {
vot_region* copy = vot_region_create();
copy->x = region->x;
copy->y = region->y;
copy->width = region->width;
copy->height = region->height;
return copy;
}
#endif
#ifdef __cplusplus
#include <string>
#include <fstream>
#include <iostream>
using namespace std;
class VOT;
typedef struct VOTImage {
#ifdef VOT_RGBD
string color;
string depth;
#elif defined(VOT_IR)
string ir;
#elif defined(VOT_RGBT)
string color;
string ir;
#else
string color;
#endif
} VOTImage;
class VOTRegion {
friend class VOT;
public:
~VOTRegion() {
vot_region_release(&_region);
}
VOTRegion(const vot_region* region) {
_region = vot_region_copy(region);
}
#ifdef VOT_POLYGON
VOTRegion(int count) {
_region = vot_region_create(count);
}
void set(int i, float x, float y) { assert(i >= 0 && i < _region->count); _region->x[i] = x; _region->y[i] = y; }
float get_x(int i) const { assert(i >= 0 && i < _region->count); return _region->x[i]; }
float get_y(int i) const { assert(i >= 0 && i < _region->count); return _region->y[i]; }
int count() const { return _region->count; }
#else
VOTRegion() {
_region = vot_region_create();
}
float get_x() const { return _region->x; }
float get_y() const { return _region->y; }
float get_width() const { return _region->width; }
float get_height() const { return _region->height; }
float set_x(float x) { return _region->x = x; }
float set_y(float y) { return _region->y = y; }
float set_width(float width) { return _region->width = width; }
float set_height(float height) { return _region->height = height; }
#endif
VOTRegion& operator= (const VOTRegion &source) {
if (this == &source)
return *this;
#ifdef VOT_POLYGON
if (this->_region->count != source.count()) {
vot_region_release(&(this->_region));
this->_region = vot_region_create(source.count());
}
for (int i = 0; i < source.count(); i++) {
set(i, source.get_x(i), source.get_y(i));
}
#else
set_x(source.get_x());
set_y(source.get_y());
set_width(source.get_width());
set_height(source.get_height());
#endif
return *this;
}
#ifdef VOT_OPENCV
VOTRegion(const cv::Rect& rectangle) {
#ifdef VOT_POLYGON
_region = vot_region_create(4);
#else
_region = vot_region_create();
#endif
set(rectangle);
}
void set(const cv::Rect& rectangle) {
#ifdef VOT_POLYGON
if (_region->count != 4) {
vot_region_release(&(this->_region));
_region = vot_region_create(4);
}
set(0, rectangle.x, rectangle.y);
set(1, rectangle.x + rectangle.width, rectangle.y);
set(2, rectangle.x + rectangle.width, rectangle.y + rectangle.height);
set(3, rectangle.x, rectangle.y + rectangle.height);
#else
set_x(rectangle.x);
set_y(rectangle.y);
set_width(rectangle.width);
set_height(rectangle.height);
#endif
}
void get(cv::Rect& rectangle) const {
#ifdef VOT_POLYGON
float top = FLT_MAX;
float bottom = FLT_MIN;
float left = FLT_MAX;
float right = FLT_MIN;
for (int j = 0; j < _region->count; j++) {
top = MIN(top, _region->y[j]);
bottom = MAX(bottom, _region->y[j]);
left = MIN(left, _region->x[j]);
right = MAX(right, _region->x[j]);
}
rectangle.x = left;
rectangle.y = top;
rectangle.width = right - left;
rectangle.height = bottom - top;
#else
rectangle.x = get_x();
rectangle.y = get_y();
rectangle.width = get_width();
rectangle.height = get_height();
#endif
}
void operator= (cv::Rect& rectangle) {
this->get(rectangle);
}
#endif
protected:
vot_region* _region;
};
#ifdef VOT_OPENCV
void operator<< (VOTRegion &source, const cv::Rect& rectangle) {
source.set(rectangle);
}
void operator>> (const VOTRegion &source, cv::Rect& rectangle) {
source.get(rectangle);
}
void operator<< (cv::Rect& rectangle, const VOTRegion &source) {
source.get(rectangle);
}
void operator>> (const cv::Rect& rectangle, VOTRegion &source) {
source.set(rectangle);
}
#endif
class VOT {
public:
VOT() {
_region = vot_initialize();
}
~VOT() {
vot_quit();
}
const VOTRegion region() {
return VOTRegion(_region);
}
void report(const VOTRegion& region, float confidence = 1) {
vot_report2(region._region, confidence);
}
#if defined(VOT_RGBD) || defined(VOT_RGBT)
const VOTImage frame() {
#else
const string frame() {
#endif
const vot_image* result = vot_frame();
#if defined(VOT_RGBD) || defined(VOT_RGBT)
VOTImage wrapper;
#else
string wrapper;
#endif
if (!result)
return wrapper;
#if defined(VOT_RGBD)
wrapper.color = string(_image.color);
wrapper.depth = string(_image.depth);
#elif defined(VOT_RGBT)
wrapper.color = string(_image.color);
wrapper.ir = string(_image.ir);
#elif defined(VOT_IR)
wrapper = string(_image.ir);
#else
wrapper = string(_image.color);
#endif
return wrapper;
}
bool end() {
return vot_end() != 0;
}
private:
vot_region* vot_initialize();
void vot_quit();
const vot_image* vot_frame();
void vot_report(vot_region* region);
void vot_report2(vot_region* region, float confidence);
int vot_end();
#endif
vot_region* _region;
// Current position in the sequence
int _vot_sequence_position;
// Size of the sequence
int _vot_sequence_size;
// List of image file names
char** _vot_sequence;
// List of results
vot_region** _vot_result;
trax_handle* _trax_handle;
vot_image _image;
#ifdef VOT_POLYGON
vot_region* _trax_to_region(const trax_region* _trax_region) {
int i;
int count = trax_region_get_polygon_count(_trax_region);
vot_region* region = vot_region_create(count);
for (i = 0; i < count; i++)
trax_region_get_polygon_point(_trax_region, i, &(region->x[i]), &(region->y[i]));
return region;
}
trax_region* _region_to_trax(const vot_region* region) {
int i;
trax_region* _trax_region = trax_region_create_polygon(region->count);
assert(trax_region_get_type(_trax_region) == TRAX_REGION_POLYGON);
for (i = 0; i < region->count; i++)
trax_region_set_polygon_point(_trax_region, i, region->x[i], region->y[i]);
return _trax_region;
}
#else
vot_region* _trax_to_region(const trax_region* _trax_region) {
vot_region* region = vot_region_create();
assert(trax_region_get_type(_trax_region) == TRAX_REGION_RECTANGLE);
trax_region_get_rectangle(_trax_region, &(region->x), &(region->y), &(region->width), &(region->height));
return region;
}
trax_region* _region_to_trax(const vot_region* region) {
return trax_region_create_rectangle(region->x, region->y, region->width, region->height);
}
#endif
#ifdef __cplusplus
};
#endif
#ifdef __cplusplus
# define VOT_PREFIX(FUN) VOT::FUN
#else
# define VOT_PREFIX(FUN) FUN
#endif
/**
* Reads the input data and initializes all structures. Returns the initial
* position of the object as specified in the input data. This function should
* be called at the beginning of the program.
*/
vot_region* VOT_PREFIX(vot_initialize)() {
int j;
FILE *inputfile;
FILE *imagesfile;
_vot_sequence_position = 0;
_vot_sequence_size = 0;
trax_configuration config;
trax_image_list* _trax_image = NULL;
trax_region* _trax_region = NULL;
_trax_handle = NULL;
int response;
#ifdef VOT_POLYGON
int region_format = TRAX_REGION_POLYGON;
#else
int region_format = TRAX_REGION_RECTANGLE;
#endif
#ifdef VOT_RGBD
int channels = TRAX_CHANNEL_COLOR | TRAX_CHANNEL_DEPTH;
#elif defined(VOT_IR)
int channels = TRAX_CHANNEL_IR;
#elif defined(VOT_RGBT)
int channels = TRAX_CHANNEL_COLOR | TRAX_CHANNEL_IR;
#else
int channels = TRAX_CHANNEL_COLOR;
#endif
trax_metadata* metadata = trax_metadata_create(region_format, TRAX_IMAGE_PATH, channels, NULL, NULL, NULL);
_trax_handle = trax_server_setup(metadata, trax_no_log);
trax_metadata_release(&metadata);
response = trax_server_wait(_trax_handle, &_trax_image, &_trax_region, NULL);
assert(response == TRAX_INITIALIZE);
#if defined(VOT_RGBD)
strcpy(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
strcpy(_image.depth, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_DEPTH)));
#elif defined(VOT_RGBT)
strcpy(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
strcpy(_image.ir, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_IR)));
#elif defined(VOT_IR)
strcpy(_image.ir, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_IR)));
#else
//strcpy_s(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
strcpy(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
#endif
trax_server_reply(_trax_handle, _trax_region, NULL);
vot_region* region = _trax_to_region(_trax_region);
trax_region_release(&_trax_region);
trax_image_list_clear(_trax_image);
trax_image_list_release(&_trax_image);
return region;
}
/**
* Stores results to the result file and frees memory. This function should be
* called at the end of the tracking program.
*/
void VOT_PREFIX(vot_quit)() {
if (_trax_handle) {
trax_cleanup(&_trax_handle);
return;
}
}
/**
* Returns the file name of the current frame. This function does not advance
* the current position.
*/
const vot_image* VOT_PREFIX(vot_frame)() {
if (_trax_handle) {
int response;
trax_image_list* _trax_image = NULL;
trax_region* _trax_region = NULL;
if (_vot_sequence_position == 0) {
_vot_sequence_position++;
return &_image;
}
response = trax_server_wait(_trax_handle, &_trax_image, &_trax_region, NULL);
if (response != TRAX_FRAME) {
vot_quit();
return NULL;
}
#if defined(VOT_RGBD)
strcpy(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
strcpy(_image.depth, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_DEPTH)));
#elif defined(VOT_RGBT)
strcpy(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
strcpy(_image.ir, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_IR)));
#elif defined(VOT_IR)
strcpy(_image.ir, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_IR)));
#else
//strcpy_s(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
strcpy(_image.color, trax_image_get_path(trax_image_list_get(_trax_image, TRAX_CHANNEL_COLOR)));
#endif
trax_image_list_clear(_trax_image);
trax_image_list_release(&_trax_image);
return &_image;
}
}
/**
* Used to report position of the object. This function also advances the
* current position.
*/
void VOT_PREFIX(vot_report)(vot_region* region) {
if (_trax_handle) {
trax_region* _trax_region = _region_to_trax(region);
trax_server_reply(_trax_handle, _trax_region, NULL);
trax_region_release(&_trax_region);
return;
}
}
/**
* Used to report position of the object. This function also advances the
* current position.
*/
void VOT_PREFIX(vot_report2)(vot_region* region, float confidence) {
if (_trax_handle) {
trax_region* _trax_region = _region_to_trax(region);
trax_properties* _trax_properties = trax_properties_create();
trax_properties_set_float(_trax_properties, "confidence", confidence);
trax_server_reply(_trax_handle, _trax_region, _trax_properties);
trax_region_release(&_trax_region);
trax_properties_release(&_trax_properties);
return;
}
}
int VOT_PREFIX(vot_end)() {
return 0;
}
#endif