refactored FaceDetection GPU sample

pull/13383/head
Anatoly Baksheev 14 years ago
parent 58476b64a6
commit ce474db8eb
  1. 243
      samples/gpu/cascadeclassifier.cpp

@ -8,73 +8,139 @@
#include <iostream> #include <iostream>
#include <iomanip> #include <iomanip>
#include <stdio.h>
using namespace std; using namespace std;
using namespace cv; using namespace cv;
using namespace cv::gpu; using namespace cv::gpu;
void help() void help()
{ {
cout << "Usage: ./cascadeclassifier <cascade_file> <image_or_video_or_cameraid>\n" cout << "Usage: ./cascadeclassifier <cascade_file> <image_or_video_or_cameraid>\n"
"Using OpenCV version " << CV_VERSION << endl << endl; "Using OpenCV version " << CV_VERSION << endl << endl;
} }
void DetectAndDraw(Mat& img, CascadeClassifier_GPU& cascade); void DetectAndDraw(Mat& img, CascadeClassifier_GPU& cascade);
String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml"; String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";
String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml"; String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";
template<class T> void convertAndResize(const T& src, T& gray, T& resized, double scale)
template<class T> void convertAndReseize(const T& src, T& gray, T& resized, double scale = 2.0)
{ {
if (src.channels() == 3) if (src.channels() == 3)
{
cvtColor( src, gray, CV_BGR2GRAY ); cvtColor( src, gray, CV_BGR2GRAY );
}
else else
{
gray = src; gray = src;
}
Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale)); Size sz(cvRound(gray.cols * scale), cvRound(gray.rows * scale));
if (scale != 1) if (scale != 1)
{
resize(gray, resized, sz); resize(gray, resized, sz);
}
else else
{
resized = gray; 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);
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 )
int main(int argc, const char *argv[])
{ {
if (argc != 3) if (argc != 3)
{
return help(), -1; 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; return cerr << "No GPU found or the library is compiled without GPU support" << endl, -1;
}
VideoCapture capture; VideoCapture capture;
string cascadeName = argv[1]; string cascadeName = argv[1];
string inputName = argv[2]; string inputName = argv[2];
cv::gpu::CascadeClassifier_GPU cascade_gpu; CascadeClassifier_GPU cascade_gpu;
if( !cascade_gpu.load( cascadeName ) ) if (!cascade_gpu.load(cascadeName))
{
return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1; return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
}
cv::CascadeClassifier cascade_cpu; CascadeClassifier cascade_cpu;
if( !cascade_cpu.load( cascadeName ) ) if (!cascade_cpu.load(cascadeName))
{
return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1; return cerr << "ERROR: Could not load cascade classifier \"" << cascadeName << "\"" << endl, help(), -1;
}
Mat image = imread(inputName);
Mat image = imread( inputName); if (image.empty())
if( image.empty() ) {
if (!capture.open(inputName)) if (!capture.open(inputName))
{ {
int camid = 0; int camid = 0;
sscanf(inputName.c_str(), "%d", &camid); sscanf(inputName.c_str(), "%d", &camid);
if(!capture.open(camid)) if (!capture.open(camid))
{
cout << "Can't open source" << endl; 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; Mat frame, frame_cpu, gray_cpu, resized_cpu, faces_downloaded, frameDisp;
vector<Rect> facesBuf_cpu; vector<Rect> facesBuf_cpu;
@ -83,120 +149,119 @@ int main( int argc, const char** argv )
/* parameters */ /* parameters */
bool useGPU = true; bool useGPU = true;
double scale_factor = 1; double scaleFactor = 1.0;
double font_scale = 0.8;
bool visualizeInPlace = false;
bool findLargestObject = false; bool findLargestObject = false;
int minNeighbors = 4; bool filterRects = true;
bool helpScreen = false;
printf("\t<space> - 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; int detections_num;
for(;;) for (;;)
{ {
if( capture.isOpened() ) if (capture.isOpened())
{ {
capture >> frame; capture >> frame;
if( frame.empty()) if (frame.empty())
{
break; break;
}
} }
(image.empty() ? frame : image).copyTo(frame_cpu); (image.empty() ? frame : image).copyTo(frame_cpu);
frame_gpu.upload( image.empty() ? frame : image); frame_gpu.upload(image.empty() ? frame : image);
convertAndReseize(frame_gpu, gray_gpu, resized_gpu, scale_factor); convertAndResize(frame_gpu, gray_gpu, resized_gpu, scaleFactor);
convertAndReseize(frame_cpu, gray_cpu, resized_cpu, scale_factor); convertAndResize(frame_cpu, gray_cpu, resized_cpu, scaleFactor);
cv::TickMeter tm; TickMeter tm;
tm.start(); tm.start();
if (useGPU) if (useGPU)
{ {
cascade_gpu.visualizeInPlace = visualizeInPlace; cascade_gpu.visualizeInPlace = true;
cascade_gpu.findLargestObject = findLargestObject; 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); facesBuf_gpu.colRange(0, detections_num).download(faces_downloaded);
} }
else /* so use CPU */ else
{ {
Size minSize = cascade_gpu.getClassifierSize(); Size minSize = cascade_gpu.getClassifierSize();
if (findLargestObject) cascade_cpu.detectMultiScale(resized_cpu, facesBuf_cpu, 1.2, filterRects ? 4 : 0, (findLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0) | CV_HAAR_SCALE_IMAGE, minSize);
{
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);
detections_num = (int)facesBuf_cpu.size(); detections_num = (int)facesBuf_cpu.size();
} }
tm.stop(); if (!useGPU)
printf( "detection time = %g ms\n", tm.getTimeMilli() ); {
if (useGPU)
resized_gpu.download(resized_cpu);
if (!visualizeInPlace || !useGPU)
if (detections_num) if (detections_num)
{ {
Rect* faces = useGPU ? faces_downloaded.ptr<Rect>() : &facesBuf_cpu[0]; for (int i = 0; i < detections_num; ++i)
for(int i = 0; i < detections_num; ++i) {
cv::rectangle(resized_cpu, faces[i], Scalar(255)); rectangle(resized_cpu, facesBuf_cpu[i], Scalar(255));
}
} }
}
int tickness = font_scale > 0.75 ? 2 : 1; if (useGPU)
{
Point text_pos(5, 25); resized_gpu.download(resized_cpu);
Scalar color = CV_RGB(255, 0, 0); }
Size fontSz = cv::getTextSize("T[]", FONT_HERSHEY_SIMPLEX, font_scale, tickness, 0);
int offs = fontSz.height + 5;
cv::cvtColor(resized_cpu, frameDisp, CV_GRAY2BGR);
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);
if (findLargestObject) tm.stop();
putText(frameDisp, "FindLargestObject", text_pos+=Point(0,offs), FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); double detectionTime = tm.getTimeMilli();
double fps = 1000 / detectionTime;
if (visualizeInPlace && useGPU) //print detections to console
putText(frameDisp, "VisualizeInPlace", text_pos+Point(0,offs), FONT_HERSHEY_SIMPLEX, font_scale, color, tickness); 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<Rect>() : &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;
cv::imshow( "result", frameDisp); cvtColor(resized_cpu, frameDisp, CV_GRAY2BGR);
displayState(frameDisp, helpScreen, useGPU, findLargestObject, filterRects, fps);
imshow("result", frameDisp);
int key = waitKey( 5 ); int key = waitKey(5);
if( key == 27) if (key == 27)
{
break; break;
}
switch ((char)key) switch ((char)key)
{ {
case ' ': useGPU = !useGPU; printf("Using %s\n", useGPU ? "GPU" : "CPU");break; case ' ':
case 'v': case 'V': visualizeInPlace = !visualizeInPlace; printf("VisualizeInPlace = %d\n", visualizeInPlace); break; useGPU = !useGPU;
case 'l': case 'L': findLargestObject = !findLargestObject; printf("FindLargestObject = %d\n", findLargestObject); break; break;
case '1': scale_factor*=1.05; printf("Scale factor = %g\n", scale_factor); break; case 'm':
case 'q': case 'Q':scale_factor/=1.05; printf("Scale factor = %g\n", scale_factor); break; case 'M':
findLargestObject = !findLargestObject;
case '3': font_scale*=1.05; printf("Fond scale = %g\n", font_scale); break; break;
case 'e': case 'E':font_scale/=1.05; printf("Fond scale = %g\n", font_scale); break; case 'f':
case 'F':
case '2': ++minNeighbors; printf("Min Neighbors = %d\n", minNeighbors); break; filterRects = !filterRects;
case 'w': case 'W':minNeighbors = max(minNeighbors-1, 0); printf("Min Neighbors = %d\n", minNeighbors); break; break;
case '1':
scaleFactor *= 1.05;
break;
case 'q':
case 'Q':
scaleFactor /= 1.05;
break;
case 'h':
case 'H':
helpScreen = !helpScreen;
break;
} }
} }
return 0; return 0;
} }

Loading…
Cancel
Save