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