Made changes in DetectionBasedTracker -- refactored the class.
authorLeonid Beynenson <no@email>
Thu, 17 Nov 2011 15:17:02 +0000 (15:17 +0000)
committerLeonid Beynenson <no@email>
Thu, 17 Nov 2011 15:17:02 +0000 (15:17 +0000)
modules/contrib/include/opencv2/contrib/detection_based_tracker.hpp
modules/contrib/src/detection_based_tracker.cpp

index 4d7be59..bef80bf 100644 (file)
@@ -40,6 +40,10 @@ class DetectionBasedTracker
         virtual void getObjects(std::vector<Object>& result) const;
 
     protected:
+        class SeparateDetectionWork;
+        cv::Ptr<SeparateDetectionWork> separateDetectionWork;
+        friend void* workcycleObjectDetectorFunction(void* p);
+
 
         struct InnerParameters
         {
@@ -54,6 +58,9 @@ class DetectionBasedTracker
 
             InnerParameters();
         };
+        Parameters parameters;
+        InnerParameters innerParameters;
+
         struct TrackedObject
         {
             typedef std::vector<cv::Rect> PositionsVector;
@@ -77,50 +84,17 @@ class DetectionBasedTracker
             }
         };
 
-        Parameters parameters;
-        InnerParameters innerParameters;
-
         int numTrackedSteps;
         std::vector<TrackedObject> trackedObjects;
 
         std::vector<float> weightsPositionsSmoothing;
         std::vector<float> 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<cv::Rect> 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<cv::Rect>& detectedObjects);
-
         cv::Rect calcTrackedObjectPositionToShow(int i) const;
-
         void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector<cv::Rect>& detectedObjectsInRegions);
 };
 
index 146975a..05ccf3f 100644 (file)
@@ -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<Rect>& 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<cv::Rect> 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<Rect> 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<Rect> 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<cv::Rect>& 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<Object>& 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<Rect> 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<Rect>& 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<Rect> 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<Rect> 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<cv::Rect>& 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<Object>& 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<Rect>& 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;
 }