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; \
} 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; \
} 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);
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;
}
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) {
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);
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;
}
+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 {
return false;
}
- pthread_mutex_lock(&mutex);
-
-
+ separateDetectionWork->lock();
parameters=params;
-
- pthread_mutex_unlock(&mutex);
+ separateDetectionWork->unlock();
return true;
}