Path: blob/master/samples/gpu/cascadeclassifier_nvidia_api.cpp
16337 views
#if defined _MSC_VER && _MSC_VER >= 14001#pragma warning( disable : 4201 4408 4127 4100)2#endif34#include <iostream>5#include <iomanip>6#include <cstdio>7#include "opencv2/core/cuda.hpp"8#include "opencv2/cudalegacy.hpp"9#include "opencv2/highgui.hpp"10#include "opencv2/imgproc.hpp"11#include "opencv2/objdetect.hpp"12#include "opencv2/objdetect/objdetect_c.h"1314using namespace std;15using namespace cv;161718#if !defined(HAVE_CUDA) || defined(__arm__)1920int main( int, const char** )21{22#if !defined(HAVE_CUDA)23std::cout << "CUDA support is required (CMake key 'WITH_CUDA' must be true)." << std::endl;24#endif2526#if defined(__arm__)27std::cout << "Unsupported for ARM CUDA library." << std::endl;28#endif2930return 0;31}3233#else343536const Size2i preferredVideoFrameSize(640, 480);37const cv::String wndTitle = "NVIDIA Computer Vision :: Haar Classifiers Cascade";383940static void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const string &ss)41{42int fontFace = FONT_HERSHEY_DUPLEX;43double fontScale = 0.8;44int fontThickness = 2;45Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);4647Point org;48org.x = 1;49org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;50putText(img, ss, org, fontFace, fontScale, Scalar(0,0,0), 5*fontThickness/2, 16);51putText(img, ss, org, fontFace, fontScale, fontColor, fontThickness, 16);52}535455static void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)56{57Scalar fontColorRed(0,0,255);58Scalar fontColorNV(0,185,118);5960ostringstream ss;61ss << "FPS = " << setprecision(1) << fixed << fps;62matPrint(canvas, 0, fontColorRed, ss.str());63ss.str("");64ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<65(bGpu ? "GPU, " : "CPU, ") <<66(bLargestFace ? "OneFace, " : "MultiFace, ") <<67(bFilter ? "Filter:ON" : "Filter:OFF");68matPrint(canvas, 1, fontColorRed, ss.str());6970if (bHelp)71{72matPrint(canvas, 2, fontColorNV, "Space - switch GPU / CPU");73matPrint(canvas, 3, fontColorNV, "M - switch OneFace / MultiFace");74matPrint(canvas, 4, fontColorNV, "F - toggle rectangles Filter");75matPrint(canvas, 5, fontColorNV, "H - toggle hotkeys help");76}77else78{79matPrint(canvas, 2, fontColorNV, "H - toggle hotkeys help");80}81}828384static NCVStatus process(Mat *srcdst,85Ncv32u width, Ncv32u height,86NcvBool bFilterRects, NcvBool bLargestFace,87HaarClassifierCascadeDescriptor &haar,88NCVVector<HaarStage64> &d_haarStages, NCVVector<HaarClassifierNode128> &d_haarNodes,89NCVVector<HaarFeature64> &d_haarFeatures, NCVVector<HaarStage64> &h_haarStages,90INCVMemAllocator &gpuAllocator,91INCVMemAllocator &cpuAllocator,92cudaDeviceProp &devProp)93{94ncvAssertReturn(!((srcdst == NULL) ^ gpuAllocator.isCounting()), NCV_NULL_PTR);9596NCVStatus ncvStat;9798NCV_SET_SKIP_COND(gpuAllocator.isCounting());99100NCVMatrixAlloc<Ncv8u> d_src(gpuAllocator, width, height);101ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);102NCVMatrixAlloc<Ncv8u> h_src(cpuAllocator, width, height);103ncvAssertReturn(h_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);104NCVVectorAlloc<NcvRect32u> d_rects(gpuAllocator, 100);105ncvAssertReturn(d_rects.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);106107NCV_SKIP_COND_BEGIN108109for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++)110{111memcpy(h_src.ptr() + i * h_src.stride(), srcdst->ptr(i), srcdst->cols);112}113114ncvStat = h_src.copySolid(d_src, 0);115ncvAssertReturnNcvStat(ncvStat);116ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);117118NCV_SKIP_COND_END119120NcvSize32u roi;121roi.width = d_src.width();122roi.height = d_src.height();123124Ncv32u numDetections;125ncvStat = ncvDetectObjectsMultiScale_device(126d_src, roi, d_rects, numDetections, haar, h_haarStages,127d_haarStages, d_haarNodes, d_haarFeatures,128haar.ClassifierSize,129(bFilterRects || bLargestFace) ? 4 : 0,1301.2f, 1,131(bLargestFace ? NCVPipeObjDet_FindLargestObject : 0)132| NCVPipeObjDet_VisualizeInPlace,133gpuAllocator, cpuAllocator, devProp, 0);134ncvAssertReturnNcvStat(ncvStat);135ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);136137NCV_SKIP_COND_BEGIN138139ncvStat = d_src.copySolid(h_src, 0);140ncvAssertReturnNcvStat(ncvStat);141ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);142143for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++)144{145memcpy(srcdst->ptr(i), h_src.ptr() + i * h_src.stride(), srcdst->cols);146}147148NCV_SKIP_COND_END149150return NCV_SUCCESS;151}152153154int main(int argc, const char** argv)155{156cout << "OpenCV / NVIDIA Computer Vision" << endl;157cout << "Face Detection in video and live feed" << endl;158cout << "Syntax: exename <cascade_file> <image_or_video_or_cameraid>" << endl;159cout << "=========================================" << endl;160161ncvAssertPrintReturn(cv::cuda::getCudaEnabledDeviceCount() != 0, "No GPU found or the library is compiled without CUDA support", -1);162ncvAssertPrintReturn(argc == 3, "Invalid number of arguments", -1);163164cv::cuda::printShortCudaDeviceInfo(cv::cuda::getDevice());165166string cascadeName = argv[1];167string inputName = argv[2];168169NCVStatus ncvStat;170NcvBool bQuit = false;171VideoCapture capture;172Size2i frameSize;173174//open content source175Mat image = imread(inputName);176Mat frame;177if (!image.empty())178{179frameSize.width = image.cols;180frameSize.height = image.rows;181}182else183{184if (!capture.open(inputName))185{186int camid = -1;187188istringstream ss(inputName);189int x = 0;190ss >> x;191192ncvAssertPrintReturn(capture.open(camid) != 0, "Can't open source", -1);193}194195capture >> frame;196ncvAssertPrintReturn(!frame.empty(), "Empty video source", -1);197198frameSize.width = frame.cols;199frameSize.height = frame.rows;200}201202NcvBool bUseGPU = true;203NcvBool bLargestObject = false;204NcvBool bFilterRects = true;205NcvBool bHelpScreen = false;206207CascadeClassifier classifierOpenCV;208ncvAssertPrintReturn(classifierOpenCV.load(cascadeName) != 0, "Error (in OpenCV) opening classifier", -1);209210int devId;211ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);212cudaDeviceProp devProp;213ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);214cout << "Using GPU: " << devId << "(" << devProp.name <<215"), arch=" << devProp.major << "." << devProp.minor << endl;216217//==============================================================================218//219// Load the classifier from file (assuming its size is about 1 mb)220// using a simple allocator221//222//==============================================================================223224NCVMemNativeAllocator gpuCascadeAllocator(NCVMemoryTypeDevice, static_cast<Ncv32u>(devProp.textureAlignment));225ncvAssertPrintReturn(gpuCascadeAllocator.isInitialized(), "Error creating cascade GPU allocator", -1);226NCVMemNativeAllocator cpuCascadeAllocator(NCVMemoryTypeHostPinned, static_cast<Ncv32u>(devProp.textureAlignment));227ncvAssertPrintReturn(cpuCascadeAllocator.isInitialized(), "Error creating cascade CPU allocator", -1);228229Ncv32u haarNumStages, haarNumNodes, haarNumFeatures;230ncvStat = ncvHaarGetClassifierSize(cascadeName, haarNumStages, haarNumNodes, haarNumFeatures);231ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", -1);232233NCVVectorAlloc<HaarStage64> h_haarStages(cpuCascadeAllocator, haarNumStages);234ncvAssertPrintReturn(h_haarStages.isMemAllocated(), "Error in cascade CPU allocator", -1);235NCVVectorAlloc<HaarClassifierNode128> h_haarNodes(cpuCascadeAllocator, haarNumNodes);236ncvAssertPrintReturn(h_haarNodes.isMemAllocated(), "Error in cascade CPU allocator", -1);237NCVVectorAlloc<HaarFeature64> h_haarFeatures(cpuCascadeAllocator, haarNumFeatures);238239ncvAssertPrintReturn(h_haarFeatures.isMemAllocated(), "Error in cascade CPU allocator", -1);240241HaarClassifierCascadeDescriptor haar;242ncvStat = ncvHaarLoadFromFile_host(cascadeName, haar, h_haarStages, h_haarNodes, h_haarFeatures);243ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error loading classifier", -1);244245NCVVectorAlloc<HaarStage64> d_haarStages(gpuCascadeAllocator, haarNumStages);246ncvAssertPrintReturn(d_haarStages.isMemAllocated(), "Error in cascade GPU allocator", -1);247NCVVectorAlloc<HaarClassifierNode128> d_haarNodes(gpuCascadeAllocator, haarNumNodes);248ncvAssertPrintReturn(d_haarNodes.isMemAllocated(), "Error in cascade GPU allocator", -1);249NCVVectorAlloc<HaarFeature64> d_haarFeatures(gpuCascadeAllocator, haarNumFeatures);250ncvAssertPrintReturn(d_haarFeatures.isMemAllocated(), "Error in cascade GPU allocator", -1);251252ncvStat = h_haarStages.copySolid(d_haarStages, 0);253ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);254ncvStat = h_haarNodes.copySolid(d_haarNodes, 0);255ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);256ncvStat = h_haarFeatures.copySolid(d_haarFeatures, 0);257ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1);258259//==============================================================================260//261// Calculate memory requirements and create real allocators262//263//==============================================================================264265NCVMemStackAllocator gpuCounter(static_cast<Ncv32u>(devProp.textureAlignment));266ncvAssertPrintReturn(gpuCounter.isInitialized(), "Error creating GPU memory counter", -1);267NCVMemStackAllocator cpuCounter(static_cast<Ncv32u>(devProp.textureAlignment));268ncvAssertPrintReturn(cpuCounter.isInitialized(), "Error creating CPU memory counter", -1);269270ncvStat = process(NULL, frameSize.width, frameSize.height,271false, false, haar,272d_haarStages, d_haarNodes,273d_haarFeatures, h_haarStages,274gpuCounter, cpuCounter, devProp);275ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1);276277NCVMemStackAllocator gpuAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), static_cast<Ncv32u>(devProp.textureAlignment));278ncvAssertPrintReturn(gpuAllocator.isInitialized(), "Error creating GPU memory allocator", -1);279NCVMemStackAllocator cpuAllocator(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), static_cast<Ncv32u>(devProp.textureAlignment));280ncvAssertPrintReturn(cpuAllocator.isInitialized(), "Error creating CPU memory allocator", -1);281282printf("Initialized for frame size [%dx%d]\n", frameSize.width, frameSize.height);283284//==============================================================================285//286// Main processing loop287//288//==============================================================================289290namedWindow(wndTitle, 1);291Mat frameDisp;292293do294{295Mat gray;296cvtColor((image.empty() ? frame : image), gray, cv::COLOR_BGR2GRAY);297298//299// process300//301302NcvSize32u minSize = haar.ClassifierSize;303if (bLargestObject)304{305Ncv32u ratioX = preferredVideoFrameSize.width / minSize.width;306Ncv32u ratioY = preferredVideoFrameSize.height / minSize.height;307Ncv32u ratioSmallest = min(ratioX, ratioY);308ratioSmallest = max((Ncv32u)(ratioSmallest / 2.5f), (Ncv32u)1);309minSize.width *= ratioSmallest;310minSize.height *= ratioSmallest;311}312313Ncv32f avgTime;314NcvTimer timer = ncvStartTimer();315316if (bUseGPU)317{318ncvStat = process(&gray, frameSize.width, frameSize.height,319bFilterRects, bLargestObject, haar,320d_haarStages, d_haarNodes,321d_haarFeatures, h_haarStages,322gpuAllocator, cpuAllocator, devProp);323ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1);324}325else326{327vector<Rect> rectsOpenCV;328329classifierOpenCV.detectMultiScale(330gray,331rectsOpenCV,3321.2f,333bFilterRects ? 4 : 0,334(bLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)335| CV_HAAR_SCALE_IMAGE,336Size(minSize.width, minSize.height));337338for (size_t rt = 0; rt < rectsOpenCV.size(); ++rt)339rectangle(gray, rectsOpenCV[rt], Scalar(255));340}341342avgTime = (Ncv32f)ncvEndQueryTimerMs(timer);343344cvtColor(gray, frameDisp, cv::COLOR_GRAY2BGR);345displayState(frameDisp, bHelpScreen, bUseGPU, bLargestObject, bFilterRects, 1000.0f / avgTime);346imshow(wndTitle, frameDisp);347348//handle input349switch (cv::waitKey(3))350{351case ' ':352bUseGPU = !bUseGPU;353break;354case 'm':355case 'M':356bLargestObject = !bLargestObject;357break;358case 'f':359case 'F':360bFilterRects = !bFilterRects;361break;362case 'h':363case 'H':364bHelpScreen = !bHelpScreen;365break;366case 27:367bQuit = true;368break;369}370371// For camera and video file, capture the next image372if (capture.isOpened())373{374capture >> frame;375if (frame.empty())376{377break;378}379}380} while (!bQuit);381382cv::destroyWindow(wndTitle);383384return 0;385}386387#endif //!defined(HAVE_CUDA)388389390