From: Leonid Beynenson Date: Thu, 17 Nov 2011 15:17:02 +0000 (+0000) Subject: Made changes in DetectionBasedTracker -- refactored the class. X-Git-Tag: accepted/2.0/20130307.220821~1621 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e9b9dfe1c29dfe71c1a623704e171612bba8f118;p=profile%2Fivi%2Fopencv.git Made changes in DetectionBasedTracker -- refactored the class. --- diff --git a/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp b/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp index 4d7be59..bef80bf 100644 --- a/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp +++ b/modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp @@ -40,6 +40,10 @@ class DetectionBasedTracker virtual void getObjects(std::vector& result) const; protected: + class SeparateDetectionWork; + cv::Ptr separateDetectionWork; + friend void* workcycleObjectDetectorFunction(void* p); + struct InnerParameters { @@ -54,6 +58,9 @@ class DetectionBasedTracker InnerParameters(); }; + Parameters parameters; + InnerParameters innerParameters; + struct TrackedObject { typedef std::vector PositionsVector; @@ -77,50 +84,17 @@ class DetectionBasedTracker } }; - Parameters parameters; - InnerParameters innerParameters; - int numTrackedSteps; std::vector trackedObjects; std::vector weightsPositionsSmoothing; std::vector weightsSizesSmoothing; - cv::CascadeClassifier cascadeInThread; cv::CascadeClassifier cascadeForTracking; - cv::Mat imageSeparateDetecting; - - void workcycleObjectDetector(); - friend void* workcycleObjectDetectorFunction(void* p); - - pthread_t second_workthread; - pthread_mutex_t mutex; - pthread_cond_t objectDetectorRun; - pthread_cond_t objectDetectorThreadStartStop; - - std::vector resultDetect; - volatile bool isObjectDetectingReady; - volatile bool shouldObjectDetectingResultsBeForgot; - - enum StateSeparatedThread { - STATE_THREAD_STOPPED=0, - STATE_THREAD_WORKING, - STATE_THREAD_STOPPING - }; - volatile StateSeparatedThread stateThread; - - enum StateSeparatedObjectDetector{ - OBJECT_DETECTOR_NOT_STARTED, - OBJECT_DETECTOR_WAITING_IMAGE, - OBJECT_DETECTOR_HANDLING_IMAGE - }; - volatile StateSeparatedObjectDetector stateSeparatedObjectDetector; void updateTrackedObjects(const std::vector& detectedObjects); - cv::Rect calcTrackedObjectPositionToShow(int i) const; - void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector& detectedObjectsInRegions); }; diff --git a/modules/contrib/src/detection_based_tracker.cpp b/modules/contrib/src/detection_based_tracker.cpp index 146975a..05ccf3f 100644 --- a/modules/contrib/src/detection_based_tracker.cpp +++ b/modules/contrib/src/detection_based_tracker.cpp @@ -51,235 +51,126 @@ static inline cv::Rect scale_rect(const cv::Rect& r, float scale) return cv::Rect(x, y, cvRound(width), cvRound(height)); }; -DetectionBasedTracker::Parameters::Parameters() +void* workcycleObjectDetectorFunction(void* p); +class DetectionBasedTracker::SeparateDetectionWork { - minObjectSize=96; - maxObjectSize=INT_MAX; - scaleFactor=1.1; - maxTrackLifetime=5; - minNeighbors=2; - minDetectionPeriod=0; -} + public: + SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, const std::string& cascadeFilename); + virtual ~SeparateDetectionWork(); + bool communicateWithDetectingThread(const Mat& imageGray, vector& rectsWhereRegions); + bool run(); + void stop(); + void resetTracking(); + inline bool isWorking() + { + return (stateThread==STATE_THREAD_WORKING); + } + inline void lock() + { + pthread_mutex_lock(&mutex); + } + inline void unlock() + { + pthread_mutex_unlock(&mutex); + } + protected: + DetectionBasedTracker& detectionBasedTracker; + cv::CascadeClassifier cascadeInThread; -DetectionBasedTracker::InnerParameters::InnerParameters() -{ - numLastPositionsToTrack=4; - numStepsToWaitBeforeFirstShow=6; - numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown=3; - numStepsToShowWithoutDetecting=3; + pthread_t second_workthread; + pthread_mutex_t mutex; + pthread_cond_t objectDetectorRun; + pthread_cond_t objectDetectorThreadStartStop; - coeffTrackingWindowSize=2.0; - coeffObjectSizeToTrack=0.85; - coeffObjectSpeedUsingInPrediction=0.8; + std::vector resultDetect; + volatile bool isObjectDetectingReady; + volatile bool shouldObjectDetectingResultsBeForgot; -} -DetectionBasedTracker::DetectionBasedTracker(const std::string& cascadeFilename, const Parameters& params) - :innerParameters(), - numTrackedSteps(0), + enum StateSeparatedThread { + STATE_THREAD_STOPPED=0, + STATE_THREAD_WORKING, + STATE_THREAD_STOPPING + }; + volatile StateSeparatedThread stateThread; + + enum StateSeparatedObjectDetector{ + OBJECT_DETECTOR_NOT_STARTED, + OBJECT_DETECTOR_WAITING_IMAGE, + OBJECT_DETECTOR_HANDLING_IMAGE + }; + volatile StateSeparatedObjectDetector stateSeparatedObjectDetector; + + + cv::Mat imageSeparateDetecting; + + void workcycleObjectDetector(); + friend void* workcycleObjectDetectorFunction(void* p); + + long long timeWhenDetectingThreadStartedWork; +}; + +DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, const std::string& cascadeFilename) + :detectionBasedTracker(_detectionBasedTracker), cascadeInThread(cascadeFilename), - cascadeForTracking(cascadeFilename), isObjectDetectingReady(false), shouldObjectDetectingResultsBeForgot(false), stateThread(STATE_THREAD_STOPPED), - stateSeparatedObjectDetector(OBJECT_DETECTOR_NOT_STARTED) + stateSeparatedObjectDetector(OBJECT_DETECTOR_NOT_STARTED), + timeWhenDetectingThreadStartedWork(-1) { - CV_Assert( (params.minObjectSize > 0) - && (params.maxObjectSize >= 0) - && (params.scaleFactor > 1.0) - && (params.maxTrackLifetime >= 0) ); - - parameters=params; - - weightsPositionsSmoothing.push_back(1); - weightsSizesSmoothing.push_back(0.5); - weightsSizesSmoothing.push_back(0.3); - weightsSizesSmoothing.push_back(0.2); - int res=0; res=pthread_mutex_init(&mutex, NULL);//TODO: should be attributes? if (res) { - LOGE("ERROR in DetectionBasedTracker::DetectionBasedTracker in pthread_mutex_init(&mutex, NULL) is %d", res); + LOGE("ERROR in DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork in pthread_mutex_init(&mutex, NULL) is %d", res); throw(std::exception()); } res=pthread_cond_init (&objectDetectorRun, NULL); if (res) { - LOGE("ERROR in DetectionBasedTracker::DetectionBasedTracker in pthread_cond_init(&objectDetectorRun,, NULL) is %d", res); + LOGE("ERROR in DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork in pthread_cond_init(&objectDetectorRun,, NULL) is %d", res); pthread_mutex_destroy(&mutex); throw(std::exception()); } res=pthread_cond_init (&objectDetectorThreadStartStop, NULL); if (res) { - LOGE("ERROR in DetectionBasedTracker::DetectionBasedTracker in pthread_cond_init(&objectDetectorThreadStartStop,, NULL) is %d", res); + LOGE("ERROR in DetectionBasedTracker::SeparateDetectionWork::SeparateDetectionWork in pthread_cond_init(&objectDetectorThreadStartStop,, NULL) is %d", res); pthread_cond_destroy(&objectDetectorRun); pthread_mutex_destroy(&mutex); throw(std::exception()); } } -DetectionBasedTracker::~DetectionBasedTracker() + +DetectionBasedTracker::SeparateDetectionWork::~SeparateDetectionWork() { if(stateThread!=STATE_THREAD_STOPPED) { - LOGE("\n\n\nATTENTION!!! dangerous algorithm error: destructor DetectionBasedTracker::~DetectionBasedTracker is called before stopping the workthread"); + LOGE("\n\n\nATTENTION!!! dangerous algorithm error: destructor DetectionBasedTracker::DetectionBasedTracker::~SeparateDetectionWork is called before stopping the workthread"); } pthread_cond_destroy(&objectDetectorThreadStartStop); pthread_cond_destroy(&objectDetectorRun); pthread_mutex_destroy(&mutex); } - - - -void DetectionBasedTracker::process(const Mat& imageGray) +bool DetectionBasedTracker::SeparateDetectionWork::run() { - static long long timeWhenDetectingThreadStartedWork=-1; - - CV_Assert(imageGray.type()==CV_8UC1); - - if (stateThread == STATE_THREAD_STOPPED) { - run(); - } - - static double freq = getTickFrequency(); - static long long time_when_last_call_started=getTickCount(); - - { - double delta_time_from_prev_call=1000.0 * (((double)(getTickCount() - time_when_last_call_started)) / freq); - LOGD("DetectionBasedTracker::process: time from the previous call is %f ms", (double)delta_time_from_prev_call); - time_when_last_call_started=getTickCount(); - } - - Mat imageDetect=imageGray; - - Size sz=imageDetect.size(); - int D=parameters.minObjectSize; - if (D < 1) - D=1; - Size objectSize=Size(D,D); - - - bool shouldHandleResult=false; - - vector rectsWhereRegions; - - - bool shouldCommunicateWithDetectingThread=(stateSeparatedObjectDetector==OBJECT_DETECTOR_WAITING_IMAGE); - LOGD("DetectionBasedTracker::process: shouldCommunicateWithDetectingThread=%d", (shouldCommunicateWithDetectingThread?1:0)); - - if (shouldCommunicateWithDetectingThread) { - pthread_mutex_lock(&mutex); - - if (isObjectDetectingReady) { - shouldHandleResult=true; - rectsWhereRegions=resultDetect; - isObjectDetectingReady=false; - - double lastBigDetectionDuration=1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq); - LOGD("DetectionBasedTracker::process: lastBigDetectionDuration=%f ms", (double)lastBigDetectionDuration); - } - - bool shouldSendNewDataToWorkThread=true; - if (timeWhenDetectingThreadStartedWork > 0) { - double time_from_previous_launch_in_ms=1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq); //the same formula as for lastBigDetectionDuration - shouldSendNewDataToWorkThread = (time_from_previous_launch_in_ms >= parameters.minDetectionPeriod); - LOGD("DetectionBasedTracker::process: shouldSendNewDataToWorkThread was 1, now it is %d, since time_from_previous_launch_in_ms=%.2f, minDetectionPeriod=%d", - (shouldSendNewDataToWorkThread?1:0), time_from_previous_launch_in_ms, parameters.minDetectionPeriod); - } - - if (shouldSendNewDataToWorkThread) { - - imageSeparateDetecting.create(imageGray.size(), CV_8UC1); - { - uchar* databefore=imageSeparateDetecting.data; //for debugging only - - imageGray.copyTo(imageSeparateDetecting);//may change imageSeparateDetecting ptr. But should not. - - uchar* dataafter=imageSeparateDetecting.data; //for debugging only - CV_Assert(databefore == dataafter); // for debugging only - } - - timeWhenDetectingThreadStartedWork = getTickCount() ; - - pthread_cond_signal(&objectDetectorRun); - } - + LOGD("DetectionBasedTracker::SeparateDetectionWork::run() --- start"); + pthread_mutex_lock(&mutex); + if (stateThread != STATE_THREAD_STOPPED) { + LOGE("DetectionBasedTracker::SeparateDetectionWork::run is called while the previous run is not stopped"); pthread_mutex_unlock(&mutex); + return false; } - - if (shouldHandleResult) { - LOGD("DetectionBasedTracker::process: get _rectsWhereRegions were got from resultDetect"); - } else { - LOGD("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions"); - for(size_t i=0; i < trackedObjects.size(); i++) { - int n=trackedObjects[i].lastPositions.size(); - CV_Assert(n > 0); - - Rect r=trackedObjects[i].lastPositions[n-1]; - if(r.area()==0) { - LOGE("DetectionBasedTracker::process: ERROR: ATTENTION: strange algorithm's behavior: trackedObjects[i].rect() is empty"); - continue; - } - - - //correction by speed of rectangle - if (n > 1) { - Point2f center=centerRect(r); - Point2f center_prev=centerRect(trackedObjects[i].lastPositions[n-2]); - Point2f shift=(center - center_prev) * innerParameters.coeffObjectSpeedUsingInPrediction; - - r.x+=cvRound(shift.x); - r.y+=cvRound(shift.y); - } - - - rectsWhereRegions.push_back(r); - } - } - LOGI("DetectionBasedTracker::process: tracked objects num==%d", (int)trackedObjects.size()); - - vector detectedObjectsInRegions; - - LOGD("DetectionBasedTracker::process: rectsWhereRegions.size()=%d", (int)rectsWhereRegions.size()); - for(size_t i=0; i < rectsWhereRegions.size(); i++) { - Rect r=rectsWhereRegions[i]; - - detectInRegion(imageDetect, r, detectedObjectsInRegions); - } - LOGD("DetectionBasedTracker::process: detectedObjectsInRegions.size()=%d", (int)detectedObjectsInRegions.size()); - - updateTrackedObjects(detectedObjectsInRegions); -} - -void DetectionBasedTracker::getObjects(std::vector& result) const -{ - result.clear(); - - for(size_t i=0; i < trackedObjects.size(); i++) { - Rect r=calcTrackedObjectPositionToShow(i); - if (r.area()==0) { - continue; - } - result.push_back(r); - LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height); - } -} -void DetectionBasedTracker::getObjects(std::vector& result) const -{ - result.clear(); - - for(size_t i=0; i < trackedObjects.size(); i++) { - Rect r=calcTrackedObjectPositionToShow(i); - if (r.area()==0) { - continue; - } - result.push_back(Object(r, trackedObjects[i].id)); - LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height); - } + stateThread=STATE_THREAD_WORKING; + pthread_create(&second_workthread, NULL, workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes? + pthread_cond_wait(&objectDetectorThreadStartStop, &mutex); + pthread_mutex_unlock(&mutex); + LOGD("DetectionBasedTracker::SeparateDetectionWork::run --- end"); + return true; } #ifdef __GNUC__ -#define CATCH_ALL_AND_REPEATE(_block) \ -while(true) { \ +#define CATCH_ALL_AND_LOG(_block) \ +do { \ try { \ _block; \ break; \ @@ -291,10 +182,10 @@ while(true) { } catch(...) { \ LOGE("\n %s: ERROR: UNKNOWN Exception caught\n\n", __func__); \ } \ -} +} while(0) #else -#define CATCH_ALL_AND_REPEATE(_block) \ -while(true) { \ +#define CATCH_ALL_AND_LOG(_block) \ +do { \ try { \ _block; \ break; \ @@ -306,47 +197,30 @@ while(true) { } catch(...) { \ LOGE("\n ERROR: UNKNOWN Exception caught\n\n"); \ } \ -} +} while(0) #endif void* workcycleObjectDetectorFunction(void* p) { - CATCH_ALL_AND_REPEATE({ ((DetectionBasedTracker*)p)->workcycleObjectDetector(); }); + CATCH_ALL_AND_LOG({ ((DetectionBasedTracker::SeparateDetectionWork*)p)->workcycleObjectDetector(); }); return NULL; } -bool DetectionBasedTracker::run() -{ - LOGD("DetectionBasedTracker::run() --- start"); - pthread_mutex_lock(&mutex); - if (stateThread != STATE_THREAD_STOPPED) { - LOGE("DetectionBasedTracker::run is called while the previous run is not stopped"); - pthread_mutex_unlock(&mutex); - return false; - } - stateThread=STATE_THREAD_WORKING; - pthread_create(&second_workthread, NULL, workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes? - pthread_cond_wait(&objectDetectorThreadStartStop, &mutex); - pthread_mutex_unlock(&mutex); - LOGD("DetectionBasedTracker::run() --- end"); - return true; -} - -void DetectionBasedTracker::workcycleObjectDetector() +void DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() { static double freq = getTickFrequency(); - LOGD0("DetectionBasedTracker::workcycleObjectDetector() --- start"); + LOGD0("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start"); vector objects; pthread_mutex_lock(&mutex); { pthread_cond_signal(&objectDetectorThreadStartStop); - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- before waiting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting"); stateSeparatedObjectDetector=OBJECT_DETECTOR_WAITING_IMAGE; pthread_cond_wait(&objectDetectorRun, &mutex); stateSeparatedObjectDetector=OBJECT_DETECTOR_HANDLING_IMAGE; - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- after waiting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting"); } pthread_mutex_unlock(&mutex); @@ -356,54 +230,54 @@ void DetectionBasedTracker::workcycleObjectDetector() while(stateThread == STATE_THREAD_WORKING) { - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- next step"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- next step"); if (! isFirstStep) { - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- before waiting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting"); pthread_mutex_lock(&mutex); stateSeparatedObjectDetector=OBJECT_DETECTOR_WAITING_IMAGE; pthread_cond_wait(&objectDetectorRun, &mutex); stateSeparatedObjectDetector=OBJECT_DETECTOR_HANDLING_IMAGE; pthread_mutex_unlock(&mutex); - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- after waiting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting"); } else { isFirstStep=false; } if (stateThread != STATE_THREAD_WORKING) { - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- go out from the workcycle just after waiting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle just after waiting"); break; } if (imageSeparateDetecting.empty()) { - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- imageSeparateDetecting is empty, continue"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- imageSeparateDetecting is empty, continue"); continue; } - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- start handling imageSeparateDetecting, img.size=%dx%d, img.data=0x%p", + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start handling imageSeparateDetecting, img.size=%dx%d, img.data=0x%p", imageSeparateDetecting.size().width, imageSeparateDetecting.size().height, (void*)imageSeparateDetecting.data); int64 t1_detect=getTickCount(); - int minObjectSize=parameters.minObjectSize; + int minObjectSize=detectionBasedTracker.parameters.minObjectSize; Size min_objectSize=Size(minObjectSize, minObjectSize); - int maxObjectSize=parameters.maxObjectSize; + int maxObjectSize=detectionBasedTracker.parameters.maxObjectSize; Size max_objectSize(maxObjectSize, maxObjectSize); cascadeInThread.detectMultiScale( imageSeparateDetecting, objects, - parameters.scaleFactor, parameters.minNeighbors, 0 + detectionBasedTracker.parameters.scaleFactor, detectionBasedTracker.parameters.minNeighbors, 0 |CV_HAAR_SCALE_IMAGE , min_objectSize, max_objectSize ); - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- end handling imageSeparateDetecting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- end handling imageSeparateDetecting"); if (stateThread != STATE_THREAD_WORKING) { - LOGD("DetectionBasedTracker::workcycleObjectDetector() --- go out from the workcycle just after detecting"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- go out from the workcycle just after detecting"); break; } @@ -411,7 +285,7 @@ void DetectionBasedTracker::workcycleObjectDetector() int64 dt_detect=t2_detect-t1_detect; double dt_detect_ms=((double)dt_detect)/freq * 1000.0; - LOGI("DetectionBasedTracker::workcycleObjectDetector() --- objects num==%d, t_ms=%.4f", (int)objects.size(), dt_detect_ms); + LOGI("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- objects num==%d, t_ms=%.4f", (int)objects.size(), dt_detect_ms); pthread_mutex_lock(&mutex); if (!shouldObjectDetectingResultsBeForgot) { @@ -441,9 +315,10 @@ void DetectionBasedTracker::workcycleObjectDetector() pthread_mutex_unlock(&mutex); - LOGI("DetectionBasedTracker::workcycleObjectDetector: Returning"); + LOGI("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector: Returning"); } -void DetectionBasedTracker::stop() + +void DetectionBasedTracker::SeparateDetectionWork::stop() { //FIXME: TODO: should add quickStop functionality pthread_mutex_lock(&mutex); @@ -453,28 +328,27 @@ void DetectionBasedTracker::stop() return; } stateThread=STATE_THREAD_STOPPING; - LOGD("DetectionBasedTracker::stop: before going to sleep to wait for the signal from the workthread"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::stop: before going to sleep to wait for the signal from the workthread"); pthread_cond_signal(&objectDetectorRun); pthread_cond_wait(&objectDetectorThreadStartStop, &mutex); - LOGD("DetectionBasedTracker::stop: after receiving the signal from the workthread, stateThread=%d", (int)stateThread); + LOGD("DetectionBasedTracker::SeparateDetectionWork::stop: after receiving the signal from the workthread, stateThread=%d", (int)stateThread); pthread_mutex_unlock(&mutex); } -void DetectionBasedTracker::resetTracking() +void DetectionBasedTracker::SeparateDetectionWork::resetTracking() { - LOGD("DetectionBasedTracker::resetTracking"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking"); pthread_mutex_lock(&mutex); if ((stateThread == STATE_THREAD_WORKING) && (stateSeparatedObjectDetector == OBJECT_DETECTOR_HANDLING_IMAGE)) { - LOGD("DetectionBasedTracker::resetTracking: since workthread is detecting objects at the moment, we should make cascadeInThread stop detecting and forget the detecting results"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking: since workthread is detecting objects at the moment, we should make cascadeInThread stop detecting and forget the detecting results"); shouldObjectDetectingResultsBeForgot=true; //cascadeInThread.setStopFlag();//FIXME: TODO: this feature also should be contributed to OpenCV } else { - LOGD("DetectionBasedTracker::resetTracking: since workthread is NOT detecting objects at the moment, we should NOT make any additional actions"); + LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking: since workthread is NOT detecting objects at the moment, we should NOT make any additional actions"); } resultDetect.clear(); - trackedObjects.clear(); isObjectDetectingReady=false; @@ -482,6 +356,226 @@ void DetectionBasedTracker::resetTracking() } +bool DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread(const Mat& imageGray, vector& rectsWhereRegions) +{ + static double freq = getTickFrequency(); + + bool shouldCommunicateWithDetectingThread=(stateSeparatedObjectDetector==OBJECT_DETECTOR_WAITING_IMAGE); + LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: shouldCommunicateWithDetectingThread=%d", (shouldCommunicateWithDetectingThread?1:0)); + + if (!shouldCommunicateWithDetectingThread) { + return false; + } + + bool shouldHandleResult=false; + pthread_mutex_lock(&mutex); + + if (isObjectDetectingReady) { + shouldHandleResult=true; + rectsWhereRegions=resultDetect; + isObjectDetectingReady=false; + + double lastBigDetectionDuration=1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq); + LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: lastBigDetectionDuration=%f ms", (double)lastBigDetectionDuration); + } + + bool shouldSendNewDataToWorkThread=true; + if (timeWhenDetectingThreadStartedWork > 0) { + double time_from_previous_launch_in_ms=1000.0 * (((double)(getTickCount() - timeWhenDetectingThreadStartedWork )) / freq); //the same formula as for lastBigDetectionDuration + shouldSendNewDataToWorkThread = (time_from_previous_launch_in_ms >= detectionBasedTracker.parameters.minDetectionPeriod); + LOGD("DetectionBasedTracker::SeparateDetectionWork::communicateWithDetectingThread: shouldSendNewDataToWorkThread was 1, now it is %d, since time_from_previous_launch_in_ms=%.2f, minDetectionPeriod=%d", + (shouldSendNewDataToWorkThread?1:0), time_from_previous_launch_in_ms, detectionBasedTracker.parameters.minDetectionPeriod); + } + + if (shouldSendNewDataToWorkThread) { + + imageSeparateDetecting.create(imageGray.size(), CV_8UC1); + + imageGray.copyTo(imageSeparateDetecting);//may change imageSeparateDetecting ptr. But should not. + + + timeWhenDetectingThreadStartedWork = getTickCount() ; + + pthread_cond_signal(&objectDetectorRun); + } + + pthread_mutex_unlock(&mutex); + + return shouldHandleResult; +} + +DetectionBasedTracker::Parameters::Parameters() +{ + minObjectSize=96; + maxObjectSize=INT_MAX; + scaleFactor=1.1; + maxTrackLifetime=5; + minNeighbors=2; + minDetectionPeriod=0; +} + + + +DetectionBasedTracker::InnerParameters::InnerParameters() +{ + numLastPositionsToTrack=4; + numStepsToWaitBeforeFirstShow=6; + numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown=3; + numStepsToShowWithoutDetecting=3; + + coeffTrackingWindowSize=2.0; + coeffObjectSizeToTrack=0.85; + coeffObjectSpeedUsingInPrediction=0.8; + +} +DetectionBasedTracker::DetectionBasedTracker(const std::string& cascadeFilename, const Parameters& params) + :separateDetectionWork(), + innerParameters(), + numTrackedSteps(0), + cascadeForTracking(cascadeFilename) +{ + CV_Assert( (params.minObjectSize > 0) + && (params.maxObjectSize >= 0) + && (params.scaleFactor > 1.0) + && (params.maxTrackLifetime >= 0) ); + + parameters=params; + + separateDetectionWork=new SeparateDetectionWork(*this, cascadeFilename); + + weightsPositionsSmoothing.push_back(1); + weightsSizesSmoothing.push_back(0.5); + weightsSizesSmoothing.push_back(0.3); + weightsSizesSmoothing.push_back(0.2); + +} +DetectionBasedTracker::~DetectionBasedTracker() +{ +} + + + +void DetectionBasedTracker::process(const Mat& imageGray) +{ + + CV_Assert(imageGray.type()==CV_8UC1); + + if (!separateDetectionWork->isWorking()) { + separateDetectionWork->run(); + } + + static double freq = getTickFrequency(); + static long long time_when_last_call_started=getTickCount(); + + { + double delta_time_from_prev_call=1000.0 * (((double)(getTickCount() - time_when_last_call_started)) / freq); + LOGD("DetectionBasedTracker::process: time from the previous call is %f ms", (double)delta_time_from_prev_call); + time_when_last_call_started=getTickCount(); + } + + Mat imageDetect=imageGray; + + Size sz=imageDetect.size(); + int D=parameters.minObjectSize; + if (D < 1) + D=1; + Size objectSize=Size(D,D); + + + vector rectsWhereRegions; + bool shouldHandleResult=separateDetectionWork->communicateWithDetectingThread(imageGray, rectsWhereRegions); + + + + if (shouldHandleResult) { + LOGD("DetectionBasedTracker::process: get _rectsWhereRegions were got from resultDetect"); + } else { + LOGD("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions"); + for(size_t i=0; i < trackedObjects.size(); i++) { + int n=trackedObjects[i].lastPositions.size(); + CV_Assert(n > 0); + + Rect r=trackedObjects[i].lastPositions[n-1]; + if(r.area()==0) { + LOGE("DetectionBasedTracker::process: ERROR: ATTENTION: strange algorithm's behavior: trackedObjects[i].rect() is empty"); + continue; + } + + + //correction by speed of rectangle + if (n > 1) { + Point2f center=centerRect(r); + Point2f center_prev=centerRect(trackedObjects[i].lastPositions[n-2]); + Point2f shift=(center - center_prev) * innerParameters.coeffObjectSpeedUsingInPrediction; + + r.x+=cvRound(shift.x); + r.y+=cvRound(shift.y); + } + + + rectsWhereRegions.push_back(r); + } + } + LOGI("DetectionBasedTracker::process: tracked objects num==%d", (int)trackedObjects.size()); + + vector detectedObjectsInRegions; + + LOGD("DetectionBasedTracker::process: rectsWhereRegions.size()=%d", (int)rectsWhereRegions.size()); + for(size_t i=0; i < rectsWhereRegions.size(); i++) { + Rect r=rectsWhereRegions[i]; + + detectInRegion(imageDetect, r, detectedObjectsInRegions); + } + LOGD("DetectionBasedTracker::process: detectedObjectsInRegions.size()=%d", (int)detectedObjectsInRegions.size()); + + updateTrackedObjects(detectedObjectsInRegions); +} + +void DetectionBasedTracker::getObjects(std::vector& result) const +{ + result.clear(); + + for(size_t i=0; i < trackedObjects.size(); i++) { + Rect r=calcTrackedObjectPositionToShow(i); + if (r.area()==0) { + continue; + } + result.push_back(r); + LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height); + } +} +void DetectionBasedTracker::getObjects(std::vector& result) const +{ + result.clear(); + + for(size_t i=0; i < trackedObjects.size(); i++) { + Rect r=calcTrackedObjectPositionToShow(i); + if (r.area()==0) { + continue; + } + result.push_back(Object(r, trackedObjects[i].id)); + LOGD("DetectionBasedTracker::process: found a object with SIZE %d x %d, rect={%d, %d, %d x %d}", r.width, r.height, r.x, r.y, r.width, r.height); + } +} + + + +bool DetectionBasedTracker::run() +{ + return separateDetectionWork->run(); +} + +void DetectionBasedTracker::stop() +{ + separateDetectionWork->stop(); +} + +void DetectionBasedTracker::resetTracking() +{ + separateDetectionWork->resetTracking(); + trackedObjects.clear(); +} + void DetectionBasedTracker::updateTrackedObjects(const vector& detectedObjects) { enum { @@ -730,12 +824,9 @@ bool DetectionBasedTracker::setParameters(const Parameters& params) return false; } - pthread_mutex_lock(&mutex); - - + separateDetectionWork->lock(); parameters=params; - - pthread_mutex_unlock(&mutex); + separateDetectionWork->unlock(); return true; }