camshiftdemo.cpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  1. #include "opencv2/core/utility.hpp"
  2. #include "opencv2/video/tracking.hpp"
  3. #include "opencv2/imgproc.hpp"
  4. #include "opencv2/videoio.hpp"
  5. #include "opencv2/highgui.hpp"
  6. #include <iostream>
  7. #include <ctype.h>
  8. using namespace cv;
  9. using namespace std;
  10. Mat image;
  11. bool backprojMode = false;
  12. bool selectObject = false;
  13. int trackObject = 0;
  14. bool showHist = true;
  15. Point origin;
  16. Rect selection;
  17. int vmin = 10, vmax = 256, smin = 30;
  18. // User draws box around object to track. This triggers CAMShift to start tracking
  19. static void onMouse( int event, int x, int y, int, void* )
  20. {
  21. if( selectObject )
  22. {
  23. selection.x = MIN(x, origin.x);
  24. selection.y = MIN(y, origin.y);
  25. selection.width = std::abs(x - origin.x);
  26. selection.height = std::abs(y - origin.y);
  27. selection &= Rect(0, 0, image.cols, image.rows);
  28. }
  29. switch( event )
  30. {
  31. case EVENT_LBUTTONDOWN:
  32. origin = Point(x,y);
  33. selection = Rect(x,y,0,0);
  34. selectObject = true;
  35. break;
  36. case EVENT_LBUTTONUP:
  37. selectObject = false;
  38. if( selection.width > 0 && selection.height > 0 )
  39. trackObject = -1; // Set up CAMShift properties in main() loop
  40. break;
  41. }
  42. }
  43. string hot_keys =
  44. "\n\nHot keys: \n"
  45. "\tESC - quit the program\n"
  46. "\tc - stop the tracking\n"
  47. "\tb - switch to/from backprojection view\n"
  48. "\th - show/hide object histogram\n"
  49. "\tp - pause video\n"
  50. "To initialize tracking, select the object with mouse\n";
  51. static void help(const char** argv)
  52. {
  53. cout << "\nThis is a demo that shows mean-shift based tracking\n"
  54. "You select a color objects such as your face and it tracks it.\n"
  55. "This reads from video camera (0 by default, or the camera number the user enters\n"
  56. "Usage: \n\t";
  57. cout << argv[0] << " [camera number]\n";
  58. cout << hot_keys;
  59. }
  60. const char* keys =
  61. {
  62. "{help h | | show help message}{@camera_number| 0 | camera number}"
  63. };
  64. int main( int argc, const char** argv )
  65. {
  66. VideoCapture cap;
  67. Rect trackWindow;
  68. int hsize = 16;
  69. float hranges[] = {0,180};
  70. const float* phranges = hranges;
  71. CommandLineParser parser(argc, argv, keys);
  72. if (parser.has("help"))
  73. {
  74. help(argv);
  75. return 0;
  76. }
  77. int camNum = parser.get<int>(0);
  78. cap.open(camNum);
  79. if( !cap.isOpened() )
  80. {
  81. help(argv);
  82. cout << "***Could not initialize capturing...***\n";
  83. cout << "Current parameter's value: \n";
  84. parser.printMessage();
  85. return -1;
  86. }
  87. cout << hot_keys;
  88. namedWindow( "Histogram", 0 );
  89. namedWindow( "CamShift Demo", 0 );
  90. setMouseCallback( "CamShift Demo", onMouse, 0 );
  91. createTrackbar( "Vmin", "CamShift Demo", &vmin, 256, 0 );
  92. createTrackbar( "Vmax", "CamShift Demo", &vmax, 256, 0 );
  93. createTrackbar( "Smin", "CamShift Demo", &smin, 256, 0 );
  94. Mat frame, hsv, hue, mask, hist, histimg = Mat::zeros(200, 320, CV_8UC3), backproj;
  95. bool paused = false;
  96. for(;;)
  97. {
  98. if( !paused )
  99. {
  100. cap >> frame;
  101. if( frame.empty() )
  102. break;
  103. }
  104. frame.copyTo(image);
  105. if( !paused )
  106. {
  107. cvtColor(image, hsv, COLOR_BGR2HSV);
  108. if( trackObject )
  109. {
  110. int _vmin = vmin, _vmax = vmax;
  111. inRange(hsv, Scalar(0, smin, MIN(_vmin,_vmax)),
  112. Scalar(180, 256, MAX(_vmin, _vmax)), mask);
  113. int ch[] = {0, 0};
  114. hue.create(hsv.size(), hsv.depth());
  115. mixChannels(&hsv, 1, &hue, 1, ch, 1);
  116. if( trackObject < 0 )
  117. {
  118. // Object has been selected by user, set up CAMShift search properties once
  119. Mat roi(hue, selection), maskroi(mask, selection);
  120. calcHist(&roi, 1, 0, maskroi, hist, 1, &hsize, &phranges);
  121. normalize(hist, hist, 0, 255, NORM_MINMAX);
  122. trackWindow = selection;
  123. trackObject = 1; // Don't set up again, unless user selects new ROI
  124. histimg = Scalar::all(0);
  125. int binW = histimg.cols / hsize;
  126. Mat buf(1, hsize, CV_8UC3);
  127. for( int i = 0; i < hsize; i++ )
  128. buf.at<Vec3b>(i) = Vec3b(saturate_cast<uchar>(i*180./hsize), 255, 255);
  129. cvtColor(buf, buf, COLOR_HSV2BGR);
  130. for( int i = 0; i < hsize; i++ )
  131. {
  132. int val = saturate_cast<int>(hist.at<float>(i)*histimg.rows/255);
  133. rectangle( histimg, Point(i*binW,histimg.rows),
  134. Point((i+1)*binW,histimg.rows - val),
  135. Scalar(buf.at<Vec3b>(i)), -1, 8 );
  136. }
  137. }
  138. // Perform CAMShift
  139. calcBackProject(&hue, 1, 0, hist, backproj, &phranges);
  140. backproj &= mask;
  141. RotatedRect trackBox = CamShift(backproj, trackWindow,
  142. TermCriteria( TermCriteria::EPS | TermCriteria::COUNT, 10, 1 ));
  143. if( trackWindow.area() <= 1 )
  144. {
  145. int cols = backproj.cols, rows = backproj.rows, r = (MIN(cols, rows) + 5)/6;
  146. trackWindow = Rect(trackWindow.x - r, trackWindow.y - r,
  147. trackWindow.x + r, trackWindow.y + r) &
  148. Rect(0, 0, cols, rows);
  149. }
  150. if( backprojMode )
  151. cvtColor( backproj, image, COLOR_GRAY2BGR );
  152. ellipse( image, trackBox, Scalar(0,0,255), 3, LINE_AA );
  153. }
  154. }
  155. else if( trackObject < 0 )
  156. paused = false;
  157. if( selectObject && selection.width > 0 && selection.height > 0 )
  158. {
  159. Mat roi(image, selection);
  160. bitwise_not(roi, roi);
  161. }
  162. imshow( "CamShift Demo", image );
  163. imshow( "Histogram", histimg );
  164. char c = (char)waitKey(10);
  165. if( c == 27 )
  166. break;
  167. switch(c)
  168. {
  169. case 'b':
  170. backprojMode = !backprojMode;
  171. break;
  172. case 'c':
  173. trackObject = 0;
  174. histimg = Scalar::all(0);
  175. break;
  176. case 'h':
  177. showHist = !showHist;
  178. if( !showHist )
  179. destroyWindow( "Histogram" );
  180. else
  181. namedWindow( "Histogram", 1 );
  182. break;
  183. case 'p':
  184. paused = !paused;
  185. break;
  186. default:
  187. ;
  188. }
  189. }
  190. return 0;
  191. }