cascadeclassifier.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // WARNING: this sample is under construction! Use it on your own risk.
  2. #if defined _MSC_VER && _MSC_VER >= 1400
  3. #pragma warning(disable : 4100)
  4. #endif
  5. #include <iostream>
  6. #include <iomanip>
  7. #include "opencv2/objdetect.hpp"
  8. #include "opencv2/highgui.hpp"
  9. #include "opencv2/imgproc.hpp"
  10. #include "opencv2/cudaobjdetect.hpp"
  11. #include "opencv2/cudaimgproc.hpp"
  12. #include "opencv2/cudawarping.hpp"
  13. using namespace std;
  14. using namespace cv;
  15. using namespace cv::cuda;
  16. static void help()
  17. {
  18. cout << "Usage: ./cascadeclassifier \n\t--cascade <cascade_file>\n\t(<image>|--video <video>|--camera <camera_id>)\n"
  19. "Using OpenCV version " << CV_VERSION << endl << endl;
  20. }
  21. static void convertAndResize(const Mat& src, Mat& gray, Mat& resized, double scale)
  22. {
  23. if (src.channels() == 3)
  24. {
  25. cv::cvtColor( src, gray, COLOR_BGR2GRAY );
  26. }
  27. else
  28. {
  29. gray = src;
  30. }
  31. Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
  32. if (scale != 1)
  33. {
  34. cv::resize(gray, resized, sz);
  35. }
  36. else
  37. {
  38. resized = gray;
  39. }
  40. }
  41. static void convertAndResize(const GpuMat& src, GpuMat& gray, GpuMat& resized, double scale)
  42. {
  43. if (src.channels() == 3)
  44. {
  45. cv::cuda::cvtColor( src, gray, COLOR_BGR2GRAY );
  46. }
  47. else
  48. {
  49. gray = src;
  50. }
  51. Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
  52. if (scale != 1)
  53. {
  54. cv::cuda::resize(gray, resized, sz);
  55. }
  56. else
  57. {
  58. resized = gray;
  59. }
  60. }
  61. static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)
  62. {
  63. int fontFace = FONT_HERSHEY_DUPLEX;
  64. double fontScale = 0.8;
  65. int fontThickness = 2;
  66. Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);
  67. Point org;
  68. org.x = 1;
  69. org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;
  70. putText(img, ss, org, fontFace, fontScale, Scalar(0,0,0), 5*fontThickness/2, 16);
  71. putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);
  72. }
  73. static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)
  74. {
  75. Scalar fontColorRed = Scalar(255,0,0);
  76. Scalar fontColorNV = Scalar(118,185,0);
  77. ostringstream ss;
  78. ss << "FPS = " << setprecision(1) << fixed << fps;
  79. matPrint(canvas, 0, fontColorRed, ss.str());
  80. ss.str("");
  81. ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<
  82. (bGpu ? "GPU, " : "CPU, ") <<
  83. (bLargestFace ? "OneFace, " : "MultiFace, ") <<
  84. (bFilter ? "Filter:ON" : "Filter:OFF");
  85. matPrint(canvas, 1, fontColorRed, ss.str());
  86. // by Anatoly. MacOS fix. ostringstream(const string&) is a private
  87. // matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));
  88. if (bHelp)
  89. {
  90. matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");
  91. matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");
  92. matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");
  93. matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");
  94. matPrint(canvas, 6, fontColorNV, "1/Q - increase/decrease scale");
  95. }
  96. else
  97. {
  98. matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");
  99. }
  100. }
  101. int main(int argc, const char *argv[])
  102. {
  103. if (argc == 1)
  104. {
  105. help();
  106. return -1;
  107. }
  108. if (getCudaEnabledDeviceCount() == 0)
  109. {
  110. return cerr << "No GPU found or the library is compiled without CUDA support" << endl, -1;
  111. }
  112. cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());
  113. string cascadeName;
  114. string inputName;
  115. bool isInputImage = false;
  116. bool isInputVideo = false;
  117. bool isInputCamera = false;
  118. for (int i = 1; i < argc; ++i)
  119. {
  120. if (string(argv[i]) == "--cascade")
  121. cascadeName = argv[++i];
  122. else if (string(argv[i]) == "--video")
  123. {
  124. inputName = argv[++i];
  125. isInputVideo = true;
  126. }
  127. else if (string(argv[i]) == "--camera")
  128. {
  129. inputName = argv[++i];
  130. isInputCamera = true;
  131. }
  132. else if (string(argv[i]) == "--help")
  133. {
  134. help();
  135. return -1;
  136. }
  137. else if (!isInputImage)
  138. {
  139. inputName = argv[i];
  140. isInputImage = true;
  141. }
  142. else
  143. {
  144. cout << "Unknown key: " << argv[i] << endl;
  145. return -1;
  146. }
  147. }
  148. Ptr<cuda::CascadeClassifier> cascade_gpu = cuda::CascadeClassifier::create(cascadeName);
  149. cv::CascadeClassifier cascade_cpu;
  150. if (!cascade_cpu.load(cascadeName))
  151. {
  152. return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
  153. }
  154. VideoCapture capture;
  155. Mat image;
  156. if (isInputImage)
  157. {
  158. image = imread(inputName);
  159. CV_Assert(!image.empty());
  160. }
  161. else if (isInputVideo)
  162. {
  163. capture.open(inputName);
  164. CV_Assert(capture.isOpened());
  165. }
  166. else
  167. {
  168. capture.open(atoi(inputName.c_str()));
  169. CV_Assert(capture.isOpened());
  170. }
  171. namedWindow("result", 1);
  172. Mat frame, frame_cpu, gray_cpu, resized_cpu, frameDisp;
  173. vector<Rect> faces;
  174. GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu;
  175. /* parameters */
  176. bool useGPU = true;
  177. double scaleFactor = 1.0;
  178. bool findLargestObject = false;
  179. bool filterRects = true;
  180. bool helpScreen = false;
  181. for (;;)
  182. {
  183. if (isInputCamera || isInputVideo)
  184. {
  185. capture >> frame;
  186. if (frame.empty())
  187. {
  188. break;
  189. }
  190. }
  191. (image.empty() ? frame : image).copyTo(frame_cpu);
  192. frame_gpu.upload(image.empty() ? frame : image);
  193. convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor);
  194. convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor);
  195. TickMeter tm;
  196. tm.start();
  197. if (useGPU)
  198. {
  199. cascade_gpu->setFindLargestObject(findLargestObject);
  200. cascade_gpu->setScaleFactor(1.2);
  201. cascade_gpu->setMinNeighbors((filterRects || findLargestObject) ? 4 : 0);
  202. cascade_gpu->detectMultiScale(resized_gpu, facesBuf_gpu);
  203. cascade_gpu->convert(facesBuf_gpu, faces);
  204. }
  205. else
  206. {
  207. Size minSize = cascade_gpu->getClassifierSize();
  208. cascade_cpu.detectMultiScale(resized_cpu, faces, 1.2,
  209. (filterRects || findLargestObject) ? 4 : 0,
  210. (findLargestObject ? CASCADE_FIND_BIGGEST_OBJECT : 0)
  211. | CASCADE_SCALE_IMAGE,
  212. minSize);
  213. }
  214. for (size_t i = 0; i < faces.size(); ++i)
  215. {
  216. rectangle(resized_cpu, faces[i], Scalar(255));
  217. }
  218. tm.stop();
  219. double detectionTime = tm.getTimeMilli();
  220. double fps = 1000 / detectionTime;
  221. //print detections to console
  222. cout << setfill(' ') << setprecision(2);
  223. cout << setw(6) << fixed << fps << " FPS, " << faces.size() << " det";
  224. if ((filterRects || findLargestObject) && !faces.empty())
  225. {
  226. for (size_t i = 0; i < faces.size(); ++i)
  227. {
  228. cout << ", [" << setw(4) << faces[i].x
  229. << ", " << setw(4) << faces[i].y
  230. << ", " << setw(4) << faces[i].width
  231. << ", " << setw(4) << faces[i].height << "]";
  232. }
  233. }
  234. cout << endl;
  235. cv::cvtColor(resized_cpu, frameDisp, COLOR_GRAY2BGR);
  236. displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps);
  237. imshow("result", frameDisp);
  238. char key = (char)waitKey(5);
  239. if (key == 27)
  240. {
  241. break;
  242. }
  243. switch (key)
  244. {
  245. case ' ':
  246. useGPU = !useGPU;
  247. break;
  248. case 'm':
  249. case 'M':
  250. findLargestObject = !findLargestObject;
  251. break;
  252. case 'f':
  253. case 'F':
  254. filterRects = !filterRects;
  255. break;
  256. case '1':
  257. scaleFactor *= 1.05;
  258. break;
  259. case 'q':
  260. case 'Q':
  261. scaleFactor /= 1.05;
  262. break;
  263. case 'h':
  264. case 'H':
  265. helpScreen = !helpScreen;
  266. break;
  267. }
  268. }
  269. return 0;
  270. }