|
|
|
@ -5,121 +5,15 @@ |
|
|
|
|
#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, |
|
|
|
|