multithreading facedetector
authorKonstantin Matskevich <konstantin.matskevich@itseez.com>
Mon, 2 Dec 2013 07:15:46 +0000 (11:15 +0400)
committerKonstantin Matskevich <konstantin.matskevich@itseez.com>
Thu, 5 Dec 2013 05:47:36 +0000 (09:47 +0400)
samples/ocl/facedetect.cpp

index 7e760da..0f452b9 100644 (file)
 #include <iostream>
 #include <stdio.h>
 
-using namespace std;
-using namespace cv;
-#define LOOP_NUM 10
-
-///////////////////////////////////////detectfaces with multithreading////////////////////////////////////////////
-#define MAX_THREADS 8
-
-#if defined _WIN32|| defined _WIN64
-    #include <process.h>
-    #include <windows.h>
-    HANDLE handleThreads[MAX_THREADS];
-#endif
-
-#if defined __linux__ || defined __APPLE__
-    #include <pthread.h>
-    #include <vector>
+#if defined(_MSC_VER) && (_MSC_VER >= 1700)
+    # include <thread>
 #endif
 
+using namespace std;
 using namespace cv;
+#define LOOP_NUM 10
 
-#if defined _WIN32|| defined _WIN64
-    void detectFaces(void* str)
-#elif defined __linux__ || defined __APPLE__
-    void* detectFaces(void* str)
-#endif
-{
-    std::string fileName = *(std::string*)str;
-    ocl::OclCascadeClassifier cascade;
-    cascade.load("cv/cascadeandhog/cascades/haarcascade_frontalface_alt.xml" );//path to haarcascade_frontalface_alt.xml
-    Mat img = imread(fileName, CV_LOAD_IMAGE_COLOR);
-    if (img.empty())
-    {
-        std::cout << "cann't open file " + fileName <<std::endl;
-        return;
-    }
-
-    ocl::oclMat d_img;
-    d_img.upload(img);
-
-    std::vector<Rect> oclfaces;
-    cascade.detectMultiScale(d_img, oclfaces,  1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0));
-
-    for(int i = 0; i<oclfaces.size(); i++)
-        rectangle(img, Point(oclfaces[i].x, oclfaces[i].y), Point(oclfaces[i].x + oclfaces[i].width, oclfaces[i].y + oclfaces[i].height), Scalar( 0, 255, 255 ), 3);
-
-    imwrite("path to result-images location/filename", img);
-
-}
-
-class Thread
-{
-private:
-    Thread* thread;
-public:
-    Thread(int _idx, std::string _fileName);
-    virtual ~Thread()
-    {
-        delete(thread);
-    }
-     virtual void run()
-     {
-         thread->run();
-     }
-     int idx;
-     std::string fileName;
-protected:
-    Thread():thread(NULL){}
-};
-
-class Thread_Win : public Thread
-{
-private:
-    friend class Thread;
-    Thread_Win(){}
-public:
-    ~Thread_Win(){};
-    void run()
-    {
-#if defined _WIN32|| defined _WIN64
-        handleThreads[idx] = (HANDLE)_beginthread(detectFaces, 0, (void*)&fileName);
-        WaitForMultipleObjects(MAX_THREADS, handleThreads, TRUE, INFINITE);
-#endif
-    }
-};
-
-class Thread_Lin : public Thread
-{
- private:
-    friend class Thread;
-    Thread_Lin(){}
-public:
-    ~Thread_Lin(){};
-    void run()
-    {
-#if defined __linux__ || defined __APPLE__
-        pthread_t thread;
-        pthread_create(&thread, NULL, detectFaces, (void*)&fileName);
-        pthread_join  (thread, NULL);
-#endif
-    }
-};
-
-Thread::Thread(int _idx, std::string _fileName)
-{
-#if defined _WIN32|| defined _WIN64
-    thread = new Thread_Win();
-#endif
-#if defined __linux__ || defined __APPLE__
-    thread = new Thread_Lin();
-#endif
-    thread->idx = _idx;
-    thread->fileName = _fileName;
-}
-
-///////////////////////////simple-threading faces detecting///////////////////////////////
+///////////////////////////single-threading faces detecting///////////////////////////////
 
 const static Scalar colors[] =  { CV_RGB(0,0,255),
                                   CV_RGB(0,128,255),
@@ -134,7 +28,7 @@ const static Scalar colors[] =  { CV_RGB(0,0,255),
 
 int64 work_begin = 0;
 int64 work_end = 0;
-string outputName;
+string inputName, outputName, cascadeName;
 
 static void workBegin()
 {
@@ -170,35 +64,11 @@ static void Draw(Mat& img, vector<Rect>& faces, double scale);
 // Else if will return (total diff of each cpu and gpu rects covered pixels)/(total cpu rects covered pixels)
 double checkRectSimilarity(Size sz, vector<Rect>& cpu_rst, vector<Rect>& gpu_rst);
 
-int facedetect_one_thread(int argc, const char** argv )
+static int facedetect_one_thread(bool useCPU, double scale )
 {
-    const char* keys =
-        "{ h | help       | false       | print help message }"
-        "{ i | input      |             | specify input image }"
-        "{ t | template   | haarcascade_frontalface_alt.xml |"
-        " specify template file path }"
-        "{ c | scale      |   1.0       | scale image }"
-        "{ s | use_cpu    | false       | use cpu or gpu to process the image }"
-        "{ o | output     | facedetect_output.jpg  |"
-        " specify output image save path(only works when input is images) }";
-
-    CommandLineParser cmd(argc, argv, keys);
-    if (cmd.get<bool>("help"))
-    {
-        cout << "Usage : facedetect [options]" << endl;
-        cout << "Available options:" << endl;
-        cmd.printParams();
-        return EXIT_SUCCESS;
-    }
-
     CvCapture* capture = 0;
     Mat frame, frameCopy, image;
 
-    bool useCPU = cmd.get<bool>("s");
-    string inputName = cmd.get<string>("i");
-    outputName = cmd.get<string>("o");
-    string cascadeName = cmd.get<string>("t");
-    double scale = cmd.get<double>("c");
     ocl::OclCascadeClassifier cascade;
     CascadeClassifier  cpu_cascade;
 
@@ -288,32 +158,98 @@ int facedetect_one_thread(int argc, const char** argv )
     }
 
     cvDestroyWindow("result");
-    std::cout<< "simple-threading sample was finished" <<std::endl;
+    std::cout<< "single-threaded sample has finished" <<std::endl;
     return 0;
 }
 
-void facedetect_multithreading()
+///////////////////////////////////////detectfaces with multithreading////////////////////////////////////////////
+#if defined(_MSC_VER) && (_MSC_VER >= 1700)
+
+#define MAX_THREADS 10
+
+static void detectFaces(std::string fileName)
 {
-    std::vector<Thread*> threads;
-    for(int i = 0; i<MAX_THREADS; i++)
-        threads.push_back(new Thread(i, "cv/cascadeandhog/images/audrybt1.png") );//path to source picture
-    for(int i = 0; i<MAX_THREADS; i++)
-    {
-        threads[i]->run();
-    }
-    for(int i = 0; i<MAX_THREADS; i++)
+    ocl::OclCascadeClassifier cascade;
+    cascade.load(cascadeName);
+    Mat img = imread(fileName, CV_LOAD_IMAGE_COLOR);
+    if (img.empty())
     {
-        delete(threads[i]);
+        std::cout << "cann't open file " + fileName <<std::endl;
+        return;
     }
+
+    ocl::oclMat d_img;
+    d_img.upload(img);
+
+    std::vector<Rect> oclfaces;
+    cascade.detectMultiScale(d_img, oclfaces,  1.1, 3, 0|CV_HAAR_SCALE_IMAGE, Size(30, 30), Size(0, 0));
+
+    for(unsigned int i = 0; i<oclfaces.size(); i++)
+        rectangle(img, Point(oclfaces[i].x, oclfaces[i].y), Point(oclfaces[i].x + oclfaces[i].width, oclfaces[i].y + oclfaces[i].height), Scalar( 0, 255, 255 ), 3);
+
+    imwrite(std::to_string(_threadid) + outputName, img);
+
 }
 
+static void facedetect_multithreading(int nthreads)
+{
+    int thread_number = MAX_THREADS < nthreads ? MAX_THREADS : nthreads;
+    std::vector<std::thread> threads;
+    for(int i = 0; i<thread_number; i++)
+        threads.push_back(std::thread(detectFaces, inputName));
+    for(int i = 0; i<thread_number; i++)
+        threads[i].join();
+    for(int i = 0; i<thread_number; i++)
+        threads[i].~thread();
+}
+#endif
+
 int main( int argc, const char** argv )
 {
-    std::cout<<"multi-threading sample was running" <<std::endl;
-    facedetect_multithreading();
-    std::cout<<"multi-threading sample was finished" <<std::endl;
-    std::cout<<"simple-threading sample was running" <<std::endl;
-    return facedetect_one_thread(argc,argv);
+
+    const char* keys =
+        "{ h | help       | false       | print help message }"
+        "{ i | input      |             | specify input image }"
+        "{ t | template   | haarcascade_frontalface_alt.xml |"
+        " specify template file path }"
+        "{ c | scale      |   1.0       | scale image }"
+        "{ s | use_cpu    | false       | use cpu or gpu to process the image }"
+        "{ o | output     | facedetect_output.jpg  |"
+        " specify output image save path(only works when input is images) }"
+        "{ n | thread_num |      1      | set number of threads >= 1 }";
+
+    CommandLineParser cmd(argc, argv, keys);
+    if (cmd.get<bool>("help"))
+    {
+        cout << "Usage : facedetect [options]" << endl;
+        cout << "Available options:" << endl;
+        cmd.printParams();
+        return EXIT_SUCCESS;
+    }
+    bool useCPU = cmd.get<bool>("s");
+    inputName = cmd.get<string>("i");
+    outputName = cmd.get<string>("o");
+    cascadeName = cmd.get<string>("t");
+    double scale = cmd.get<double>("c");
+    int n = cmd.get<int>("n");
+
+    if(n > 1)
+    {
+#if defined(_MSC_VER) && (_MSC_VER >= 1700)
+            std::cout<<"multi-threaded sample is running" <<std::endl;
+            facedetect_multithreading(n);
+            std::cout<<"multi-threaded sample has finished" <<std::endl;
+            return 0;
+#else
+            std::cout << "std::thread is not supported, running a single-threaded version" << std::endl;
+#endif
+    }
+    if (n<0)
+        std::cout<<"incorrect number of threads:" << n << ", running a single-threaded version" <<std::endl;
+    else
+        std::cout<<"single-threaded sample is running" <<std::endl;
+    return facedetect_one_thread(useCPU, scale);
+
 }
 
 void detect( Mat& img, vector<Rect>& faces,