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.

185 lines
5.9 KiB

/* -*- Mode: C++; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 4 -*- */
/*
* This example is based on the camshiftdemo code from the OpenCV repository
* The main function of this example is to show the developers how to integrate trax
* support into their own programs.
*/
//#include <opencv2/tracking.hpp>
#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/video/tracking.hpp>
#include <iostream>
#include <trax.h>
#include <trax/opencv.hpp>
using namespace std;
using namespace cv;
Rect trackWindow;
int hsize = 16;
float hranges[] = {0,180};
const float* phranges = hranges;
CvRect box2rect(CvBox2D box) {
CvPoint pt0, pt1, pt2, pt3;
CvRect result;
double _angle = box.angle*CV_PI/180.0;
float a = (float)cos(_angle)*0.5f;
float b = (float)sin(_angle)*0.5f;
pt0.x = box.center.x - a*box.size.height - b*box.size.width;
pt0.y = box.center.y + b*box.size.height - a*box.size.width;
pt1.x = box.center.x + a*box.size.height - b*box.size.width;
pt1.y = box.center.y - b*box.size.height - a*box.size.width;
pt2.x = 2 * box.center.x - pt0.x;
pt2.y = 2 * box.center.y - pt0.y;
pt3.x = 2 * box.center.x - pt1.x;
pt3.y = 2 * box.center.y - pt1.y;
result.x = cvFloor(MIN(MIN(MIN(pt0.x, pt1.x), pt2.x), pt3.x));
result.y = cvFloor(MIN(MIN(MIN(pt0.y, pt1.y), pt2.y), pt3.y));
result.width = cvCeil(MAX(MAX(MAX(pt0.x, pt1.x), pt2.x), pt3.x)) - result.x - 1;
result.height = cvCeil(MAX(MAX(MAX(pt0.y, pt1.y), pt2.y), pt3.y)) - result.y - 1;
return result;
}
int track_object = 0;
Point origin;
Rect selection;
int vmin = 10, vmax = 256, smin = 30;
int main( int argc, char** argv )
{
trax::Configuration config(TRAX_IMAGE_MEMORY | TRAX_IMAGE_BUFFER | TRAX_IMAGE_PATH, TRAX_REGION_RECTANGLE);
// Call trax_server_setup to initialize trax protocol
trax::Server handle(config, trax_no_log);
trax::ImageList img;
trax::Region rect;
Mat frame, hsv, hue, mask, hist, backproj;
for(;;)
{
trax::Properties prop;
// The main idea of Trax interface is to leave the control to the master program
// and just follow the instructions that the tracker gets.
// The main function for this is trax_wait that actually listens for commands.
int tr = handle.wait(img, rect, prop);
// There are two important commands. The first one is TRAX_INITIALIZE that tells the
// tracker how to initialize.
if (tr == TRAX_INITIALIZE) {
float x, y, width, height;
rect.get(&(x), &(y), &(width), &(height));
// The bounding box of the object is given during initialization
selection.x = x;
selection.y = y;
selection.width = width;
selection.height = height;
// With every parameter master program can also give one or more key-value
// parameters. This is useful for seting some tracking parameters externally.
vmin = prop.get("vmin", vmin);
vmax = prop.get("vmax", vmax);
smin = prop.get("smin", smin);
track_object = -1;
handle.reply(rect, trax::Properties());
} else
// The second one is TRAX_FRAME that tells the tracker what to process next.
if (tr == TRAX_FRAME) {
if (track_object < 1) {
// Tracker was not initialized successfully
break;
}
}
// Any other command is either TRAX_QUIT or illegal, so we exit.
else {
break;
}
// In trax mode images are read from the disk. The master program tells the
// tracker where to get them.
Mat frame = trax::image_to_mat(img.get(TRAX_CHANNEL_COLOR));
if( frame.empty() )
break;
cvtColor(frame, hsv, COLOR_BGR2HSV);
if( track_object )
{
int _vmin = vmin, _vmax = vmax;
inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)),
Scalar(180, 256, MAX(_vmin, _vmax)), mask);
int ch[] = {0, 0};
hue.create(hsv.size(), hsv.depth());
mixChannels(&hsv, 1, &hue, 1, ch, 1);
if( track_object < 0 )
{
Mat roi(hue, selection), maskroi(mask, selection);
calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);
normalize(hist, hist, 0, 255, NORM_MINMAX);
trackWindow = selection;
track_object = 1;
Mat buf(1, hsize, CV_8UC3);
for( int i = 0; i < hsize; i++ )
buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize), 255, 255);
cvtColor(buf, buf, COLOR_HSV2BGR);
}
calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
backproj &= mask;
RotatedRect trackBox = CamShift(backproj, trackWindow,
TermCriteria( TermCriteria::EPS | TermCriteria::COUNT, 10, 1 ));
if( trackWindow.area() <= 1 )
{
int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
trackWindow.x + r, trackWindow.y + r) &
Rect(0, 0, cols, rows);
}
}
// At the end of single frame processing we send back the estimated
// bounding box and wait for further instructions.
trax::Region region = trax::Region::create_rectangle(trackWindow.x, trackWindow.y, trackWindow.width, trackWindow.height);
// Note that the tracker also has an option of sending additional data
// back to the main program in a form of key-value pairs. We do not use
// this option here, so this part is empty.
handle.reply(region, trax::Properties());
}
return 0;
}