Statement: This article is not the author's original, original Reprinted from: http://blog.csdn.net/koriya/article/details/3347365
Implementation of the meanshift Tracking Algorithm Based on opencv
# Include "cv. H"
# Include "highgui. H"
# Include <stdio. h>
# Include <ctype. h>
Iplimage * image = 0, * HSV = 0, * hue = 0, * mask = 0, * backproject = 0, * histimg = 0; // use the hue component in HSV for tracking
Cvhistogram * hist = 0; // histogram class
Int backproject_mode = 0;
Int select_object = 0;
Int track_object = 0;
Int show_hist = 1;
Cvpoint origin;
Cvrect selection;
Cvrect track_window;
Cvbox2d track_box; // box class returned by the meanshift Tracking Algorithm
Cvconnectedcomp track_comp;
Int hdims = 50; // Number of bins in the histogram. the more accurate the number
Float hranges_arr [] = {0,180}; // pixel value range
Float * hranges = hranges_arr; // used to initialize the cvhistogram class
Int Vmin = 10, Vmax = 256, Smin = 30;
Void on_mouse (INT event, int X, int y, int flags, void * notused) // This function is used to select a trail target.
{
If (! Image)
Return;
If (image-> origin)
Y = image-> height-y;
If (select_object) // if you are in the select tracking object stage, set selection with the current mouse position
{
Selection. x = min (x, origin. X );
Selection. Y = min (Y, origin. y );
Selection. width = selection. x + cv_iabs (X-origin. X );
Selection. Height = selection. Y + cv_iabs (Y-origin. y );
Selection. x = max (selection. X, 0 );
Selection. Y = max (selection. Y, 0 );
Selection. width = min (selection. Width, image-> width );
Selection. Height = min (selection. Height, image-> height );
Selection. Width-= selection. X;
Selection. Height-= selection. Y;
}
Switch (Event)
{
Case cv_event_lbuttondown: // start to click to select a tracking object
Origin = cvpoint (x, y );
Selection = cvrect (X, Y, 0, 0); // Coordinate
Select_object = 1; // indicates that the selection starts.
Break;
Case cv_event_lbuttonup:
Select_object = 0; // The selection is complete.
If (selection. width> 0 & selection. Height> 0)
Track_object =-1; // If the selected object is valid, the tracking function is enabled.
Break;
}
}
Cvscalar HSV 2rgb (float Hue) // used to convert hue to RGB
{
Int RGB [3], p, sector;
Static const int sector_data [] [3] = {, 1}, {, 0}, {, 2}, {, 1, 0 },{ 0, 1, 2 }};
Hue * = 0.033333333333333333333333333333333f;
Sector = cvfloor (Hue );
P = cvround (255 * (hue-sector ));
P ^ = Sector & 1? 255: 0;
RGB [sector_data [Sector] [0] = 255;
RGB [sector_data [Sector] [1] = 0;
RGB [sector_data [Sector] [2] = P;
Return cvscalar (RGB [2], RGB [1], RGB [0], 0); // return the corresponding color value
}
Int main (INT argc, char ** argv)
{
Cvcapture * capture = 0;
Iplimage * frame = 0;
If (argc = 1 | (argc = 2 & strlen (argv [1]) = 1 & isdigit (argv [1] [0])
Capture = cvcapturefromcam (argc = 2? Argv [1] [0]-'0': 0); // open the camera
Else if (argc = 2)
Capture = cvcapturefromavi (argv [1]); // open the AVI file
If (! Capture)
{
Fprintf (stderr, "cocould not initialize capturing.../N"); // failed to process video stream opening
Return-1;
}
Printf ("hot keys: /n/tesc-quit the program/n/TC-stop the tracking/n/TB-switch to/from Backprojection view/n/Th-show/hide object histogram/nto initialize tracking, select the object with mouse/N "); // print out the program function list
Cvnamedwindow ("camshiftdemo", 1); // creates a video window.
Cvsetmousecallback ("camshiftdemo", on_mouse); // sets the mouse callback function.
Cvcreatetrackbar ("Vmin", "camshiftdemo", & Vmin, 256, 0); // create a slider
Cvcreatetrackbar ("Vmax", "camshiftdemo", & vmax, 256, 0 );
Cvcreatetrackbar ("Smin", "camshiftdemo", & Smin, 256, 0 );
For (;) // enters the main loop of video frame Processing
{
Int I, bin_w, C;
Frame = cvqueryframe (capture );
If (! Frame)
Break;
If (! Image) // create some buffer at the beginning
{
Image = cvcreateimage (cvgetsize (FRAME), 8, 3 );//
Image-> origin = frame-> origin;
HSV = cvcreateimage (cvgetsize (FRAME), 8, 3 );
Hue = cvcreateimage (cvgetsize (FRAME), 8, 1 );
Mask = cvcreateimage (cvgetsize (FRAME), 8, 1); // allocate mask image space
Backproject = cvcreateimage (cvgetsize (FRAME), 8, 1); // allocate reverse projection image space, same size, single channel
Hist = cvcreatehist (1, & hdims, cv_hist_array, & hranges, 1); // allocate and create a histogram Space
Histimg = cvcreateimage (cvsize (320,200), 8, 3); // allocate the space used to draw the Histogram
Cvzero (histimg); // The background is black.
}
Cvcopy (frame, image, 0 );
Cvcvtcolor (image, HSV, cv_bgr2hsv); // convert the image from RGB to HSV
If (track_object) // if the current object needs to be tracked
{
Int _ Vmin = Vmin, _ Vmax = vmax;
Cvinranges (HSV, cvscalar (0, Smin, min (_ Vmin, _ Vmax), 0), cvscalar (180,256, max (_ Vmin, _ Vmax), 0 ), mask); // create a mask. The pixel value is H: 0 ~ 180, S: Smin ~ 256, V: Vmin ~ Between Vmax
Cvsplit (HSV, hue, 0, 0, 0); // obtain the H component
If (track_object <0) // if the object to be tracked has not been extracted from attributes, extract the image attributes of the Selection box
{
Float max_val = 0.f;
Cvsetimageroi (hue, selection); // you can specify the original selection box.
Cvsetimageroi (mask, selection); // sets the selection box of the mask.
Cvcalchist (& hue, Hist, 0, mask); // obtain the histogram in the selection box that meets the requirements of the mask.
Cvgetminmaxhistvalue (Hist, 0, & max_val, 0, 0 );
Cvconvertscale (hist-> bins, hist-> bins, max_val? 255./max_val: 0., 0); // convert the histogram to 0 ~ 255
Cvresetimageroi (Hue); // remove ROI
Cvresetimageroi (mask );
Track_window = selection;
Track_object = 1;
Cvzero (histimg );
Bin_w = histimg-> width/hdims;
For (I = 0; I {
Int val = cvround (
Cvgetreal1d (hist-> bins, I) * histimg-> height/255 );
Cvscalar color = HSV 2rgb (I * 180.f/ hdims );
Cvrectangle (histimg, cvpoint (I * bin_w, histimg-> height ),
Cvpoint (I + 1) * bin_w, histimg-> height-Val), color,-1, 8, 0); // draw a histogram to the image space
}
}
Cvcalcbackproject (& hue, backproject, hist); // obtain the reverse projection of hue.
Cvand (backproject, mask, backproject, 0); obtain the content in the reverse Projection Image Mask.
Cvcamshift (backproject, track_window, cvtermcriteria
Track_window = track_comp.rect; // rectangular box for the tracking result
If (backproject_mode)
Cvcvtcolor (backproject, image, cv_gray2bgr); // Display Mode
If (image-> origin)
Track_box.angle =-track_box.angle;
Cvellipsebox (image, track_box, cv_rgb (255, 0), 3, cv_aa, 0); // draw the position of the tracking result
}
If (select_object & selection. width> 0 & selection. Height> 0) // if you are selecting an object, draw a selection box
{
Cvsetimageroi (image, selection );
Cvxors (image, cvscalarall (255), image, 0 );
Cvresetimageroi (image );
}
Cvshowimage ("camshiftdemo", image); // display the video and Histogram
Cvshowimage ("histogram", histimg );
C = cvwaitkey (10 );
If (C = 27)
Break;
Switch (c)
{
Case 'B ':
Backproject_mode ^ = 1;
Break;
Case 'C ':
Track_object = 0;
Cvzero (histimg );
Break;
Case 'H ':
Show_hist ^ = 1;
If (! Show_hist)
Cvdestroywindow ("histogram ");
Else
Cvnamedwindow ("histogram", 1 );
Break;
Default:
;
}
}
Cvreleasecapture (& capture );
Cvdestroywindow ("camshiftdemo ");
Return 0;
}