// The cascade classifier class for object detection.\r
class CV_EXPORTS CascadeClassifier_GPU\r
{\r
- public: \r
+ public:\r
CascadeClassifier_GPU();\r
CascadeClassifier_GPU(const string& filename);\r
~CascadeClassifier_GPU();\r
bool empty() const;\r
bool load(const string& filename);\r
void release();\r
- \r
+\r
/* returns number of detected objects */\r
int detectMultiScale( const GpuMat& image, GpuMat& objectsBuf, double scaleFactor=1.2, int minNeighbors=4, Size minSize=Size());\r
- \r
+\r
bool findLargestObject;\r
bool visualizeInPlace;\r
\r
Size getClassifierSize() const;\r
private:\r
- \r
- struct CascadeClassifierImpl; \r
- CascadeClassifierImpl* impl; \r
+\r
+ struct CascadeClassifierImpl;\r
+ CascadeClassifierImpl* impl;\r
};\r
- \r
+\r
////////////////////////////////// SURF //////////////////////////////////////////\r
\r
class CV_EXPORTS SURF_GPU : public CvSURFParams\r
#else\r
\r
struct cv::gpu::CascadeClassifier_GPU::CascadeClassifierImpl\r
-{ \r
+{\r
CascadeClassifierImpl(const string& filename) : lastAllocatedFrameSize(-1, -1)\r
{\r
- ncvSetDebugOutputHandler(NCVDebugOutputHandler); \r
+ ncvSetDebugOutputHandler(NCVDebugOutputHandler);\r
if (ncvStat != load(filename))\r
+ {\r
CV_Error(CV_GpuApiCallError, "Error in GPU cacade load");\r
- } \r
- NCVStatus process(const GpuMat& src, GpuMat& objects, float scaleStep, int minNeighbors, bool findLargestObject, bool visualizeInPlace, NcvSize32u ncvMinSize, /*out*/unsigned int& numDetections)\r
- { \r
- calculateMemReqsAndAllocate(src.size()); \r
+ }\r
+ }\r
+\r
+\r
+ NCVStatus process(const GpuMat& src, GpuMat& objects, float scaleStep, int minNeighbors,\r
+ bool findLargestObject, bool visualizeInPlace, NcvSize32u ncvMinSize,\r
+ /*out*/unsigned int& numDetections)\r
+ {\r
+ calculateMemReqsAndAllocate(src.size());\r
\r
NCVMemPtr src_beg;\r
src_beg.ptr = (void*)src.ptr<Ncv8u>();\r
src_seg.begin = src_beg;\r
src_seg.size = src.step * src.rows;\r
\r
- NCVMatrixReuse<Ncv8u> d_src(src_seg, devProp.textureAlignment, src.cols, src.rows, src.step, true); \r
- ncvAssertReturn(d_src.isMemReused(), NCV_ALLOCATOR_BAD_REUSE);\r
- \r
- //NCVMatrixAlloc<Ncv8u> d_src(*gpuAllocator, src.cols, src.rows);\r
- //ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);\r
-\r
- //NCVMatrixAlloc<Ncv8u> h_src(*cpuAllocator, src.cols, src.rows);\r
- //ncvAssertReturn(h_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);\r
+ NCVMatrixReuse<Ncv8u> d_src(src_seg, devProp.textureAlignment, src.cols, src.rows, src.step, true);\r
+ ncvAssertReturn(d_src.isMemReused(), NCV_ALLOCATOR_BAD_REUSE);\r
\r
CV_Assert(objects.rows == 1);\r
\r
objects_seg.begin = objects_beg;\r
objects_seg.size = objects.step * objects.rows;\r
NCVVectorReuse<NcvRect32u> d_rects(objects_seg, objects.cols);\r
- ncvAssertReturn(d_rects.isMemReused(), NCV_ALLOCATOR_BAD_REUSE);\r
- //NCVVectorAlloc<NcvRect32u> d_rects(*gpuAllocator, 100); \r
- //ncvAssertReturn(d_rects.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC); \r
- \r
+ ncvAssertReturn(d_rects.isMemReused(), NCV_ALLOCATOR_BAD_REUSE);\r
+\r
NcvSize32u roi;\r
roi.width = d_src.width();\r
roi.height = d_src.height();\r
Ncv32u flags = 0;\r
flags |= findLargestObject? NCVPipeObjDet_FindLargestObject : 0;\r
flags |= visualizeInPlace ? NCVPipeObjDet_VisualizeInPlace : 0;\r
- \r
+\r
ncvStat = ncvDetectObjectsMultiScale_device(\r
d_src, roi, d_rects, numDetections, haar, *h_haarStages,\r
*d_haarStages, *d_haarNodes, *d_haarFeatures,\r
*gpuAllocator, *cpuAllocator, devProp, 0);\r
ncvAssertReturnNcvStat(ncvStat);\r
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);\r
- \r
+\r
return NCV_SUCCESS;\r
}\r
- ////\r
- \r
+\r
+\r
NcvSize32u getClassifierSize() const { return haar.ClassifierSize; }\r
cv::Size getClassifierCvSize() const { return cv::Size(haar.ClassifierSize.width, haar.ClassifierSize.height); }\r
+\r
+\r
private:\r
\r
+\r
static void NCVDebugOutputHandler(const char* msg) { CV_Error(CV_GpuApiCallError, msg); }\r
\r
+\r
NCVStatus load(const string& classifierFile)\r
- { \r
- int devId = cv::gpu::getDevice(); \r
+ {\r
+ int devId = cv::gpu::getDevice();\r
ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), NCV_CUDA_ERROR);\r
\r
// Load the classifier from file (assuming its size is about 1 mb) using a simple allocator\r
- gpuCascadeAllocator = new NCVMemNativeAllocator(NCVMemoryTypeDevice, devProp.textureAlignment); \r
+ gpuCascadeAllocator = new NCVMemNativeAllocator(NCVMemoryTypeDevice, devProp.textureAlignment);\r
cpuCascadeAllocator = new NCVMemNativeAllocator(NCVMemoryTypeHostPinned, devProp.textureAlignment);\r
\r
ncvAssertPrintReturn(gpuCascadeAllocator->isInitialized(), "Error creating cascade GPU allocator", NCV_CUDA_ERROR);\r
ncvStat = ncvHaarGetClassifierSize(classifierFile, haarNumStages, haarNumNodes, haarNumFeatures);\r
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", NCV_FILE_ERROR);\r
\r
- h_haarStages = new NCVVectorAlloc<HaarStage64>(*cpuCascadeAllocator, haarNumStages); \r
+ h_haarStages = new NCVVectorAlloc<HaarStage64>(*cpuCascadeAllocator, haarNumStages);\r
h_haarNodes = new NCVVectorAlloc<HaarClassifierNode128>(*cpuCascadeAllocator, haarNumNodes);\r
h_haarFeatures = new NCVVectorAlloc<HaarFeature64>(*cpuCascadeAllocator, haarNumFeatures);\r
\r
ncvAssertPrintReturn(h_haarStages->isMemAllocated(), "Error in cascade CPU allocator", NCV_CUDA_ERROR);\r
- ncvAssertPrintReturn(h_haarNodes->isMemAllocated(), "Error in cascade CPU allocator", NCV_CUDA_ERROR); \r
+ ncvAssertPrintReturn(h_haarNodes->isMemAllocated(), "Error in cascade CPU allocator", NCV_CUDA_ERROR);\r
ncvAssertPrintReturn(h_haarFeatures->isMemAllocated(), "Error in cascade CPU allocator", NCV_CUDA_ERROR);\r
\r
ncvStat = ncvHaarLoadFromFile_host(classifierFile, haar, *h_haarStages, *h_haarNodes, *h_haarFeatures);\r
d_haarFeatures = new NCVVectorAlloc<HaarFeature64>(*gpuCascadeAllocator, haarNumFeatures);\r
\r
ncvAssertPrintReturn(d_haarStages->isMemAllocated(), "Error in cascade GPU allocator", NCV_CUDA_ERROR);\r
- ncvAssertPrintReturn(d_haarNodes->isMemAllocated(), "Error in cascade GPU allocator", NCV_CUDA_ERROR); \r
+ ncvAssertPrintReturn(d_haarNodes->isMemAllocated(), "Error in cascade GPU allocator", NCV_CUDA_ERROR);\r
ncvAssertPrintReturn(d_haarFeatures->isMemAllocated(), "Error in cascade GPU allocator", NCV_CUDA_ERROR);\r
\r
ncvStat = h_haarStages->copySolid(*d_haarStages, 0);\r
ncvStat = h_haarNodes->copySolid(*d_haarNodes, 0);\r
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", NCV_CUDA_ERROR);\r
ncvStat = h_haarFeatures->copySolid(*d_haarFeatures, 0);\r
- ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", NCV_CUDA_ERROR); \r
+ ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error copying cascade to GPU", NCV_CUDA_ERROR);\r
\r
return NCV_SUCCESS;\r
}\r
- ////\r
+\r
\r
NCVStatus calculateMemReqsAndAllocate(const Size& frameSize)\r
- { \r
+ {\r
if (lastAllocatedFrameSize == frameSize)\r
+ {\r
return NCV_SUCCESS;\r
+ }\r
\r
// Calculate memory requirements and create real allocators\r
NCVMemStackAllocator gpuCounter(devProp.textureAlignment);\r
NCVMemStackAllocator cpuCounter(devProp.textureAlignment);\r
\r
- ncvAssertPrintReturn(gpuCounter.isInitialized(), "Error creating GPU memory counter", NCV_CUDA_ERROR); \r
+ ncvAssertPrintReturn(gpuCounter.isInitialized(), "Error creating GPU memory counter", NCV_CUDA_ERROR);\r
ncvAssertPrintReturn(cpuCounter.isInitialized(), "Error creating CPU memory counter", NCV_CUDA_ERROR);\r
- \r
+\r
NCVMatrixAlloc<Ncv8u> d_src(gpuCounter, frameSize.width, frameSize.height);\r
NCVMatrixAlloc<Ncv8u> h_src(cpuCounter, frameSize.width, frameSize.height);\r
\r
- ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC); \r
+ ncvAssertReturn(d_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);\r
ncvAssertReturn(h_src.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);\r
\r
- NCVVectorAlloc<NcvRect32u> d_rects(gpuCounter, 100); \r
+ NCVVectorAlloc<NcvRect32u> d_rects(gpuCounter, 100);\r
ncvAssertReturn(d_rects.isMemAllocated(), NCV_ALLOCATOR_BAD_ALLOC);\r
\r
NcvSize32u roi;\r
\r
ncvAssertReturnNcvStat(ncvStat);\r
ncvAssertCUDAReturn(cudaStreamSynchronize(0), NCV_CUDA_ERROR);\r
- \r
- gpuAllocator = new NCVMemStackAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), devProp.textureAlignment); \r
+\r
+ gpuAllocator = new NCVMemStackAllocator(NCVMemoryTypeDevice, gpuCounter.maxSize(), devProp.textureAlignment);\r
cpuAllocator = new NCVMemStackAllocator(NCVMemoryTypeHostPinned, cpuCounter.maxSize(), devProp.textureAlignment);\r
\r
ncvAssertPrintReturn(gpuAllocator->isInitialized(), "Error creating GPU memory allocator", NCV_CUDA_ERROR);\r
- ncvAssertPrintReturn(cpuAllocator->isInitialized(), "Error creating CPU memory allocator", NCV_CUDA_ERROR); \r
+ ncvAssertPrintReturn(cpuAllocator->isInitialized(), "Error creating CPU memory allocator", NCV_CUDA_ERROR);\r
return NCV_SUCCESS;\r
}\r
- //// \r
+\r
\r
cudaDeviceProp devProp;\r
NCVStatus ncvStat;\r
\r
- Ptr<NCVMemNativeAllocator> gpuCascadeAllocator; \r
+ Ptr<NCVMemNativeAllocator> gpuCascadeAllocator;\r
Ptr<NCVMemNativeAllocator> cpuCascadeAllocator;\r
\r
- Ptr<NCVVectorAlloc<HaarStage64> > h_haarStages; \r
+ Ptr<NCVVectorAlloc<HaarStage64> > h_haarStages;\r
Ptr<NCVVectorAlloc<HaarClassifierNode128> > h_haarNodes;\r
Ptr<NCVVectorAlloc<HaarFeature64> > h_haarFeatures;\r
\r
\r
Size lastAllocatedFrameSize;\r
\r
- Ptr<NCVMemStackAllocator> gpuAllocator; \r
+ Ptr<NCVMemStackAllocator> gpuAllocator;\r
Ptr<NCVMemStackAllocator> cpuAllocator;\r
};\r
\r
\r
-\r
cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU() : findLargestObject(false), visualizeInPlace(false), impl(0) {}\r
cv::gpu::CascadeClassifier_GPU::CascadeClassifier_GPU(const string& filename) : findLargestObject(false), visualizeInPlace(false), impl(0) { load(filename); }\r
cv::gpu::CascadeClassifier_GPU::~CascadeClassifier_GPU() { release(); }\r
bool cv::gpu::CascadeClassifier_GPU::empty() const { return impl == 0; }\r
-\r
void cv::gpu::CascadeClassifier_GPU::release() { if (impl) { delete impl; impl = 0; } }\r
\r
+\r
bool cv::gpu::CascadeClassifier_GPU::load(const string& filename)\r
-{ \r
+{\r
release();\r
impl = new CascadeClassifierImpl(filename);\r
- return !this->empty(); \r
+ return !this->empty();\r
}\r
\r
+\r
Size cv::gpu::CascadeClassifier_GPU::getClassifierSize() const\r
{\r
return this->empty() ? Size() : impl->getClassifierCvSize();\r
}\r
- \r
+\r
+\r
int cv::gpu::CascadeClassifier_GPU::detectMultiScale( const GpuMat& image, GpuMat& objectsBuf, double scaleFactor, int minNeighbors, Size minSize)\r
-{ \r
+{\r
CV_Assert( scaleFactor > 1 && image.depth() == CV_8U);\r
CV_Assert( !this->empty());\r
- \r
+\r
const int defaultObjSearchNum = 100;\r
if (objectsBuf.empty())\r
+ {\r
objectsBuf.create(1, defaultObjSearchNum, DataType<Rect>::type);\r
- \r
+ }\r
+\r
NcvSize32u ncvMinSize = impl->getClassifierSize();\r
\r
if (ncvMinSize.width < (unsigned)minSize.width && ncvMinSize.height < (unsigned)minSize.height)\r
{\r
ncvMinSize.width = minSize.width;\r
ncvMinSize.height = minSize.height;\r
- } \r
- \r
+ }\r
+\r
unsigned int numDetections;\r
- NCVStatus ncvStat = impl->process(image, objectsBuf, (float)scaleFactor, minNeighbors, findLargestObject, visualizeInPlace, ncvMinSize, numDetections); \r
+ NCVStatus ncvStat = impl->process(image, objectsBuf, (float)scaleFactor, minNeighbors, findLargestObject, visualizeInPlace, ncvMinSize, numDetections);\r
if (ncvStat != NCV_SUCCESS)\r
+ {\r
CV_Error(CV_GpuApiCallError, "Error in face detectioln");\r
+ }\r
\r
return numDetections;\r
}\r
\r
+\r
struct RectConvert\r
{\r
- Rect operator()(const NcvRect32u& nr) const { return Rect(nr.x, nr.y, nr.width, nr.height); }\r
- NcvRect32u operator()(const Rect& nr) const \r
- { \r
- NcvRect32u rect;\r
- rect.x = nr.x;\r
- rect.y = nr.y;\r
- rect.width = nr.width;\r
- rect.height = nr.height;\r
- return rect; \r
- }\r
+ Rect operator()(const NcvRect32u& nr) const { return Rect(nr.x, nr.y, nr.width, nr.height); }\r
+ NcvRect32u operator()(const Rect& nr) const\r
+ {\r
+ NcvRect32u rect;\r
+ rect.x = nr.x;\r
+ rect.y = nr.y;\r
+ rect.width = nr.width;\r
+ rect.height = nr.height;\r
+ return rect;\r
+ }\r
};\r
\r
+\r
void groupRectangles(std::vector<NcvRect32u> &hypotheses, int groupThreshold, double eps, std::vector<Ncv32u> *weights)\r
{\r
- vector<Rect> rects(hypotheses.size()); \r
- std::transform(hypotheses.begin(), hypotheses.end(), rects.begin(), RectConvert());\r
- \r
- if (weights) \r
- {\r
- vector<int> weights_int;\r
- weights_int.assign(weights->begin(), weights->end()); \r
- cv::groupRectangles(rects, weights_int, groupThreshold, eps);\r
- }\r
- else\r
- { \r
- cv::groupRectangles(rects, groupThreshold, eps);\r
- }\r
- std::transform(rects.begin(), rects.end(), hypotheses.begin(), RectConvert()); \r
- hypotheses.resize(rects.size());\r
+ vector<Rect> rects(hypotheses.size());\r
+ std::transform(hypotheses.begin(), hypotheses.end(), rects.begin(), RectConvert());\r
+\r
+ if (weights)\r
+ {\r
+ vector<int> weights_int;\r
+ weights_int.assign(weights->begin(), weights->end());\r
+ cv::groupRectangles(rects, weights_int, groupThreshold, eps);\r
+ }\r
+ else\r
+ {\r
+ cv::groupRectangles(rects, groupThreshold, eps);\r
+ }\r
+ std::transform(rects.begin(), rects.end(), hypotheses.begin(), RectConvert());\r
+ hypotheses.resize(rects.size());\r
}\r
\r
\r
#if 1 /* loadFromXML implementation switch */\r
\r
-NCVStatus loadFromXML(const std::string &filename, \r
- HaarClassifierCascadeDescriptor &haar, \r
- std::vector<HaarStage64> &haarStages, \r
- std::vector<HaarClassifierNode128> &haarClassifierNodes, \r
+NCVStatus loadFromXML(const std::string &filename,\r
+ HaarClassifierCascadeDescriptor &haar,\r
+ std::vector<HaarStage64> &haarStages,\r
+ std::vector<HaarClassifierNode128> &haarClassifierNodes,\r
std::vector<HaarFeature64> &haarFeatures)\r
{\r
NCVStatus ncvStat;\r
haarStages.resize(0);\r
haarClassifierNodes.resize(0);\r
haarFeatures.resize(0);\r
- \r
+\r
Ptr<CvHaarClassifierCascade> oldCascade = (CvHaarClassifierCascade*)cvLoad(filename.c_str(), 0, 0, 0);\r
if (oldCascade.empty())\r
+ {\r
return NCV_HAAR_XML_LOADING_EXCEPTION;\r
-\r
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
+ }\r
\r
haar.ClassifierSize.width = oldCascade->orig_window_size.width;\r
haar.ClassifierSize.height = oldCascade->orig_window_size.height;\r
\r
HaarClassifierNodeDescriptor32 nodeLeft;\r
if ( tree->left[n] <= 0 )\r
- { \r
+ {\r
Ncv32f leftVal = tree->alpha[-tree->left[n]];\r
ncvStat = nodeLeft.create(leftVal);\r
ncvAssertReturn(ncvStat == NCV_SUCCESS, ncvStat);\r
bIsLeftNodeLeaf = true;\r
}\r
else\r
- { \r
+ {\r
Ncv32u leftNodeOffset = tree->left[n];\r
nodeLeft.create((Ncv32u)(h_TmpClassifierNotRootNodes.size() + leftNodeOffset - 1));\r
haar.bHasStumpsOnly = false;\r
\r
Ncv32u featureId = 0;\r
for(int l = 0; l < CV_HAAR_FEATURE_MAX; ++l) //by rects\r
- { \r
- Ncv32u rectX = feature->rect[l].r.x; \r
+ {\r
+ Ncv32u rectX = feature->rect[l].r.x;\r
Ncv32u rectY = feature->rect[l].r.y;\r
Ncv32u rectWidth = feature->rect[l].r.width;\r
Ncv32u rectHeight = feature->rect[l].r.height;\r
\r
HaarFeatureDescriptor32 tmpFeatureDesc;\r
ncvStat = tmpFeatureDesc.create(haar.bNeedsTiltedII, bIsLeftNodeLeaf, bIsRightNodeLeaf,\r
- featureId, haarFeatures.size() - featureId);\r
+ featureId, haarFeatures.size() - featureId);\r
ncvAssertReturn(NCV_SUCCESS == ncvStat, ncvStat);\r
curNode.setFeatureDesc(tmpFeatureDesc);\r
\r
haarStages.push_back(curStage);\r
}\r
\r
-///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\r
-\r
//fill in cascade stats\r
haar.NumStages = haarStages.size();\r
haar.NumClassifierRootNodes = haarClassifierNodes.size();\r
}\r
haarClassifierNodes[i].setRightNodeDesc(nodeRight);\r
}\r
+\r
for (Ncv32u i=0; i<h_TmpClassifierNotRootNodes.size(); i++)\r
{\r
HaarFeatureDescriptor32 featureDesc = h_TmpClassifierNotRootNodes[i].getFeatureDesc();\r
return NCV_SUCCESS;\r
}\r
\r
-////\r
-\r
#else /* loadFromXML implementation switch */\r
\r
#include "e:/devNPP-OpenCV/src/external/_rapidxml-1.13/rapidxml.hpp"\r
#endif /* loadFromXML implementation switch */\r
\r
#endif /* HAVE_CUDA */\r
-\r
-\r
// WARNING: this sample is under construction! Use it on your own risk.\r
+#pragma warning(disable : 4100)\r
\r
+#include "cvconfig.h"\r
+#include <iostream>\r
+#include <iomanip>\r
#include <opencv2/contrib/contrib.hpp>\r
#include <opencv2/objdetect/objdetect.hpp>\r
#include <opencv2/highgui/highgui.hpp>\r
#include <opencv2/imgproc/imgproc.hpp>\r
#include <opencv2/gpu/gpu.hpp>\r
\r
-#include <iostream>\r
-#include <iomanip>\r
-\r
using namespace std;\r
using namespace cv;\r
using namespace cv::gpu;\r
\r
\r
+#if !defined(HAVE_CUDA)\r
+int main(int argc, const char **argv)\r
+{\r
+ cout << "Please compile the library with CUDA support" << endl;\r
+ return -1;\r
+}\r
+#else\r
+\r
+\r
void help()\r
{\r
cout << "Usage: ./cascadeclassifier <cascade_file> <image_or_video_or_cameraid>\n"\r
}\r
\r
\r
-void DetectAndDraw(Mat& img, CascadeClassifier_GPU& cascade);\r
-\r
-\r
-String cascadeName = "../../data/haarcascades/haarcascade_frontalface_alt.xml";\r
-String nestedCascadeName = "../../data/haarcascades/haarcascade_eye_tree_eyeglasses.xml";\r
-\r
-\r
-template<class T> void convertAndResize(const T& src, T& gray, T& resized, double scale)\r
+template<class T>\r
+void convertAndResize(const T& src, T& gray, T& resized, double scale)\r
{\r
if (src.channels() == 3)\r
{\r
\r
void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const ostringstream &ss)\r
{\r
- int fontFace = FONT_HERSHEY_PLAIN;\r
- double fontScale = 1.5;\r
+ int fontFace = FONT_HERSHEY_DUPLEX;\r
+ double fontScale = 0.8;\r
int fontThickness = 2;\r
Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);\r
\r
Point org;\r
org.x = 1;\r
org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;\r
- putText(img, ss.str(), org, fontFace, fontScale, fontColor, fontThickness);\r
+ putText(img, ss.str(), org, fontFace, fontScale, CV_RGB(0,0,0), 5*fontThickness/2, 16);\r
+ putText(img, ss.str(), org, fontFace, fontScale, fontColor, fontThickness, 16);\r
}\r
\r
\r
Scalar fontColorNV = CV_RGB(118,185,0);\r
\r
ostringstream ss;\r
+ ss << "FPS = " << setprecision(1) << fixed << fps;\r
+ matPrint(canvas, 0, fontColorRed, ss);\r
+ ss.str("");\r
ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<\r
(bGpu ? "GPU, " : "CPU, ") <<\r
(bLargestFace ? "OneFace, " : "MultiFace, ") <<\r
- (bFilter ? "Filter:ON, " : "Filter:OFF, ") <<\r
- "FPS = " << setprecision(1) << fixed << fps;\r
-\r
- matPrint(canvas, 0, fontColorRed, ss);\r
+ (bFilter ? "Filter:ON" : "Filter:OFF");\r
+ matPrint(canvas, 1, fontColorRed, ss);\r
\r
if (bHelp)\r
{\r
- matPrint(canvas, 1, fontColorNV, ostringstream("Space - switch GPU / CPU"));\r
- matPrint(canvas, 2, fontColorNV, ostringstream("M - switch OneFace / MultiFace"));\r
- matPrint(canvas, 3, fontColorNV, ostringstream("F - toggle rectangles Filter (only in MultiFace)"));\r
- matPrint(canvas, 4, fontColorNV, ostringstream("H - toggle hotkeys help"));\r
- matPrint(canvas, 5, fontColorNV, ostringstream("1/Q - increase/decrease scale"));\r
+ matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));\r
+ matPrint(canvas, 3, fontColorNV, ostringstream("M - switch OneFace / MultiFace"));\r
+ matPrint(canvas, 4, fontColorNV, ostringstream("F - toggle rectangles Filter"));\r
+ matPrint(canvas, 5, fontColorNV, ostringstream("H - toggle hotkeys help"));\r
+ matPrint(canvas, 6, fontColorNV, ostringstream("1/Q - increase/decrease scale"));\r
}\r
else\r
{\r
- matPrint(canvas, 1, fontColorNV, ostringstream("H - toggle hotkeys help"));\r
+ matPrint(canvas, 2, fontColorNV, ostringstream("H - toggle hotkeys help"));\r
}\r
}\r
\r
{\r
if (!capture.open(inputName))\r
{\r
- int camid = 0;\r
- sscanf(inputName.c_str(), "%d", &camid);\r
+ int camid = -1;\r
+ istringstream iss(inputName);\r
+ iss >> camid;\r
+\r
if (!capture.open(camid))\r
{\r
cout << "Can't open source" << endl;\r
cascade_gpu.visualizeInPlace = true;\r
cascade_gpu.findLargestObject = findLargestObject;\r
\r
- detections_num = cascade_gpu.detectMultiScale(resized_gpu, facesBuf_gpu, 1.2, filterRects ? 4 : 0);\r
+ detections_num = cascade_gpu.detectMultiScale(resized_gpu, facesBuf_gpu, 1.2,\r
+ (filterRects || findLargestObject) ? 4 : 0);\r
facesBuf_gpu.colRange(0, detections_num).download(faces_downloaded);\r
}\r
else\r
{\r
Size minSize = cascade_gpu.getClassifierSize();\r
- cascade_cpu.detectMultiScale(resized_cpu, facesBuf_cpu, 1.2, filterRects ? 4 : 0, (findLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0) | CV_HAAR_SCALE_IMAGE, minSize);\r
+ cascade_cpu.detectMultiScale(resized_cpu, facesBuf_cpu, 1.2,\r
+ (filterRects || findLargestObject) ? 4 : 0,\r
+ (findLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)\r
+ | CV_HAAR_SCALE_IMAGE,\r
+ minSize);\r
detections_num = (int)facesBuf_cpu.size();\r
}\r
\r
- if (!useGPU)\r
+ if (!useGPU && detections_num)\r
{\r
- if (detections_num)\r
+ for (int i = 0; i < detections_num; ++i)\r
{\r
- for (int i = 0; i < detections_num; ++i)\r
- {\r
- rectangle(resized_cpu, facesBuf_cpu[i], Scalar(255));\r
- }\r
+ rectangle(resized_cpu, facesBuf_cpu[i], Scalar(255));\r
}\r
}\r
\r
\r
return 0;\r
}\r
+\r
+#endif //!defined(HAVE_CUDA)\r
#pragma warning( disable : 4201 4408 4127 4100)\r
-#include <cstdio>\r
\r
#include "cvconfig.h"\r
-#if !defined(HAVE_CUDA)\r
- int main( int argc, const char** argv ) { return printf("Please compile the library with CUDA support."), -1; }\r
-#else\r
-\r
-#include <cuda_runtime.h>\r
-#include "opencv2/opencv.hpp"\r
+#include <iostream>\r
+#include <iomanip>\r
+#include <opencv2/opencv.hpp>\r
+#include <opencv2/gpu/gpu.hpp>\r
#include "NCVHaarObjectDetection.hpp"\r
\r
+using namespace std;\r
using namespace cv;\r
\r
-const Size2i preferredVideoFrameSize(640, 480);\r
\r
-std::string preferredClassifier = "haarcascade_frontalface_alt.xml";\r
-std::string wndTitle = "NVIDIA Computer Vision SDK :: Face Detection in Video Feed";\r
-\r
-\r
-void printSyntax(void)\r
+#if !defined(HAVE_CUDA)\r
+int main( int argc, const char** argv )\r
{\r
- printf("Syntax: FaceDetectionFeed.exe [-c cameranum | -v filename] classifier.xml\n");\r
+ cout << "Please compile the library with CUDA support" << endl;\r
+ return -1;\r
}\r
+#else\r
\r
-void imagePrintf(Mat& img, int lineOffsY, Scalar color, const char *format, ...)\r
-{ \r
- int fontFace = CV_FONT_HERSHEY_PLAIN;\r
- double fontScale = 1; \r
- \r
- int baseline;\r
- Size textSize = cv::getTextSize("T", fontFace, fontScale, 1, &baseline);\r
\r
- va_list arg_ptr;\r
- va_start(arg_ptr, format);\r
+const Size2i preferredVideoFrameSize(640, 480);\r
+const string wndTitle = "NVIDIA Computer Vision :: Haar Classifiers Cascade";\r
\r
- char strBuf[4096];\r
- vsprintf(&strBuf[0], format, arg_ptr);\r
\r
- Point org(1, 3 * textSize.height * (lineOffsY + 1) / 2); \r
- putText(img, &strBuf[0], org, fontFace, fontScale, color);\r
- va_end(arg_ptr); \r
+void matPrint(Mat &img, int lineOffsY, Scalar fontColor, const ostringstream &ss)\r
+{\r
+ int fontFace = FONT_HERSHEY_DUPLEX;\r
+ double fontScale = 0.8;\r
+ int fontThickness = 2;\r
+ Size fontSize = cv::getTextSize("T[]", fontFace, fontScale, fontThickness, 0);\r
+\r
+ Point org;\r
+ org.x = 1;\r
+ org.y = 3 * fontSize.height * (lineOffsY + 1) / 2;\r
+ putText(img, ss.str(), org, fontFace, fontScale, CV_RGB(0,0,0), 5*fontThickness/2, 16);\r
+ putText(img, ss.str(), org, fontFace, fontScale, fontColor, fontThickness, 16);\r
}\r
\r
+\r
+void displayState(Mat &canvas, bool bHelp, bool bGpu, bool bLargestFace, bool bFilter, double fps)\r
+{\r
+ Scalar fontColorRed = CV_RGB(255,0,0);\r
+ Scalar fontColorNV = CV_RGB(118,185,0);\r
+\r
+ ostringstream ss;\r
+ ss << "FPS = " << setprecision(1) << fixed << fps;\r
+ matPrint(canvas, 0, fontColorRed, ss);\r
+ ss.str("");\r
+ ss << "[" << canvas.cols << "x" << canvas.rows << "], " <<\r
+ (bGpu ? "GPU, " : "CPU, ") <<\r
+ (bLargestFace ? "OneFace, " : "MultiFace, ") <<\r
+ (bFilter ? "Filter:ON" : "Filter:OFF");\r
+ matPrint(canvas, 1, fontColorRed, ss);\r
+\r
+ if (bHelp)\r
+ {\r
+ matPrint(canvas, 2, fontColorNV, ostringstream("Space - switch GPU / CPU"));\r
+ matPrint(canvas, 3, fontColorNV, ostringstream("M - switch OneFace / MultiFace"));\r
+ matPrint(canvas, 4, fontColorNV, ostringstream("F - toggle rectangles Filter"));\r
+ matPrint(canvas, 5, fontColorNV, ostringstream("H - toggle hotkeys help"));\r
+ }\r
+ else\r
+ {\r
+ matPrint(canvas, 2, fontColorNV, ostringstream("H - toggle hotkeys help"));\r
+ }\r
+}\r
+\r
+\r
NCVStatus process(Mat *srcdst,\r
Ncv32u width, Ncv32u height,\r
- NcvBool bShowAllHypotheses, NcvBool bLargestFace,\r
+ NcvBool bFilterRects, NcvBool bLargestFace,\r
HaarClassifierCascadeDescriptor &haar,\r
NCVVector<HaarStage64> &d_haarStages, NCVVector<HaarClassifierNode128> &d_haarNodes,\r
NCVVector<HaarFeature64> &d_haarFeatures, NCVVector<HaarStage64> &h_haarStages,\r
d_src, roi, d_rects, numDetections, haar, h_haarStages,\r
d_haarStages, d_haarNodes, d_haarFeatures,\r
haar.ClassifierSize,\r
- bShowAllHypotheses ? 0 : 4,\r
+ (bFilterRects || bLargestFace) ? 4 : 0,\r
1.2f, 1,\r
(bLargestFace ? NCVPipeObjDet_FindLargestObject : 0)\r
| NCVPipeObjDet_VisualizeInPlace,\r
return NCV_SUCCESS;\r
}\r
\r
-int main( int argc, const char** argv )\r
+\r
+int main(int argc, const char** argv)\r
{\r
- NCVStatus ncvStat;\r
+ cout << "OpenCV / NVIDIA Computer Vision" << endl;\r
+ cout << "Face Detection in video and live feed" << endl;\r
+ cout << "Syntax: exename <cascade_file> <image_or_video_or_cameraid>" << endl;\r
+ cout << "=========================================" << endl;\r
\r
- printf("NVIDIA Computer Vision SDK\n");\r
- printf("Face Detection in video and live feed\n");\r
- printf("=========================================\n");\r
- printf(" Esc - Quit\n");\r
- printf(" Space - Switch between NCV and OpenCV\n");\r
- printf(" L - Switch between FullSearch and LargestFace modes\n");\r
- printf(" U - Toggle unfiltered hypotheses visualization in FullSearch\n");\r
- \r
- VideoCapture capture; \r
- bool bQuit = false;\r
+ ncvAssertPrintReturn(cv::gpu::getCudaEnabledDeviceCount() != 0, "No GPU found or the library is compiled without GPU support", -1);\r
+ ncvAssertPrintReturn(argc == 3, "Invalid number of arguments", -1);\r
\r
- Size2i frameSize;\r
+ string cascadeName = argv[1];\r
+ string inputName = argv[2];\r
\r
- if (argc != 4 && argc != 1)\r
- {\r
- printSyntax();\r
- return -1;\r
- }\r
+ NCVStatus ncvStat;\r
+ NcvBool bQuit = false;\r
+ VideoCapture capture;\r
+ Size2i frameSize;\r
\r
- if (argc == 1 || strcmp(argv[1], "-c") == 0)\r
+ //open content source\r
+ Mat image = imread(inputName);\r
+ Mat frame;\r
+ if (!image.empty())\r
{\r
- // Camera input is specified\r
- int camIdx = (argc == 3) ? atoi(argv[2]) : 0;\r
- if(!capture.open(camIdx)) \r
- return printf("Error opening camera\n"), -1; \r
- \r
- capture.set(CV_CAP_PROP_FRAME_WIDTH, preferredVideoFrameSize.width);\r
- capture.set(CV_CAP_PROP_FRAME_HEIGHT, preferredVideoFrameSize.height);\r
- capture.set(CV_CAP_PROP_FPS, 25);\r
- frameSize = preferredVideoFrameSize;\r
+ frameSize.width = image.cols;\r
+ frameSize.height = image.rows;\r
}\r
- else if (strcmp(argv[1], "-v") == 0)\r
+ else\r
{\r
- // Video file input (avi)\r
- if(!capture.open(argv[2]))\r
- return printf("Error opening video file\n"), -1;\r
+ if (!capture.open(inputName))\r
+ {\r
+ int camid = -1;\r
\r
- frameSize.width = (int)capture.get(CV_CAP_PROP_FRAME_WIDTH);\r
- frameSize.height = (int)capture.get(CV_CAP_PROP_FRAME_HEIGHT);\r
- }\r
- else\r
- return printSyntax(), -1;\r
+ istringstream ss(inputName);\r
+ int x = 0;\r
+ ss >> x;\r
\r
- NcvBool bUseOpenCV = true;\r
- NcvBool bLargestFace = false; //LargestFace=true is used usually during training\r
- NcvBool bShowAllHypotheses = false;\r
+ ncvAssertPrintReturn(capture.open(camid) != 0, "Can't open source", -1);\r
+ }\r
\r
- CascadeClassifier classifierOpenCV;\r
- std::string classifierFile;\r
- if (argc == 1)\r
- {\r
- classifierFile = preferredClassifier;\r
- }\r
- else\r
- {\r
- classifierFile.assign(argv[3]);\r
- }\r
+ capture >> frame;\r
+ ncvAssertPrintReturn(!frame.empty(), "Empty video source", -1);\r
\r
- if (!classifierOpenCV.load(classifierFile))\r
- {\r
- printf("Error (in OpenCV) opening classifier\n");\r
- printSyntax();\r
- return -1;\r
+ frameSize.width = frame.cols;\r
+ frameSize.height = frame.rows;\r
}\r
\r
+ NcvBool bUseGPU = true;\r
+ NcvBool bLargestObject = false;\r
+ NcvBool bFilterRects = true;\r
+ NcvBool bHelpScreen = false;\r
+\r
+ CascadeClassifier classifierOpenCV;\r
+ ncvAssertPrintReturn(classifierOpenCV.load(cascadeName) != 0, "Error (in OpenCV) opening classifier", -1);\r
+\r
int devId;\r
ncvAssertCUDAReturn(cudaGetDevice(&devId), -1);\r
cudaDeviceProp devProp;\r
ncvAssertCUDAReturn(cudaGetDeviceProperties(&devProp, devId), -1);\r
- printf("Using GPU %d %s, arch=%d.%d\n", devId, devProp.name, devProp.major, devProp.minor);\r
+ cout << "Using GPU: " << devId << "(" << devProp.name <<\r
+ "), arch=" << devProp.major << "." << devProp.minor << endl;\r
\r
//==============================================================================\r
//\r
ncvAssertPrintReturn(cpuCascadeAllocator.isInitialized(), "Error creating cascade CPU allocator", -1);\r
\r
Ncv32u haarNumStages, haarNumNodes, haarNumFeatures;\r
- ncvStat = ncvHaarGetClassifierSize(classifierFile, haarNumStages, haarNumNodes, haarNumFeatures);\r
+ ncvStat = ncvHaarGetClassifierSize(cascadeName, haarNumStages, haarNumNodes, haarNumFeatures);\r
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error reading classifier size (check the file)", -1);\r
\r
NCVVectorAlloc<HaarStage64> h_haarStages(cpuCascadeAllocator, haarNumStages);\r
ncvAssertPrintReturn(h_haarFeatures.isMemAllocated(), "Error in cascade CPU allocator", -1);\r
\r
HaarClassifierCascadeDescriptor haar;\r
- ncvStat = ncvHaarLoadFromFile_host(classifierFile, haar, h_haarStages, h_haarNodes, h_haarFeatures);\r
+ ncvStat = ncvHaarLoadFromFile_host(cascadeName, haar, h_haarStages, h_haarNodes, h_haarFeatures);\r
ncvAssertPrintReturn(ncvStat == NCV_SUCCESS, "Error loading classifier", -1);\r
\r
NCVVectorAlloc<HaarStage64> d_haarStages(gpuCascadeAllocator, haarNumStages);\r
//\r
//==============================================================================\r
\r
- namedWindow(wndTitle, 1);\r
- Mat frame, gray, frameDisp;\r
+ namedWindow(wndTitle, 1);\r
+ Mat gray, frameDisp;\r
\r
do\r
{\r
- // For camera and video file, capture the next image \r
- capture >> frame;\r
- if (frame.empty())\r
- break;\r
-\r
Mat gray;\r
- cvtColor(frame, gray, CV_BGR2GRAY);\r
+ cvtColor((image.empty() ? frame : image), gray, CV_BGR2GRAY);\r
\r
//\r
// process\r
//\r
\r
NcvSize32u minSize = haar.ClassifierSize;\r
- if (bLargestFace)\r
+ if (bLargestObject)\r
{\r
Ncv32u ratioX = preferredVideoFrameSize.width / minSize.width;\r
Ncv32u ratioY = preferredVideoFrameSize.height / minSize.height;\r
- Ncv32u ratioSmallest = std::min(ratioX, ratioY);\r
- ratioSmallest = std::max((Ncv32u)(ratioSmallest / 2.5f), (Ncv32u)1);\r
+ Ncv32u ratioSmallest = min(ratioX, ratioY);\r
+ ratioSmallest = max((Ncv32u)(ratioSmallest / 2.5f), (Ncv32u)1);\r
minSize.width *= ratioSmallest;\r
minSize.height *= ratioSmallest;\r
}\r
Ncv32f avgTime;\r
NcvTimer timer = ncvStartTimer();\r
\r
- if (!bUseOpenCV)\r
+ if (bUseGPU)\r
{\r
ncvStat = process(&gray, frameSize.width, frameSize.height,\r
- bShowAllHypotheses, bLargestFace, haar,\r
+ bFilterRects, bLargestObject, haar,\r
d_haarStages, d_haarNodes,\r
d_haarFeatures, h_haarStages,\r
gpuAllocator, cpuAllocator, devProp);\r
gray,\r
rectsOpenCV,\r
1.2f,\r
- bShowAllHypotheses && !bLargestFace ? 0 : 4,\r
- (bLargestFace ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)\r
+ bFilterRects ? 4 : 0,\r
+ (bLargestObject ? CV_HAAR_FIND_BIGGEST_OBJECT : 0)\r
| CV_HAAR_SCALE_IMAGE,\r
Size(minSize.width, minSize.height));\r
\r
avgTime = (Ncv32f)ncvEndQueryTimerMs(timer);\r
\r
cvtColor(gray, frameDisp, CV_GRAY2BGR);\r
+ displayState(frameDisp, bHelpScreen, bUseGPU, bLargestObject, bFilterRects, 1000.0f / avgTime);\r
+ imshow(wndTitle, frameDisp);\r
\r
- imagePrintf(frameDisp, 0, CV_RGB(255, 0,0), "Space - Switch NCV%s / OpenCV%s", bUseOpenCV?"":" (ON)", bUseOpenCV?" (ON)":"");\r
- imagePrintf(frameDisp, 1, CV_RGB(255, 0,0), "L - Switch FullSearch%s / LargestFace%s modes", bLargestFace?"":" (ON)", bLargestFace?" (ON)":"");\r
- imagePrintf(frameDisp, 2, CV_RGB(255, 0,0), "U - Toggle unfiltered hypotheses visualization in FullSearch %s", bShowAllHypotheses?"(ON)":"(OFF)");\r
- imagePrintf(frameDisp, 3, CV_RGB(118,185,0), " Running at %f FPS on %s", 1000.0f / avgTime, bUseOpenCV?"CPU":"GPU");\r
-\r
- cv::imshow(wndTitle, frameDisp);\r
-\r
+ //handle input\r
switch (cvWaitKey(3))\r
{\r
case ' ':\r
- bUseOpenCV = !bUseOpenCV;\r
+ bUseGPU = !bUseGPU;\r
+ break;\r
+ case 'm':\r
+ case 'M':\r
+ bLargestObject = !bLargestObject;\r
break;\r
- case 'L':\r
- case 'l':\r
- bLargestFace = !bLargestFace;\r
+ case 'f':\r
+ case 'F':\r
+ bFilterRects = !bFilterRects;\r
break;\r
- case 'U':\r
- case 'u':\r
- bShowAllHypotheses = !bShowAllHypotheses;\r
+ case 'h':\r
+ case 'H':\r
+ bHelpScreen = !bHelpScreen;\r
break;\r
case 27:\r
bQuit = true;\r
break;\r
}\r
\r
+ // For camera and video file, capture the next image\r
+ if (capture.isOpened())\r
+ {\r
+ capture >> frame;\r
+ if (frame.empty())\r
+ {\r
+ break;\r
+ }\r
+ }\r
} while (!bQuit);\r
\r
cvDestroyWindow(wndTitle.c_str());\r
return 0;\r
}\r
\r
-\r
-#endif\r
+#endif //!defined(HAVE_CUDA)\r