1 |
|
2 | #include <iostream>
|
3 | #include "cv.h"
|
4 | #include "highgui.h"
|
5 |
|
6 | using namespace std;
|
7 | using namespace cv;
|
8 |
|
9 |
|
10 | int hbins = 16;
|
11 | int sbins = 32;
|
12 |
|
13 | int histSize[] = {hbins};
|
14 | float hranges[] = { 0, 180 };
|
15 | float sranges[] = { 0, 256 };
|
16 |
|
17 | const float* ranges[] = { hranges };
|
18 | int channels[] = {0};
|
19 |
|
20 | int backproject_mode = 0;
|
21 | int select_object = 0;
|
22 | int track_object = 0;
|
23 | int show_hist = 1;
|
24 |
|
25 | Point origin2;
|
26 | Rect selection2;
|
27 | Rect track_window2;
|
28 | RotatedRect track_box2;
|
29 | int vmin = 10, vmax = 256, smin = 30;
|
30 | Mat image2, hsv2, hue2, mask2, backproject2;
|
31 | MatND hist2;
|
32 | Mat histimg2 = Mat::zeros(200, 320, CV_8UC3);
|
33 |
|
34 |
|
35 | void on_mouse( int event, int x, int y, int flags, void* param )
|
36 | {
|
37 | if( image2.empty() )
|
38 | return;
|
39 |
|
40 | if( select_object )
|
41 | {
|
42 | selection2.x = MIN(x,origin2.x);
|
43 | selection2.y = MIN(y,origin2.y);
|
44 | selection2.width = selection2.x + CV_IABS(x - origin2.x);
|
45 | selection2.height = selection2.y + CV_IABS(y - origin2.y);
|
46 |
|
47 | selection2.x = MAX( selection2.x, 0 );
|
48 | selection2.y = MAX( selection2.y, 0 );
|
49 | selection2.width = MIN( selection2.width, image2.cols );
|
50 | selection2.height = MIN( selection2.height, image2.rows );
|
51 | selection2.width -= selection2.x;
|
52 | selection2.height -= selection2.y;
|
53 | }
|
54 |
|
55 | switch( event )
|
56 | {
|
57 | case CV_EVENT_LBUTTONDOWN:
|
58 | origin2 = cvPoint(x,y);
|
59 | selection2 = cvRect(x,y,0,0);
|
60 | select_object = 1;
|
61 | break;
|
62 | case CV_EVENT_LBUTTONUP:
|
63 | select_object = 0;
|
64 | if( selection2.width > 0 && selection2.height > 0 )
|
65 | track_object = -1;
|
66 | break;
|
67 | }
|
68 | }
|
69 |
|
70 |
|
71 | Scalar hsv2rgb( float hue2 )
|
72 | {
|
73 | int rgb[3], p, sector;
|
74 | static const int sector_data[][3]=
|
75 | {{0,2,1}, {1,2,0}, {1,0,2}, {2,0,1}, {2,1,0}, {0,1,2}};
|
76 | hue2 *= 0.033333333333333333333333333333333f;
|
77 | sector = cvFloor(hue2);
|
78 | p = cvRound(255*(hue2 - sector));
|
79 | p ^= sector & 1 ? 255 : 0;
|
80 |
|
81 | rgb[sector_data[sector][0]] = 255;
|
82 | rgb[sector_data[sector][1]] = 0;
|
83 | rgb[sector_data[sector][2]] = p;
|
84 |
|
85 | return Scalar(rgb[2], rgb[1], rgb[0],0);
|
86 | }
|
87 |
|
88 |
|
89 | int main( int argc, char** argv )
|
90 | {
|
91 | VideoCapture capture;
|
92 | capture.set(CV_CAP_PROP_FRAME_WIDTH,320);
|
93 | capture.set(CV_CAP_PROP_FRAME_HEIGHT,240);
|
94 | bool isOpened = false;
|
95 |
|
96 | if( argc == 1 || (argc == 2 && strlen(argv[1]) == 1 && isdigit(argv[1][0])))
|
97 | isOpened = capture.open( argc == 2 ? argv[1][0] - '0' : 0 );
|
98 | else if( argc == 2 )
|
99 | isOpened = capture.open( argv[1] );
|
100 |
|
101 | if( !capture.isOpened() )
|
102 | {
|
103 | cerr << "Could not initialize capturing..." << endl;
|
104 | return -1;
|
105 | }
|
106 |
|
107 | cout << "Hot keys: " << endl
|
108 | << "\tESC - quit the program" << endl
|
109 | << "\tc - stop the tracking" << endl
|
110 | << "\tb - switch to/from backprojection view" << endl
|
111 | << "\th - show/hide object histogram" << endl
|
112 | << "To initialize tracking, select the object with mouse" << endl;
|
113 |
|
114 | namedWindow( "CamShiftDemo", 1 );
|
115 | cvSetMouseCallback( "CamShiftDemo", on_mouse, 0 );
|
116 | createTrackbar( "Vmin", "CamShiftDemo", &vmin, 256, 0 );
|
117 | createTrackbar( "Vmax", "CamShiftDemo", &vmax, 256, 0 );
|
118 | createTrackbar( "Smin", "CamShiftDemo", &smin, 256, 0 );
|
119 | namedWindow( "Histogram", 1 );
|
120 |
|
121 | for(;;)
|
122 | {
|
123 | Mat frame;
|
124 | int i, bin_w, c;
|
125 |
|
126 | capture >> frame;
|
127 | if (frame.empty()) break;
|
128 |
|
129 |
|
130 | frame.copyTo( image2 );
|
131 | cvtColor( image2, hsv2, CV_BGR2HSV );
|
132 |
|
133 | if( track_object )
|
134 | {
|
135 | int _vmin = vmin, _vmax = vmax;
|
136 |
|
137 | inRange( hsv2, Scalar(0,smin,MIN(_vmin,_vmax),0),
|
138 | Scalar(180,256,MAX(_vmin,_vmax),0), mask2 );
|
139 | vector<Mat> vhsv;
|
140 | vhsv.resize(3);
|
141 | split( hsv2, vhsv );
|
142 | vhsv[0].copyTo(hue2);
|
143 |
|
144 |
|
145 | if( track_object < 0 )
|
146 | {
|
147 | double max_val2 = 0.f;
|
148 | Mat roi = hue2(Range(selection2.y, selection2.y+selection2.height),
|
149 | Range(selection2.x, selection2.x+selection2.width) );
|
150 | Mat roi_mask = mask2(Range(selection2.y, selection2.y+selection2.height),
|
151 | Range(selection2.x, selection2.x+selection2.width) );
|
152 | calcHist( &roi, 1, channels, roi_mask,
|
153 | hist2, 1, histSize, ranges,
|
154 | true,
|
155 | false );
|
156 | minMaxLoc(hist2, 0, &max_val2, 0, 0);
|
157 | hist2.convertTo(hist2, hist2.type(), (max_val2 ? 255. / max_val2 : 0.), 0);
|
158 | track_window2 = selection2;
|
159 | track_object = 1;
|
160 |
|
161 | histimg2 = Mat::zeros(histimg2.size(), histimg2.type());
|
162 | bin_w = histimg2.cols / hbins;
|
163 | for( i = 0; i < hbins; i++ )
|
164 | {
|
165 | int val2 = cvRound( hist2.at<float>(i)*(float)histimg2.rows/255.0 );
|
166 | Scalar color = hsv2rgb(i*180.f/hbins);
|
167 | rectangle(histimg2, Point(i*bin_w,histimg2.rows),
|
168 | Point((i+1)*bin_w,histimg2.rows - val2),
|
169 | color, -1, 8, 0);
|
170 | }
|
171 | }
|
172 |
|
173 |
|
174 | calcBackProject( &hue2, 1, channels, hist2, backproject2, ranges);
|
175 | bitwise_and( backproject2, mask2, backproject2 );
|
176 | track_box2 = CamShift( backproject2, track_window2, TermCriteria(TermCriteria::COUNT+TermCriteria::EPS, 10, 1) );
|
177 |
|
178 | if( backproject_mode )
|
179 | cvtColor( backproject2, image2, CV_GRAY2BGR );
|
180 | ellipse(image2, track_box2, CV_RGB(255,0,0), 3, CV_AA);
|
181 |
|
182 | }
|
183 |
|
184 |
|
185 | if( select_object && selection2.width > 0 && selection2.height > 0 )
|
186 | {
|
187 | Mat roi(image2, selection2);
|
188 | bitwise_xor( roi, cvScalarAll(255), roi );
|
189 | }
|
190 |
|
191 | imshow( "CamShiftDemo", image2 );
|
192 | imshow( "Histogram", histimg2 );
|
193 | waitKey(10);
|
194 |
|
195 | if( (char) c == 27 )
|
196 | break;
|
197 | switch( (char) c )
|
198 | {
|
199 | case 'b':
|
200 | backproject_mode ^= 1;
|
201 | break;
|
202 | case 'c':
|
203 | track_object = 0;
|
204 | histimg2 = Mat::zeros(histimg2.size(), histimg2.type());
|
205 | break;
|
206 | case 'h':
|
207 | show_hist ^= 1;
|
208 | if( !show_hist )
|
209 | cvDestroyWindow( "Histogram2" );
|
210 | else
|
211 | namedWindow( "Histogram2", 1 );
|
212 | break;
|
213 | default:
|
214 | ;
|
215 | }
|
216 | }
|
217 |
|
218 | return 0;
|
219 | }
|
220 |
|