From 6f6e990988eb2cf41b05c9e89b435dec781df3d6 Mon Sep 17 00:00:00 2001 From: niko Date: Fri, 31 Aug 2012 14:08:52 +0800 Subject: [PATCH] use mutex provided by opencv itself add getoclcontext and getoclcommandqueue so that other opencl program can interactive with opencv ocl module correct haar test cases add face detection sample --- modules/ocl/include/opencv2/ocl/ocl.hpp | 5 +- modules/ocl/perf/test_haar.cpp | 228 ++++++++++++++----------------- modules/ocl/perf/utility.hpp | 6 +- modules/ocl/src/initialization.cpp | 14 +- modules/ocl/src/threadsafe.cpp | 83 ------------ modules/ocl/src/threadsafe.h | 92 ------------- modules/ocl/test/test_haar.cpp | 231 +++++++++++++------------------- samples/ocl/facedetect.cpp | 229 +++++++++++++++++++++++++++++++ 8 files changed, 438 insertions(+), 450 deletions(-) delete mode 100644 modules/ocl/src/threadsafe.cpp delete mode 100644 modules/ocl/src/threadsafe.h create mode 100644 samples/ocl/facedetect.cpp diff --git a/modules/ocl/include/opencv2/ocl/ocl.hpp b/modules/ocl/include/opencv2/ocl/ocl.hpp index 1a60a88..a86f373 100644 --- a/modules/ocl/include/opencv2/ocl/ocl.hpp +++ b/modules/ocl/include/opencv2/ocl/ocl.hpp @@ -88,7 +88,10 @@ namespace cv //CV_EXPORTS void getComputeCapability(cl_device_id device, int &major, int &minor); //optional function, if you want save opencl binary kernel to the file, set its path CV_EXPORTS void setBinpath(const char *path); - + //The two functions below are used to get opencl runtime so that opencv can interactive with + //other opencl program + CV_EXPORTS void* getoclContext(); + CV_EXPORTS void* getoclCommandQueue(); //////////////////////////////// Error handling //////////////////////// CV_EXPORTS void error(const char *error_string, const char *file, const int line, const char *func); diff --git a/modules/ocl/perf/test_haar.cpp b/modules/ocl/perf/test_haar.cpp index 45a7d41..b91d306 100644 --- a/modules/ocl/perf/test_haar.cpp +++ b/modules/ocl/perf/test_haar.cpp @@ -58,141 +58,113 @@ struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } } PARAM_TEST_CASE(HaarTestBase, int, int) { //std::vector oclinfo; - cv::ocl::OclCascadeClassifier cascade, nestedCascade; + cv::ocl::OclCascadeClassifier cascade, nestedCascade; cv::CascadeClassifier cpucascade, cpunestedCascade; -// Mat img; - - double scale; - int index; - - virtual void SetUp() - { - scale = 1.1; - -#if WIN32 - string cascadeName="E:\\opencvbuffer\\trunk\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; -#else - string cascadeName="../data/haarcascades/haarcascade_frontalface_alt.xml"; -#endif - - if( (!cascade.load( cascadeName )) || (!cpucascade.load(cascadeName))) - { - cout << "ERROR: Could not load classifier cascade" << endl; - cout << "Usage: facedetect [--cascade=]\n" - " [--nested-cascade[=nested_cascade_path]]\n" - " [--scale[=\n" - " [filename|camera_index]\n" << endl ; - - return; - } - //int devnums = getDevice(oclinfo); - //CV_Assert(devnums>0); - ////if you want to use undefault device, set it here - ////setDevice(oclinfo[0]); - //cv::ocl::setBinpath("E:\\"); - } + // Mat img; + + double scale; + int index; + + virtual void SetUp() + { + scale = 1.0; + index=0; + string cascadeName="../../../data/haarcascades/haarcascade_frontalface_alt.xml"; + + if( (!cascade.load( cascadeName )) || (!cpucascade.load(cascadeName))) + { + cout << "ERROR: Could not load classifier cascade" << endl; + cout << "Usage: facedetect [--cascade=]\n" + " [--scale[=\n" + " [filename|camera_index]\n" << endl ; + return; + } + //int devnums = getDevice(oclinfo); + //CV_Assert(devnums>0); + ////if you want to use undefault device, set it here + ////setDevice(oclinfo[0]); + //cv::ocl::setBinpath("E:\\"); + } }; ////////////////////////////////faceDetect///////////////////////////////////////////////// struct Haar : HaarTestBase {}; -TEST_P(Haar, FaceDetect) +TEST_F(Haar, FaceDetect) { - for(int index = 1;index < 2; index++) - { - Mat img; - char buff[256]; -#if WIN32 - sprintf(buff,"E:\\myDataBase\\%d.jpg",index); - img = imread( buff, 1 ); -#else - sprintf(buff,"%d.jpg",index); - img = imread( buff, 1 ); - std::cout << "Now test " << index << ".jpg" < faces; - - const static Scalar colors[] = { CV_RGB(0,0,255), - CV_RGB(0,128,255), - CV_RGB(0,255,255), - CV_RGB(0,255,0), - CV_RGB(255,128,0), - CV_RGB(255,255,0), - CV_RGB(255,0,0), - CV_RGB(255,0,255)} ; - - Mat gray, smallImg(cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); - MemStorage storage(cvCreateMemStorage(0)); - cvtColor( img, gray, CV_BGR2GRAY ); - resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); - equalizeHist( smallImg, smallImg ); - CvMat _image = smallImg; - - Mat tempimg(&_image, false); - - cv::ocl::oclMat image(tempimg); - CvSeq* _objects; - -#if 1 - for(int k= 0; k<10; k++) - { - t = (double)cvGetTickCount(); - _objects = cascade.oclHaarDetectObjects( image, storage, 1.1, - 2, 0 - |CV_HAAR_SCALE_IMAGE - , Size(30,30), Size(0, 0) ); - - t = (double)cvGetTickCount() - t ; - printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) ); - } - -#else - cpucascade.detectMultiScale( image, faces, 1.1, - 2, 0 - |CV_HAAR_SCALE_IMAGE - , Size(30,30), Size(0, 0) ); - -#endif - vector vecAvgComp; - Seq(_objects).copyTo(vecAvgComp); - faces.resize(vecAvgComp.size()); - std::transform(vecAvgComp.begin(), vecAvgComp.end(), faces.begin(), getRect()); - - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) - { - Mat smallImgROI; - vector nestedObjects; - Point center; - Scalar color = colors[i%8]; - int radius; - center.x = cvRound((r->x + r->width*0.5)*scale); - center.y = cvRound((r->y + r->height*0.5)*scale); - radius = cvRound((r->width + r->height)*0.25*scale); - circle( img, center, radius, color, 3, 8, 0 ); - } - -#if WIN32 - sprintf(buff,"E:\\result1\\%d.jpg",index); - imwrite(buff,img); -#else - sprintf(buff,"testdet_%d.jpg",index); - imwrite(buff,img); -#endif - } -} - - -//INSTANTIATE_TEST_CASE_P(HaarTestBase, Haar, Combine(Values(1), -// Values(1))); - + string imgName = "../../../samples/c/lena.jpg"; + Mat img = imread( imgName, 1 ); + + if(img.empty()) + { + std::cout << "Couldn't read test" << index <<".jpg" << std::endl; + return ; + } + + int i = 0; + double t = 0; + vector faces, oclfaces; + + const static Scalar colors[] = { CV_RGB(0,0,255), + CV_RGB(0,128,255), + CV_RGB(0,255,255), + CV_RGB(0,255,0), + CV_RGB(255,128,0), + CV_RGB(255,255,0), + CV_RGB(255,0,0), + CV_RGB(255,0,255)} ; + + Mat gray, smallImg(cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + MemStorage storage(cvCreateMemStorage(0)); + cvtColor( img, gray, CV_BGR2GRAY ); + resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + equalizeHist( smallImg, smallImg ); + + t = (double)cvGetTickCount(); + for(int k= 0; k vecAvgComp; + Seq(_objects).copyTo(vecAvgComp); + oclfaces.resize(vecAvgComp.size()); + std::transform(vecAvgComp.begin(), vecAvgComp.end(), oclfaces.begin(), getRect()); + + //for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + //{ + // Mat smallImgROI; + // Point center; + // Scalar color = colors[i%8]; + // int radius; + // center.x = cvRound((r->x + r->width*0.5)*scale); + // center.y = cvRound((r->y + r->height*0.5)*scale); + // radius = cvRound((r->width + r->height)*0.25*scale); + // circle( img, center, radius, color, 3, 8, 0 ); + //} + //namedWindow("result"); + //imshow("result",img); + //waitKey(0); + //destroyAllWindows(); +} #endif // HAVE_OPENCL diff --git a/modules/ocl/perf/utility.hpp b/modules/ocl/perf/utility.hpp index 8ab243a..8c14544 100644 --- a/modules/ocl/perf/utility.hpp +++ b/modules/ocl/perf/utility.hpp @@ -45,10 +45,10 @@ #ifdef PRINT_KERNEL_RUN_TIME #define LOOP_TIMES 1 #else -#define LOOP_TIMES 1 +#define LOOP_TIMES 100 #endif -#define MWIDTH 256 -#define MHEIGHT 256 +#define MWIDTH 1920 +#define MHEIGHT 1080 #define CLBINPATH ".\\" #define LOOPROISTART 0 #define LOOPROIEND 1 diff --git a/modules/ocl/src/initialization.cpp b/modules/ocl/src/initialization.cpp index 6d2eaf3..5075d30 100644 --- a/modules/ocl/src/initialization.cpp +++ b/modules/ocl/src/initialization.cpp @@ -44,7 +44,6 @@ //M*/ #include "precomp.hpp" -#include "threadsafe.h" #include #include "binarycaching.hpp" @@ -348,7 +347,14 @@ namespace cv } Context::setContext(oclinfo); } - + void* getoclContext() + { + return &(Context::getContext()->impl->clContext); + } + void* getoclCommandQueue() + { + return &(Context::getContext()->impl->clCmdQueue); + } void openCLReadBuffer(Context *clCxt, cl_mem dst_buffer, void *host_buffer, size_t size) { cl_int status; @@ -772,12 +778,12 @@ namespace cv /////////////////////////////OpenCL initialization///////////////// auto_ptr Context::clCxt; int Context::val = 0; - CriticalSection cs; + Mutex cs; Context *Context::getContext() { if(val == 0) { - myAutoLock al(&cs); + AutoLock al(cs); if( NULL == clCxt.get()) clCxt.reset(new Context); diff --git a/modules/ocl/src/threadsafe.cpp b/modules/ocl/src/threadsafe.cpp deleted file mode 100644 index 25b3773..0000000 --- a/modules/ocl/src/threadsafe.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// @Authors -// Niko Li, newlife20080214@gmail.com -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other oclMaterials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -//#include "precomp.hpp" -#include "threadsafe.h" - -CriticalSection::CriticalSection() -{ -#if defined WIN32 || defined _WIN32 - InitializeCriticalSection(&m_CritSec); -#else - pthread_mutex_init(&m_CritSec, NULL); -#endif -} - -CriticalSection::~CriticalSection() -{ -#if defined WIN32 || defined _WIN32 - DeleteCriticalSection(&m_CritSec); -#else - pthread_mutex_destroy(&m_CritSec); -#endif -} - -void CriticalSection::Lock() -{ -#if defined WIN32 || defined _WIN32 - EnterCriticalSection(&m_CritSec); -#else - pthread_mutex_lock(&m_CritSec); -#endif -} - -void CriticalSection::Unlock() -{ -#if defined WIN32 || defined _WIN32 - LeaveCriticalSection(&m_CritSec); -#else - pthread_mutex_unlock(&m_CritSec); -#endif -} diff --git a/modules/ocl/src/threadsafe.h b/modules/ocl/src/threadsafe.h deleted file mode 100644 index 5905a55..0000000 --- a/modules/ocl/src/threadsafe.h +++ /dev/null @@ -1,92 +0,0 @@ -/*M/////////////////////////////////////////////////////////////////////////////////////// -// -// IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING. -// -// By downloading, copying, installing or using the software you agree to this license. -// If you do not agree to this license, do not download, install, -// copy or use the software. -// -// -// License Agreement -// For Open Source Computer Vision Library -// -// Copyright (C) 2010-2012, Institute Of Software Chinese Academy Of Science, all rights reserved. -// Copyright (C) 2010-2012, Advanced Micro Devices, Inc., all rights reserved. -// Third party copyrights are property of their respective owners. -// -// -// Redistribution and use in source and binary forms, with or without modification, -// are permitted provided that the following conditions are met: -// -// * Redistribution's of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// * Redistribution's in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other GpuMaterials provided with the distribution. -// -// * The name of the copyright holders may not be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// This software is provided by the copyright holders and contributors "as is" and -// any express or implied warranties, including, but not limited to, the implied -// warranties of merchantability and fitness for a particular purpose are disclaimed. -// In no event shall the Intel Corporation or contributors be liable for any direct, -// indirect, incidental, special, exemplary, or consequential damages -// (including, but not limited to, procurement of substitute goods or services; -// loss of use, data, or profits; or business interruption) however caused -// and on any theory of liability, whether in contract, strict liability, -// or tort (including negligence or otherwise) arising in any way out of -// the use of this software, even if advised of the possibility of such damage. -// -//M*/ - -#if defined WIN32 || defined _WIN32 -#include -#undef min -#undef max -#else -#include -#endif - -class CriticalSection -{ -public: - CriticalSection(); - ~CriticalSection(); - // Jia Haipeng, jiahaipeng95@gmail.com - void Lock(); - void Unlock(); -protected: -#if defined WIN32 || defined _WIN32 - CRITICAL_SECTION m_CritSec; -#else - pthread_mutex_t m_CritSec; -#endif -}; - -class myAutoLock -{ -public: - explicit myAutoLock(CriticalSection *lock) - { - m_lock = lock; - m_lock->Lock(); - }; - ~myAutoLock() - { - m_lock->Unlock(); - }; -protected: - CriticalSection *m_lock; -}; - - - - - - - - - - diff --git a/modules/ocl/test/test_haar.cpp b/modules/ocl/test/test_haar.cpp index 5499fcd..59faffe 100644 --- a/modules/ocl/test/test_haar.cpp +++ b/modules/ocl/test/test_haar.cpp @@ -53,154 +53,107 @@ using namespace testing; using namespace std; using namespace cv; -struct getRect -{ - Rect operator ()(const CvAvgComp &e) const - { - return e.rect; - } -}; +struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } }; PARAM_TEST_CASE(HaarTestBase, int, int) { //std::vector oclinfo; - cv::ocl::OclCascadeClassifier cascade, nestedCascade; - cv::CascadeClassifier cpucascade, cpunestedCascade; - // Mat img; - - double scale; - int index; - - virtual void SetUp() - { - scale = 1.1; - -#if WIN32 - string cascadeName = "E:\\opencvbuffer\\trunk\\data\\haarcascades\\haarcascade_frontalface_alt.xml"; -#else - string cascadeName = "../data/haarcascades/haarcascade_frontalface_alt.xml"; -#endif - - if( (!cascade.load( cascadeName )) || (!cpucascade.load(cascadeName))) - { - cout << "ERROR: Could not load classifier cascade" << endl; - cout << "Usage: facedetect [--cascade=]\n" - " [--nested-cascade[=nested_cascade_path]]\n" - " [--scale[=\n" - " [filename|camera_index]\n" << endl ; - - return; - } - //int devnums = getDevice(oclinfo, OPENCV_DEFAULT_OPENCL_DEVICE); - //CV_Assert(devnums > 0); - ////if you want to use undefault device, set it here - ////setDevice(oclinfo[0]); - //cv::ocl::setBinpath("E:\\"); - } + cv::ocl::OclCascadeClassifier cascade, nestedCascade; + cv::CascadeClassifier cpucascade, cpunestedCascade; + // Mat img; + + double scale; + int index; + + virtual void SetUp() + { + scale = 1.0; + index=0; + string cascadeName="../../../data/haarcascades/haarcascade_frontalface_alt.xml"; + + if( (!cascade.load( cascadeName )) || (!cpucascade.load(cascadeName))) + { + cout << "ERROR: Could not load classifier cascade" << endl; + cout << "Usage: facedetect [--cascade=]\n" + " [--scale[=\n" + " [filename|camera_index]\n" << endl ; + return; + } + //int devnums = getDevice(oclinfo); + //CV_Assert(devnums>0); + ////if you want to use undefault device, set it here + ////setDevice(oclinfo[0]); + //cv::ocl::setBinpath("E:\\"); + } }; ////////////////////////////////faceDetect///////////////////////////////////////////////// struct Haar : HaarTestBase {}; -TEST_P(Haar, FaceDetect) -{ - - for(int index = 1; index < 2; index++) - { - Mat img; - char buff[256]; -#if WIN32 - sprintf(buff, "E:\\myDataBase\\%d.jpg", index); - img = imread( buff, 1 ); -#else - sprintf(buff, "%d.jpg", index); - img = imread( buff, 1 ); - std::cout << "Now test " << index << ".jpg" << std::endl; -#endif - if(img.empty()) - { - std::cout << "Couldn't read test" << index << ".jpg" << std::endl; - continue; - } - - int i = 0; - double t = 0; - vector faces; - - const static Scalar colors[] = { CV_RGB(0, 0, 255), - CV_RGB(0, 128, 255), - CV_RGB(0, 255, 255), - CV_RGB(0, 255, 0), - CV_RGB(255, 128, 0), - CV_RGB(255, 255, 0), - CV_RGB(255, 0, 0), - CV_RGB(255, 0, 255) - } ; - - Mat gray, smallImg(cvRound (img.rows / scale), cvRound(img.cols / scale), CV_8UC1 ); - MemStorage storage(cvCreateMemStorage(0)); - cvtColor( img, gray, CV_BGR2GRAY ); - resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); - equalizeHist( smallImg, smallImg ); - CvMat _image = smallImg; - - Mat tempimg(&_image, false); - - cv::ocl::oclMat image(tempimg); - CvSeq *_objects; - -#if 1 - for(int k = 0; k < 10; k++) - { - t = (double)cvGetTickCount(); - _objects = cascade.oclHaarDetectObjects( image, storage, 1.1, - 2, 0 - | CV_HAAR_SCALE_IMAGE - , Size(30, 30), Size(0, 0) ); - - t = (double)cvGetTickCount() - t ; - printf( "detection time = %g ms\n", t / ((double)cvGetTickFrequency() * 1000.) ); - } - -#else - cpucascade.detectMultiScale( image, faces, 1.1, - 2, 0 - | CV_HAAR_SCALE_IMAGE - , Size(30, 30), Size(0, 0) ); - -#endif - vector vecAvgComp; - Seq(_objects).copyTo(vecAvgComp); - faces.resize(vecAvgComp.size()); - std::transform(vecAvgComp.begin(), vecAvgComp.end(), faces.begin(), getRect()); - - for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) - { - Mat smallImgROI; - vector nestedObjects; - Point center; - Scalar color = colors[i%8]; - int radius; - center.x = cvRound((r->x + r->width * 0.5) * scale); - center.y = cvRound((r->y + r->height * 0.5) * scale); - radius = cvRound((r->width + r->height) * 0.25 * scale); - circle( img, center, radius, color, 3, 8, 0 ); - } - -#if WIN32 - sprintf(buff, "E:\\result1\\%d.jpg", index); - imwrite(buff, img); -#else - sprintf(buff, "testdet_%d.jpg", index); - imwrite(buff, img); -#endif - } -} - - -//INSTANTIATE_TEST_CASE_P(HaarTestBase, Haar, Combine(Values(1), - // Values(1))); - +TEST_F(Haar, FaceDetect) +{ + string imgName = "../../../samples/c/lena.jpg"; + Mat img = imread( imgName, 1 ); + + if(img.empty()) + { + std::cout << "Couldn't read test" << index <<".jpg" << std::endl; + return ; + } + + int i = 0; + double t = 0; + vector faces, oclfaces; + + const static Scalar colors[] = { CV_RGB(0,0,255), + CV_RGB(0,128,255), + CV_RGB(0,255,255), + CV_RGB(0,255,0), + CV_RGB(255,128,0), + CV_RGB(255,255,0), + CV_RGB(255,0,0), + CV_RGB(255,0,255)} ; + + Mat gray, smallImg(cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + MemStorage storage(cvCreateMemStorage(0)); + cvtColor( img, gray, CV_BGR2GRAY ); + resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + equalizeHist( smallImg, smallImg ); + + + cv::ocl::oclMat image; + CvSeq* _objects; + image.upload(smallImg); + _objects = cascade.oclHaarDetectObjects( image, storage, 1.1, + 3, 0 + |CV_HAAR_SCALE_IMAGE + , Size(30,30), Size(0, 0) ); + vector vecAvgComp; + Seq(_objects).copyTo(vecAvgComp); + oclfaces.resize(vecAvgComp.size()); + std::transform(vecAvgComp.begin(), vecAvgComp.end(), oclfaces.begin(), getRect()); + + cpucascade.detectMultiScale( smallImg, faces, 1.1, + 3, 0 + |CV_HAAR_SCALE_IMAGE + , Size(30,30), Size(0, 0) ); + EXPECT_EQ(faces.size(),oclfaces.size()); + /* for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + { + Mat smallImgROI; + Point center; + Scalar color = colors[i%8]; + int radius; + center.x = cvRound((r->x + r->width*0.5)*scale); + center.y = cvRound((r->y + r->height*0.5)*scale); + radius = cvRound((r->width + r->height)*0.25*scale); + circle( img, center, radius, color, 3, 8, 0 ); + } */ + //namedWindow("result"); + //imshow("result",img); + //waitKey(0); + //destroyAllWindows(); +} #endif // HAVE_OPENCL diff --git a/samples/ocl/facedetect.cpp b/samples/ocl/facedetect.cpp new file mode 100644 index 0000000..6a35be7 --- /dev/null +++ b/samples/ocl/facedetect.cpp @@ -0,0 +1,229 @@ +//This sample is inherited from facedetect.cpp in smaple/c + +#include "opencv2/objdetect/objdetect.hpp" +#include "opencv2/highgui/highgui.hpp" +#include "opencv2/imgproc/imgproc.hpp" +#include "opencv2/ocl/ocl.hpp" +#include +#include + +using namespace std; +using namespace cv; + +void help() +{ + cout << "\nThis program demonstrates the cascade recognizer.\n" + "This classifier can recognize many ~rigid objects, it's most known use is for faces.\n" + "Usage:\n" + "./facedetect [--cascade= this is the primary trained classifier such as frontal face]\n" + " [--scale=\n" + " [filename|camera_index]\n\n" + "see facedetect.cmd for one call:\n" + "./facedetect --cascade=\"../../data/haarcascades/haarcascade_frontalface_alt.xml\" --scale=1.3 \n" + "Hit any key to quit.\n" + "Using OpenCV version " << CV_VERSION << "\n" << endl; +} +struct getRect { Rect operator ()(const CvAvgComp& e) const { return e.rect; } }; +void detectAndDraw( Mat& img, + cv::ocl::OclCascadeClassifier& cascade, CascadeClassifier& nestedCascade, + double scale); + +String cascadeName = "../../../data/haarcascades/haarcascade_frontalface_alt.xml"; + +int main( int argc, const char** argv ) +{ + CvCapture* capture = 0; + Mat frame, frameCopy, image; + const String scaleOpt = "--scale="; + size_t scaleOptLen = scaleOpt.length(); + const String cascadeOpt = "--cascade="; + size_t cascadeOptLen = cascadeOpt.length(); + String inputName; + + help(); + cv::ocl::OclCascadeClassifier cascade; + CascadeClassifier nestedCascade; + double scale = 1; + + for( int i = 1; i < argc; i++ ) + { + cout << "Processing " << i << " " << argv[i] << endl; + if( cascadeOpt.compare( 0, cascadeOptLen, argv[i], cascadeOptLen ) == 0 ) + { + cascadeName.assign( argv[i] + cascadeOptLen ); + cout << " from which we have cascadeName= " << cascadeName << endl; + } + else if( scaleOpt.compare( 0, scaleOptLen, argv[i], scaleOptLen ) == 0 ) + { + if( !sscanf( argv[i] + scaleOpt.length(), "%lf", &scale ) || scale < 1 ) + scale = 1; + cout << " from which we read scale = " << scale << endl; + } + else if( argv[i][0] == '-' ) + { + cerr << "WARNING: Unknown option %s" << argv[i] << endl; + } + else + inputName.assign( argv[i] ); + } + + if( !cascade.load( cascadeName ) ) + { + cerr << "ERROR: Could not load classifier cascade" << endl; + cerr << "Usage: facedetect [--cascade=]\n" + " [--scale[=\n" + " [filename|camera_index]\n" << endl ; + return -1; + } + + if( inputName.empty() || (isdigit(inputName.c_str()[0]) && inputName.c_str()[1] == '\0') ) + { + capture = cvCaptureFromCAM( inputName.empty() ? 0 : inputName.c_str()[0] - '0' ); + int c = inputName.empty() ? 0 : inputName.c_str()[0] - '0' ; + if(!capture) cout << "Capture from CAM " << c << " didn't work" << endl; + } + else if( inputName.size() ) + { + image = imread( inputName, 1 ); + if( image.empty() ) + { + capture = cvCaptureFromAVI( inputName.c_str() ); + if(!capture) cout << "Capture from AVI didn't work" << endl; + } + } + else + { + image = imread( "lena.jpg", 1 ); + if(image.empty()) cout << "Couldn't read lena.jpg" << endl; + } + + cvNamedWindow( "result", 1 ); + std::vector oclinfo; + int devnums = cv::ocl::getDevice(oclinfo); + if(devnums<1) + { + std::cout << "no device found\n"; + return -1; + } + //if you want to use undefault device, set it here + //setDevice(oclinfo[0]); + //setBinpath(CLBINPATH); + if( capture ) + { + cout << "In capture ..." << endl; + for(;;) + { + IplImage* iplImg = cvQueryFrame( capture ); + frame = iplImg; + if( frame.empty() ) + break; + if( iplImg->origin == IPL_ORIGIN_TL ) + frame.copyTo( frameCopy ); + else + flip( frame, frameCopy, 0 ); + + detectAndDraw( frameCopy, cascade, nestedCascade, scale ); + + if( waitKey( 10 ) >= 0 ) + goto _cleanup_; + } + + waitKey(0); + +_cleanup_: + cvReleaseCapture( &capture ); + } + else + { + cout << "In image read" << endl; + if( !image.empty() ) + { + detectAndDraw( image, cascade, nestedCascade, scale ); + waitKey(0); + } + else if( !inputName.empty() ) + { + /* assume it is a text file containing the + list of the image filenames to be processed - one per line */ + FILE* f = fopen( inputName.c_str(), "rt" ); + if( f ) + { + char buf[1000+1]; + while( fgets( buf, 1000, f ) ) + { + int len = (int)strlen(buf), c; + while( len > 0 && isspace(buf[len-1]) ) + len--; + buf[len] = '\0'; + cout << "file " << buf << endl; + image = imread( buf, 1 ); + if( !image.empty() ) + { + detectAndDraw( image, cascade, nestedCascade, scale ); + c = waitKey(0); + if( c == 27 || c == 'q' || c == 'Q' ) + break; + } + else + { + cerr << "Aw snap, couldn't read image " << buf << endl; + } + } + fclose(f); + } + } + } + + cvDestroyWindow("result"); + + return 0; +} + +void detectAndDraw( Mat& img, + cv::ocl::OclCascadeClassifier& cascade, CascadeClassifier& nestedCascade, + double scale) +{ + int i = 0; + double t = 0; + vector faces; + const static Scalar colors[] = { CV_RGB(0,0,255), + CV_RGB(0,128,255), + CV_RGB(0,255,255), + CV_RGB(0,255,0), + CV_RGB(255,128,0), + CV_RGB(255,255,0), + CV_RGB(255,0,0), + CV_RGB(255,0,255)} ; + cv::ocl::oclMat image(img); + cv::ocl::oclMat gray, smallImg( cvRound (img.rows/scale), cvRound(img.cols/scale), CV_8UC1 ); + + cv::ocl::cvtColor( image, gray, CV_BGR2GRAY ); + cv::ocl::resize( gray, smallImg, smallImg.size(), 0, 0, INTER_LINEAR ); + cv::ocl::equalizeHist( smallImg, smallImg ); + + CvSeq* _objects; + MemStorage storage(cvCreateMemStorage(0)); + t = (double)cvGetTickCount(); + _objects = cascade.oclHaarDetectObjects( smallImg, storage, 1.1, + 3, 0 + |CV_HAAR_SCALE_IMAGE + , Size(30,30), Size(0, 0) ); + vector vecAvgComp; + Seq(_objects).copyTo(vecAvgComp); + faces.resize(vecAvgComp.size()); + std::transform(vecAvgComp.begin(), vecAvgComp.end(), faces.begin(), getRect()); + t = (double)cvGetTickCount() - t; + printf( "detection time = %g ms\n", t/((double)cvGetTickFrequency()*1000.) ); + for( vector::const_iterator r = faces.begin(); r != faces.end(); r++, i++ ) + { + Mat smallImgROI; + Point center; + Scalar color = colors[i%8]; + int radius; + center.x = cvRound((r->x + r->width*0.5)*scale); + center.y = cvRound((r->y + r->height*0.5)*scale); + radius = cvRound((r->width + r->height)*0.25*scale); + circle( img, center, radius, color, 3, 8, 0 ); + } + cv::imshow( "result", img ); +} -- 2.7.4