diff --git a/samples/gpu/cascadeclassifier.cpp b/samples/gpu/cascadeclassifier.cpp index 5c4a52582e..08ea80a66a 100644 --- a/samples/gpu/cascadeclassifier.cpp +++ b/samples/gpu/cascadeclassifier.cpp @@ -8,195 +8,260 @@ #include #include -#include using namespace std; using namespace cv; using namespace cv::gpu; + void help() { - cout << "Usage: ./cascadeclassifier \n" + cout << "Usage: ./cascadeclassifier \n" "Using OpenCV version " << CV_VERSION << endl << endl; } + void DetectAndDraw(Mat& img, CascadeClassifier_GPU& cascade); + String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml"; String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml"; - -template void convertAndReseize(const T& src, T& gray, T& resized, double scale = 2.0) +template void convertAndResize(const T& src, T& gray, T& resized, double scale) { if (src.channels() == 3) + { cvtColor( src, gray, CV_BGR2GRAY ); + } else + { gray = src; + } Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale)); + if (scale != 1) + { resize(gray, resized, sz); + } else + { resized = gray; + } } +void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const ostringstream &ss) +{ + int fontFace = FONT_HERSHEY_PLAIN; + double fontScale = 1.5; + int fontThickness = 2; + Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0); -int main( int argc, const char** argv ) -{ + Point org; + org.x = 1; + org.y = 3 * fontSize.height * (lineOffsY + 1) / 2; + putText(img, ss.str(), org, fontFace, fontScale, fontColor, fontThickness); +} + + +void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps) +{ + Scalar fontColorRed = CV_RGB(255,0,0); + Scalar fontColorNV = CV_RGB(118,185,0); + + ostringstream ss; + ss << "[" << canvas.cols << "x" << canvas.rows << "], " << + (bGpu ? "GPU, " : "CPU, ") << + (bLargestFace ? "OneFace, " : "MultiFace, ") << + (bFilter ? "Filter:ON, " : "Filter:OFF, ") << + "FPS = " << setprecision(1) << fixed << fps; + + matPrint(canvas, 0, fontColorRed, ss); + + if (bHelp) + { + matPrint(canvas, 1, fontColorNV, ostringstream("Space - switch GPU / CPU")); + matPrint(canvas, 2, fontColorNV, ostringstream("M - switch OneFace / MultiFace")); + matPrint(canvas, 3, fontColorNV, ostringstream("F - toggle rectangles Filter (only in MultiFace)")); + matPrint(canvas, 4, fontColorNV, ostringstream("H - toggle hotkeys help")); + matPrint(canvas, 5, fontColorNV, ostringstream("1/Q - increase/decrease scale")); + } + else + { + matPrint(canvas, 1, fontColorNV, ostringstream("H - toggle hotkeys help")); + } +} + + +int main(int argc, const char *argv[]) +{ if (argc != 3) + { return help(), -1; + } - if (cv::gpu::getCudaEnabledDeviceCount() == 0) + if (getCudaEnabledDeviceCount() == 0) + { return cerr << "No GPU found or the library is compiled without GPU support" << endl, -1; + } VideoCapture capture; - + string cascadeName = argv[1]; string inputName = argv[2]; - cv::gpu::CascadeClassifier_GPU cascade_gpu; - if( !cascade_gpu.load( cascadeName ) ) + CascadeClassifier_GPU cascade_gpu; + if (!cascade_gpu.load(cascadeName)) + { return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1; + } - cv::CascadeClassifier cascade_cpu; - if( !cascade_cpu.load( cascadeName ) ) + CascadeClassifier cascade_cpu; + if (!cascade_cpu.load(cascadeName)) + { return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1; - - Mat image = imread( inputName); - if( image.empty() ) + } + + Mat image = imread(inputName); + + if (image.empty()) + { if (!capture.open(inputName)) { int camid = 0; sscanf(inputName.c_str(), "%d", &camid); - if(!capture.open(camid)) + if (!capture.open(camid)) + { cout << "Can't open source" << endl; + return help(), -1; + } } - - namedWindow( "result", 1 ); - + } + + namedWindow("result", 1); + Mat frame, frame_cpu, gray_cpu, resized_cpu, faces_downloaded, frameDisp; vector facesBuf_cpu; - GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu; - + GpuMat frame_gpu, gray_gpu, resized_gpu, facesBuf_gpu; + /* parameters */ bool useGPU = true; - double scale_factor = 1; - double font_scale = 0.8; - - bool visualizeInPlace = false; - bool findLargestObject = false; - int minNeighbors = 4; + double scaleFactor = 1.0; + bool findLargestObject = false; + bool filterRects = true; + bool helpScreen = false; - printf("\t - toggle GPU/CPU\n"); - printf("\tL - toggle lagest faces\n"); - printf("\tV - toggle visualisation in-place (for GPU only)\n"); - printf("\t1/q - inc/dec scale\n"); - int detections_num; - for(;;) - { - if( capture.isOpened() ) + for (;;) + { + if (capture.isOpened()) { - capture >> frame; - if( frame.empty()) + capture >> frame; + if (frame.empty()) + { break; + } } (image.empty() ? frame : image).copyTo(frame_cpu); - frame_gpu.upload( image.empty() ? frame : image); - - convertAndReseize(frame_gpu, gray_gpu, resized_gpu, scale_factor); - convertAndReseize(frame_cpu, gray_cpu, resized_cpu, scale_factor); + frame_gpu.upload(image.empty() ? frame : image); - cv::TickMeter tm; - tm.start(); + convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor); + convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor); + + TickMeter tm; + tm.start(); if (useGPU) { - cascade_gpu.visualizeInPlace = visualizeInPlace; - cascade_gpu.findLargestObject = findLargestObject; + cascade_gpu.visualizeInPlace = true; + cascade_gpu.findLargestObject = findLargestObject; - detections_num = cascade_gpu.detectMultiScale( resized_gpu, facesBuf_gpu, 1.2, minNeighbors); + detections_num = cascade_gpu.detectMultiScale(resized_gpu, facesBuf_gpu, 1.2, filterRects ? 4 : 0); facesBuf_gpu.colRange(0, detections_num).download(faces_downloaded); - } - else /* so use CPU */ - { + else + { Size minSize = cascade_gpu.getClassifierSize(); - if (findLargestObject) - { - float ratio = (float)std::min(frame.cols / minSize.width, frame.rows / minSize.height); - ratio = std::max(ratio / 2.5f, 1.f); - minSize = Size(cvRound(minSize.width * ratio), cvRound(minSize.height * ratio)); - } - - cascade_cpu.detectMultiScale(resized_cpu, facesBuf_cpu, 1.2, minNeighbors, (findLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0) | CV_HAAR_SCALE_IMAGE, minSize); + cascade_cpu.detectMultiScale(resized_cpu, facesBuf_cpu, 1.2, filterRects ? 4 : 0, (findLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0) | CV_HAAR_SCALE_IMAGE, minSize); detections_num = (int)facesBuf_cpu.size(); } - tm.stop(); - printf( "detection time = %g ms\n", tm.getTimeMilli() ); - - if (useGPU) - resized_gpu.download(resized_cpu); - - if (!visualizeInPlace || !useGPU) + if (!useGPU) + { if (detections_num) { - Rect* faces = useGPU ? faces_downloaded.ptr() : &facesBuf_cpu[0]; - for(int i = 0; i < detections_num; ++i) - cv::rectangle(resized_cpu, faces[i], Scalar(255)); + for (int i = 0; i < detections_num; ++i) + { + rectangle(resized_cpu, facesBuf_cpu[i], Scalar(255)); + } } - - int tickness = font_scale > 0.75 ? 2 : 1; + } - Point text_pos(5, 25); - Scalar color = CV_RGB(255, 0, 0); - Size fontSz = cv::getTextSize("T[]", FONT_HERSHEY_SIMPLEX, font_scale, tickness, 0); - int offs = fontSz.height + 5; + if (useGPU) + { + resized_gpu.download(resized_cpu); + } - cv::cvtColor(resized_cpu, frameDisp, CV_GRAY2BGR); + tm.stop(); + double detectionTime = tm.getTimeMilli(); + double fps = 1000 / detectionTime; - char buf[4096]; - sprintf(buf, "%s, FPS = %0.3g", useGPU ? "GPU (device) " : "CPU (host)", 1.0/tm.getTimeSec()); - putText(frameDisp, buf, text_pos, FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); - sprintf(buf, "scale = %0.3g, [%d x %d] x scale, Min neighbors = %d", scale_factor, frame.cols, frame.rows, minNeighbors); - putText(frameDisp, buf, text_pos+=Point(0,offs), FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); - putText(frameDisp, "Hotkeys: space, 1/Q, 2/E, 3/E, L, V, Esc", text_pos+=Point(0,offs), FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); + //print detections to console + cout << setfill(' ') << setprecision(2); + cout << setw(6) << fixed << fps << " FPS, " << detections_num << " det"; + if ((filterRects || findLargestObject) && detections_num > 0) + { + Rect *faceRects = useGPU ? faces_downloaded.ptr() : &facesBuf_cpu[0]; + for (int i = 0; i < min(detections_num, 2); ++i) + { + cout << ", [" << setw(4) << faceRects[i].x + << ", " << setw(4) << faceRects[i].y + << ", " << setw(4) << faceRects[i].width + << ", " << setw(4) << faceRects[i].height << "]"; + } + } + cout << endl; - if (findLargestObject) - putText(frameDisp, "FindLargestObject", text_pos+=Point(0,offs), FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); + cvtColor(resized_cpu, frameDisp, CV_GRAY2BGR); + displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps); + imshow("result", frameDisp); - if (visualizeInPlace && useGPU) - putText(frameDisp, "VisualizeInPlace", text_pos+Point(0,offs), FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); - - cv::imshow( "result", frameDisp); - - int key = waitKey( 5 ); - if( key == 27) + int key = waitKey(5); + if (key == 27) + { break; + } switch ((char)key) { - case ' ': useGPU = !useGPU; printf("Using %s\n", useGPU ? "GPU" : "CPU");break; - case 'v': case 'V': visualizeInPlace = !visualizeInPlace; printf("VisualizeInPlace = %d\n", visualizeInPlace); break; - case 'l': case 'L': findLargestObject = !findLargestObject; printf("FindLargestObject = %d\n", findLargestObject); break; - case '1': scale_factor*=1.05; printf("Scale factor = %g\n", scale_factor); break; - case 'q': case 'Q':scale_factor/=1.05; printf("Scale factor = %g\n", scale_factor); break; - - case '3': font_scale*=1.05; printf("Fond scale = %g\n", font_scale); break; - case 'e': case 'E':font_scale/=1.05; printf("Fond scale = %g\n", font_scale); break; - - case '2': ++minNeighbors; printf("Min Neighbors = %d\n", minNeighbors); break; - case 'w': case 'W':minNeighbors = max(minNeighbors-1, 0); printf("Min Neighbors = %d\n", minNeighbors); break; + case ' ': + useGPU = !useGPU; + break; + case 'm': + case 'M': + findLargestObject = !findLargestObject; + break; + case 'f': + case 'F': + filterRects = !filterRects; + break; + case '1': + scaleFactor *= 1.05; + break; + case 'q': + case 'Q': + scaleFactor /= 1.05; + break; + case 'h': + case 'H': + helpScreen = !helpScreen; + break; } - - } + } + return 0; } - - -