#pragma warning( disable : 4201 4408 4127 4100) #include #include "cvconfig.h" #if !defined(HAVE_CUDA) int main( int argc, const char** argv ) { return printf("Please compile the library with CUDA support."), -1; } #else #include #include "opencv2/opencv.hpp" #include "NCVHaarObjectDetection.hpp" using namespace cv; const Size2i preferredVideoFrameSize(640, 480); std::string preferredClassifier = "haarcascade_frontalface_alt.xml"; std::string wndTitle = "NVIDIA Computer Vision SDK :: Face Detection in Video Feed"; void printSyntax(void) { printf("Syntax: FaceDetectionFeed.exe [-c cameranum | -v filename] classifier.xml\n"); } void imagePrintf(Mat& img, int lineOffsY, Scalar color, const char *format, ...) { int fontFace = CV_FONT_HERSHEY_PLAIN; double fontScale = 1; int baseline; Size textSize = cv::getTextSize("T", fontFace, fontScale, 1, &baseline); va_list arg_ptr; va_start(arg_ptr, format); char strBuf[4096]; vsprintf(&strBuf[0], format, arg_ptr); Point org(1, 3 * textSize.height * (lineOffsY + 1) / 2); putText(img, &strBuf[0], org, fontFace, fontScale, color); va_end(arg_ptr); } NCVStatus process(Mat *srcdst, Ncv32u width, Ncv32u height, NcvBool bShowAllHypotheses, NcvBool bLargestFace, HaarClassifierCascadeDescriptor &haar, NCVVector &d_haarStages, NCVVector &d_haarNodes, NCVVector &d_haarFeatures, NCVVector &h_haarStages, INCVMemAllocator &gpuAllocator, INCVMemAllocator &cpuAllocator, cudaDeviceProp &devProp) { ncvAssertReturn(!((srcdst == NULL) ^ gpuAllocator.isCounting()), NCV_NULL_PTR); NCVStatus ncvStat; NCV_SET_SKIP_COND(gpuAllocator.isCounting()); NCVMatrixAlloc d_src(gpuAllocator, width, height); ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC); NCVMatrixAlloc h_src(cpuAllocator, width, height); ncvAssertReturn(h_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC); NCVVectorAlloc d_rects(gpuAllocator, 100); ncvAssertReturn(d_rects.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC); NCV_SKIP_COND_BEGIN for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++) { memcpy(h_src.ptr() + i * h_src.stride(), srcdst->ptr(i), srcdst->cols); } ncvStat = h_src.copySolid(d_src, 0); ncvAssertReturnNcvStat(ncvStat); ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR); NCV_SKIP_COND_END NcvSize32u roi; roi.width = d_src.width(); roi.height = d_src.height(); Ncv32u numDetections; ncvStat = ncvDetectObjectsMultiScale_device( d_src, roi, d_rects, numDetections, haar, h_haarStages, d_haarStages, d_haarNodes, d_haarFeatures, haar.ClassifierSize, bShowAllHypotheses ? 0 : 4, 1.2f, 1, (bLargestFace ? NCVPipeObjDet_FindLargestObject : 0) | NCVPipeObjDet_VisualizeInPlace, gpuAllocator, cpuAllocator, devProp, 0); ncvAssertReturnNcvStat(ncvStat); ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR); NCV_SKIP_COND_BEGIN ncvStat = d_src.copySolid(h_src, 0); ncvAssertReturnNcvStat(ncvStat); ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR); for (Ncv32u i=0; i<(Ncv32u)srcdst->rows; i++) { memcpy(srcdst->ptr(i), h_src.ptr() + i * h_src.stride(), srcdst->cols); } NCV_SKIP_COND_END return NCV_SUCCESS; } int main( int argc, const char** argv ) { NCVStatus ncvStat; printf("NVIDIA Computer Vision SDK\n"); printf("Face Detection in video and live feed\n"); printf("=========================================\n"); printf(" Esc - Quit\n"); printf(" Space - Switch between NCV and OpenCV\n"); printf(" L - Switch between FullSearch and LargestFace modes\n"); printf(" U - Toggle unfiltered hypotheses visualization in FullSearch\n"); VideoCapture capture; bool bQuit = false; Size2i frameSize; if (argc != 4 && argc != 1) { printSyntax(); return -1; } if (argc == 1 || strcmp(argv[1], "-c") == 0) { // Camera input is specified int camIdx = (argc == 3) ? atoi(argv[2]) : 0; if(!capture.open(camIdx)) return printf("Error opening camera\n"), -1; capture.set(CV_CAP_PROP_FRAME_WIDTH, preferredVideoFrameSize.width); capture.set(CV_CAP_PROP_FRAME_HEIGHT, preferredVideoFrameSize.height); capture.set(CV_CAP_PROP_FPS, 25); frameSize = preferredVideoFrameSize; } else if (strcmp(argv[1], "-v") == 0) { // Video file input (avi) if(!capture.open(argv[2])) return printf("Error opening video file\n"), -1; frameSize.width = (int)capture.get(CV_CAP_PROP_FRAME_WIDTH); frameSize.height = (int)capture.get(CV_CAP_PROP_FRAME_HEIGHT); } else return printSyntax(), -1; NcvBool bUseOpenCV = true; NcvBool bLargestFace = false; //LargestFace=true is used usually during training NcvBool bShowAllHypotheses = false; CascadeClassifier classifierOpenCV; std::string classifierFile; if (argc == 1) { classifierFile = preferredClassifier; } else { classifierFile.assign(argv[3]); } if (!classifierOpenCV.load(classifierFile)) { printf("Error (in OpenCV) opening classifier\n"); printSyntax(); return -1; } int devId; ncvAssertCUDAReturn(cudaGetDevice(&devId), -1); cudaDeviceProp devProp; ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1); printf("Using GPU %d %s, arch=%d.%d\n", devId, devProp.name, devProp.major, devProp.minor); //============================================================================== // // Load the classifier from file (assuming its size is about 1 mb) // using a simple allocator // //============================================================================== NCVMemNativeAllocator gpuCascadeAllocator(NCVMemoryTypeDevice, devProp.textureAlignment); ncvAssertPrintReturn(gpuCascadeAllocator.isInitialized(), "Error creating cascade GPU allocator", -1); NCVMemNativeAllocator cpuCascadeAllocator(NCVMemoryTypeHostPinned, devProp.textureAlignment); ncvAssertPrintReturn(cpuCascadeAllocator.isInitialized(), "Error creating cascade CPU allocator", -1); Ncv32u haarNumStages, haarNumNodes, haarNumFeatures; ncvStat = ncvHaarGetClassifierSize(classifierFile, haarNumStages, haarNumNodes, haarNumFeatures); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", -1); NCVVectorAlloc h_haarStages(cpuCascadeAllocator, haarNumStages); ncvAssertPrintReturn(h_haarStages.isMemAllocated(), "Error in cascade CPU allocator", -1); NCVVectorAlloc h_haarNodes(cpuCascadeAllocator, haarNumNodes); ncvAssertPrintReturn(h_haarNodes.isMemAllocated(), "Error in cascade CPU allocator", -1); NCVVectorAlloc h_haarFeatures(cpuCascadeAllocator, haarNumFeatures); ncvAssertPrintReturn(h_haarFeatures.isMemAllocated(), "Error in cascade CPU allocator", -1); HaarClassifierCascadeDescriptor haar; ncvStat = ncvHaarLoadFromFile_host(classifierFile, haar, h_haarStages, h_haarNodes, h_haarFeatures); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error loading classifier", -1); NCVVectorAlloc d_haarStages(gpuCascadeAllocator, haarNumStages); ncvAssertPrintReturn(d_haarStages.isMemAllocated(), "Error in cascade GPU allocator", -1); NCVVectorAlloc d_haarNodes(gpuCascadeAllocator, haarNumNodes); ncvAssertPrintReturn(d_haarNodes.isMemAllocated(), "Error in cascade GPU allocator", -1); NCVVectorAlloc d_haarFeatures(gpuCascadeAllocator, haarNumFeatures); ncvAssertPrintReturn(d_haarFeatures.isMemAllocated(), "Error in cascade GPU allocator", -1); ncvStat = h_haarStages.copySolid(d_haarStages, 0); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1); ncvStat = h_haarNodes.copySolid(d_haarNodes, 0); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1); ncvStat = h_haarFeatures.copySolid(d_haarFeatures, 0); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", -1); //============================================================================== // // Calculate memory requirements and create real allocators // //============================================================================== NCVMemStackAllocator gpuCounter(devProp.textureAlignment); ncvAssertPrintReturn(gpuCounter.isInitialized(), "Error creating GPU memory counter", -1); NCVMemStackAllocator cpuCounter(devProp.textureAlignment); ncvAssertPrintReturn(cpuCounter.isInitialized(), "Error creating CPU memory counter", -1); ncvStat = process(NULL, frameSize.width, frameSize.height, false, false, haar, d_haarStages, d_haarNodes, d_haarFeatures, h_haarStages, gpuCounter, cpuCounter, devProp); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1); NCVMemStackAllocator gpuAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), devProp.textureAlignment); ncvAssertPrintReturn(gpuAllocator.isInitialized(), "Error creating GPU memory allocator", -1); NCVMemStackAllocator cpuAllocator(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), devProp.textureAlignment); ncvAssertPrintReturn(cpuAllocator.isInitialized(), "Error creating CPU memory allocator", -1); printf("Initialized for frame size [%dx%d]\n", frameSize.width, frameSize.height); //============================================================================== // // Main processing loop // //============================================================================== namedWindow(wndTitle, 1); Mat frame, gray, frameDisp; do { // For camera and video file, capture the next image capture >> frame; if (frame.empty()) break; Mat gray; cvtColor(frame, gray, CV_BGR2GRAY); // // process // NcvSize32u minSize = haar.ClassifierSize; if (bLargestFace) { Ncv32u ratioX = preferredVideoFrameSize.width / minSize.width; Ncv32u ratioY = preferredVideoFrameSize.height / minSize.height; Ncv32u ratioSmallest = std::min(ratioX, ratioY); ratioSmallest = std::max((Ncv32u)(ratioSmallest / 2.5f), (Ncv32u)1); minSize.width *= ratioSmallest; minSize.height *= ratioSmallest; } Ncv32f avgTime; NcvTimer timer = ncvStartTimer(); if (!bUseOpenCV) { ncvStat = process(&gray, frameSize.width, frameSize.height, bShowAllHypotheses, bLargestFace, haar, d_haarStages, d_haarNodes, d_haarFeatures, h_haarStages, gpuAllocator, cpuAllocator, devProp); ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error in memory counting pass", -1); } else { vector rectsOpenCV; classifierOpenCV.detectMultiScale( gray, rectsOpenCV, 1.2f, bShowAllHypotheses && !bLargestFace ? 0 : 4, (bLargestFace ? CV_HAAR_FIND_BIGGEST_OBJECT : 0) | CV_HAAR_SCALE_IMAGE, Size(minSize.width, minSize.height)); for (size_t rt = 0; rt < rectsOpenCV.size(); ++rt) rectangle(gray, rectsOpenCV[rt], Scalar(255)); } avgTime = (Ncv32f)ncvEndQueryTimerMs(timer); cvtColor(gray, frameDisp, CV_GRAY2BGR); imagePrintf(frameDisp, 0, CV_RGB(255, 0,0), "Space - Switch NCV%s / OpenCV%s", bUseOpenCV?"":" (ON)", bUseOpenCV?" (ON)":""); imagePrintf(frameDisp, 1, CV_RGB(255, 0,0), "L - Switch FullSearch%s / LargestFace%s modes", bLargestFace?"":" (ON)", bLargestFace?" (ON)":""); imagePrintf(frameDisp, 2, CV_RGB(255, 0,0), "U - Toggle unfiltered hypotheses visualization in FullSearch %s", bShowAllHypotheses?"(ON)":"(OFF)"); imagePrintf(frameDisp, 3, CV_RGB(118,185,0), " Running at %f FPS on %s", 1000.0f / avgTime, bUseOpenCV?"CPU":"GPU"); cv::imshow(wndTitle, frameDisp); switch (cvWaitKey(3)) { case ' ': bUseOpenCV = !bUseOpenCV; break; case 'L': case 'l': bLargestFace = !bLargestFace; break; case 'U': case 'u': bShowAllHypotheses = !bShowAllHypotheses; break; case 27: bQuit = true; break; } } while (!bQuit); cvDestroyWindow(wndTitle.c_str()); return 0; } #endif