Merge pull request #7552 from es0m:master

pull/7605/head
Vadim Pisarevsky 9 years ago
commit 050731c4d2
  1. 2
      modules/objdetect/include/opencv2/objdetect/detection_based_tracker.hpp
  2. 81
      modules/objdetect/src/detection_based_tracker.cpp
  3. 20
      samples/cpp/dbt_face_detection.cpp

@ -59,7 +59,7 @@ namespace cv
class CV_EXPORTS DetectionBasedTracker class CV_EXPORTS DetectionBasedTracker
{ {
public: public:
struct Parameters struct CV_EXPORTS Parameters
{ {
int maxTrackLifetime; int maxTrackLifetime;
int minDetectionPeriod; //the minimal time between run of the big object detector (on the whole frame) in ms (1000 mean 1 sec), default=0 int minDetectionPeriod; //the minimal time between run of the big object detector (on the whole frame) in ms (1000 mean 1 sec), default=0

@ -42,6 +42,7 @@
//M*/ //M*/
#include "precomp.hpp" #include "precomp.hpp"
#include <cassert>
#if (defined(__cplusplus) && __cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1700) #if (defined(__cplusplus) && __cplusplus > 199711L) || (defined(_MSC_VER) && _MSC_VER >= 1700)
#define USE_STD_THREADS #define USE_STD_THREADS
@ -124,7 +125,8 @@ namespace cv
class cv::DetectionBasedTracker::SeparateDetectionWork class cv::DetectionBasedTracker::SeparateDetectionWork
{ {
public: public:
SeparateDetectionWork(cv::DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector); SeparateDetectionWork(cv::DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector,
const cv::DetectionBasedTracker::Parameters& params);
virtual ~SeparateDetectionWork(); virtual ~SeparateDetectionWork();
bool communicateWithDetectingThread(const Mat& imageGray, std::vector<Rect>& rectsWhereRegions); bool communicateWithDetectingThread(const Mat& imageGray, std::vector<Rect>& rectsWhereRegions);
bool run(); bool run();
@ -135,23 +137,36 @@ class cv::DetectionBasedTracker::SeparateDetectionWork
{ {
return (stateThread==STATE_THREAD_WORKING_SLEEPING) || (stateThread==STATE_THREAD_WORKING_WITH_IMAGE); return (stateThread==STATE_THREAD_WORKING_SLEEPING) || (stateThread==STATE_THREAD_WORKING_WITH_IMAGE);
} }
inline void lock() void setParameters(const cv::DetectionBasedTracker::Parameters& params)
{ {
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.lock(); std::unique_lock<std::mutex> mtx_lock(mtx);
#else #else
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif
parameters = params;
#ifndef USE_STD_THREADS
pthread_mutex_unlock(&mutex);
#endif #endif
} }
inline void unlock()
inline void init()
{ {
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.unlock(); std::unique_lock<std::mutex> mtx_lock(mtx);
#else
pthread_mutex_lock(&mutex);
#endif
stateThread = STATE_THREAD_STOPPED;
isObjectDetectingReady = false;
shouldObjectDetectingResultsBeForgot = false;
#ifdef USE_STD_THREADS
objectDetectorThreadStartStop.notify_one();
#else #else
pthread_cond_signal(&(objectDetectorThreadStartStop));
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
#endif #endif
} }
protected: protected:
DetectionBasedTracker& detectionBasedTracker; DetectionBasedTracker& detectionBasedTracker;
@ -159,7 +174,6 @@ class cv::DetectionBasedTracker::SeparateDetectionWork
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
std::thread second_workthread; std::thread second_workthread;
std::mutex mtx; std::mutex mtx;
std::unique_lock<std::mutex> mtx_lock;
std::condition_variable objectDetectorRun; std::condition_variable objectDetectorRun;
std::condition_variable objectDetectorThreadStartStop; std::condition_variable objectDetectorThreadStartStop;
#else #else
@ -187,23 +201,23 @@ class cv::DetectionBasedTracker::SeparateDetectionWork
friend void* workcycleObjectDetectorFunction(void* p); friend void* workcycleObjectDetectorFunction(void* p);
long long timeWhenDetectingThreadStartedWork; long long timeWhenDetectingThreadStartedWork;
cv::DetectionBasedTracker::Parameters parameters;
}; };
cv::DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector) cv::DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, cv::Ptr<DetectionBasedTracker::IDetector> _detector,
const cv::DetectionBasedTracker::Parameters& params)
:detectionBasedTracker(_detectionBasedTracker), :detectionBasedTracker(_detectionBasedTracker),
cascadeInThread(), cascadeInThread(),
isObjectDetectingReady(false), isObjectDetectingReady(false),
shouldObjectDetectingResultsBeForgot(false), shouldObjectDetectingResultsBeForgot(false),
stateThread(STATE_THREAD_STOPPED), stateThread(STATE_THREAD_STOPPED),
timeWhenDetectingThreadStartedWork(-1) timeWhenDetectingThreadStartedWork(-1),
parameters(params)
{ {
CV_Assert(_detector); CV_Assert(_detector);
cascadeInThread = _detector; cascadeInThread = _detector;
#ifdef USE_STD_THREADS #ifndef USE_STD_THREADS
mtx_lock = std::unique_lock<std::mutex>(mtx);
mtx_lock.unlock();
#else
int res=0; int res=0;
res=pthread_mutex_init(&mutex, NULL);//TODO: should be attributes? res=pthread_mutex_init(&mutex, NULL);//TODO: should be attributes?
if (res) { if (res) {
@ -235,21 +249,22 @@ cv::DetectionBasedTracker::SeparateDetectionWork::~SeparateDetectionWork()
pthread_cond_destroy(&objectDetectorThreadStartStop); pthread_cond_destroy(&objectDetectorThreadStartStop);
pthread_cond_destroy(&objectDetectorRun); pthread_cond_destroy(&objectDetectorRun);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
#else
second_workthread.join();
#endif #endif
} }
bool cv::DetectionBasedTracker::SeparateDetectionWork::run() bool cv::DetectionBasedTracker::SeparateDetectionWork::run()
{ {
LOGD("DetectionBasedTracker::SeparateDetectionWork::run() --- start"); LOGD("DetectionBasedTracker::SeparateDetectionWork::run() --- start");
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.lock(); std::unique_lock<std::mutex> mtx_lock(mtx);
// unlocked when leaving scope
#else #else
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif #endif
if (stateThread != STATE_THREAD_STOPPED) { if (stateThread != STATE_THREAD_STOPPED) {
LOGE("DetectionBasedTracker::SeparateDetectionWork::run is called while the previous run is not stopped"); LOGE("DetectionBasedTracker::SeparateDetectionWork::run is called while the previous run is not stopped");
#ifdef USE_STD_THREADS #ifndef USE_STD_THREADS
mtx_lock.unlock();
#else
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
#endif #endif
return false; return false;
@ -258,7 +273,6 @@ bool cv::DetectionBasedTracker::SeparateDetectionWork::run()
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
second_workthread = std::thread(workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes? second_workthread = std::thread(workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes?
objectDetectorThreadStartStop.wait(mtx_lock); objectDetectorThreadStartStop.wait(mtx_lock);
mtx_lock.unlock();
#else #else
pthread_create(&second_workthread, NULL, workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes? pthread_create(&second_workthread, NULL, workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes?
pthread_cond_wait(&objectDetectorThreadStartStop, &mutex); pthread_cond_wait(&objectDetectorThreadStartStop, &mutex);
@ -284,16 +298,7 @@ void* cv::workcycleObjectDetectorFunction(void* p)
{ {
CATCH_ALL_AND_LOG({ ((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->workcycleObjectDetector(); }); CATCH_ALL_AND_LOG({ ((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->workcycleObjectDetector(); });
try{ try{
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->lock(); ((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->init();
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->stateThread = cv::DetectionBasedTracker::SeparateDetectionWork::STATE_THREAD_STOPPED;
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->isObjectDetectingReady=false;
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->shouldObjectDetectingResultsBeForgot=false;
#ifdef USE_STD_THREADS
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->objectDetectorThreadStartStop.notify_one();
#else
pthread_cond_signal(&(((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->objectDetectorThreadStartStop));
#endif
((cv::DetectionBasedTracker::SeparateDetectionWork*)p)->unlock();
} catch(...) { } catch(...) {
LOGE0("DetectionBasedTracker: workcycleObjectDetectorFunction: ERROR concerning pointer, received as the function parameter"); LOGE0("DetectionBasedTracker: workcycleObjectDetectorFunction: ERROR concerning pointer, received as the function parameter");
} }
@ -308,7 +313,7 @@ void cv::DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector()
CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING); CV_Assert(stateThread==STATE_THREAD_WORKING_SLEEPING);
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.lock(); std::unique_lock<std::mutex> mtx_lock(mtx);
#else #else
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif #endif
@ -453,7 +458,7 @@ void cv::DetectionBasedTracker::SeparateDetectionWork::stop()
{ {
//FIXME: TODO: should add quickStop functionality //FIXME: TODO: should add quickStop functionality
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.lock(); std::unique_lock<std::mutex> mtx_lock(mtx);
#else #else
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif #endif
@ -464,6 +469,7 @@ void cv::DetectionBasedTracker::SeparateDetectionWork::stop()
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
#endif #endif
LOGE("SimpleHighguiDemoCore::stop is called but the SimpleHighguiDemoCore pthread is not active"); LOGE("SimpleHighguiDemoCore::stop is called but the SimpleHighguiDemoCore pthread is not active");
stateThread = STATE_THREAD_STOPPING;
return; return;
} }
stateThread=STATE_THREAD_STOPPING; stateThread=STATE_THREAD_STOPPING;
@ -485,7 +491,7 @@ void cv::DetectionBasedTracker::SeparateDetectionWork::resetTracking()
{ {
LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking"); LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking");
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.lock(); std::unique_lock<std::mutex> mtx_lock(mtx);
#else #else
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif #endif
@ -523,7 +529,7 @@ bool cv::DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingT
bool shouldHandleResult = false; bool shouldHandleResult = false;
#ifdef USE_STD_THREADS #ifdef USE_STD_THREADS
mtx_lock.lock(); std::unique_lock<std::mutex> mtx_lock(mtx);
#else #else
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
#endif #endif
@ -574,8 +580,8 @@ bool cv::DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingT
cv::DetectionBasedTracker::Parameters::Parameters() cv::DetectionBasedTracker::Parameters::Parameters()
{ {
maxTrackLifetime=5; maxTrackLifetime = 5;
minDetectionPeriod=0; minDetectionPeriod = 0;
} }
cv::DetectionBasedTracker::InnerParameters::InnerParameters() cv::DetectionBasedTracker::InnerParameters::InnerParameters()
@ -603,7 +609,7 @@ cv::DetectionBasedTracker::DetectionBasedTracker(cv::Ptr<IDetector> mainDetector
&& trackingDetector ); && trackingDetector );
if (mainDetector) { if (mainDetector) {
separateDetectionWork.reset(new SeparateDetectionWork(*this, mainDetector)); separateDetectionWork.reset(new SeparateDetectionWork(*this, mainDetector, params));
} }
weightsPositionsSmoothing.push_back(1); weightsPositionsSmoothing.push_back(1);
@ -1016,12 +1022,9 @@ bool cv::DetectionBasedTracker::setParameters(const Parameters& params)
} }
if (separateDetectionWork) { if (separateDetectionWork) {
separateDetectionWork->lock(); separateDetectionWork->setParameters(params);
} }
parameters=params; parameters=params;
if (separateDetectionWork) {
separateDetectionWork->unlock();
}
return true; return true;
} }

@ -1,4 +1,4 @@
#if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(ANDROID) #if defined(__linux__) || defined(LINUX) || defined(__APPLE__) || defined(ANDROID) || (defined(_MSC_VER) && _MSC_VER>=1800)
#include <opencv2/imgproc.hpp> // Gaussian Blur #include <opencv2/imgproc.hpp> // Gaussian Blur
#include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar) #include <opencv2/core.hpp> // Basic OpenCV structures (cv::Mat, Scalar)
@ -54,9 +54,19 @@ int main(int , char** )
std::string cascadeFrontalfilename = "../../data/lbpcascades/lbpcascade_frontalface.xml"; std::string cascadeFrontalfilename = "../../data/lbpcascades/lbpcascade_frontalface.xml";
cv::Ptr<cv::CascadeClassifier> cascade = makePtr<cv::CascadeClassifier>(cascadeFrontalfilename); cv::Ptr<cv::CascadeClassifier> cascade = makePtr<cv::CascadeClassifier>(cascadeFrontalfilename);
cv::Ptr<DetectionBasedTracker::IDetector> MainDetector = makePtr<CascadeDetectorAdapter>(cascade); cv::Ptr<DetectionBasedTracker::IDetector> MainDetector = makePtr<CascadeDetectorAdapter>(cascade);
if ( cascade->empty() )
{
printf("Error: Cannot load %s\n", cascadeFrontalfilename.c_str());
return 2;
}
cascade = makePtr<cv::CascadeClassifier>(cascadeFrontalfilename); cascade = makePtr<cv::CascadeClassifier>(cascadeFrontalfilename);
cv::Ptr<DetectionBasedTracker::IDetector> TrackingDetector = makePtr<CascadeDetectorAdapter>(cascade); cv::Ptr<DetectionBasedTracker::IDetector> TrackingDetector = makePtr<CascadeDetectorAdapter>(cascade);
if ( cascade->empty() )
{
printf("Error: Cannot load %s\n", cascadeFrontalfilename.c_str());
return 2;
}
DetectionBasedTracker::Parameters params; DetectionBasedTracker::Parameters params;
DetectionBasedTracker Detector(MainDetector, TrackingDetector, params); DetectionBasedTracker Detector(MainDetector, TrackingDetector, params);
@ -71,7 +81,7 @@ int main(int , char** )
Mat GrayFrame; Mat GrayFrame;
vector<Rect> Faces; vector<Rect> Faces;
while(true) do
{ {
VideoStream >> ReferenceFrame; VideoStream >> ReferenceFrame;
cvtColor(ReferenceFrame, GrayFrame, COLOR_RGB2GRAY); cvtColor(ReferenceFrame, GrayFrame, COLOR_RGB2GRAY);
@ -84,9 +94,7 @@ int main(int , char** )
} }
imshow(WindowName, ReferenceFrame); imshow(WindowName, ReferenceFrame);
} while (waitKey(30) < 0);
if (waitKey(30) >= 0) break;
}
Detector.stop(); Detector.stop();
@ -98,7 +106,7 @@ int main(int , char** )
#include <stdio.h> #include <stdio.h>
int main() int main()
{ {
printf("This sample works for UNIX or ANDROID only\n"); printf("This sample works for UNIX or ANDROID or Visual Studio 2013+ only\n");
return 0; return 0;
} }

Loading…
Cancel
Save