Commit e9b9dfe1 authored by Leonid Beynenson's avatar Leonid Beynenson

Made changes in DetectionBasedTracker -- refactored the class.

parent 01c15db6
...@@ -40,6 +40,10 @@ class DetectionBasedTracker ...@@ -40,6 +40,10 @@ class DetectionBasedTracker
virtual void getObjects(std::vector<Object>& result) const; virtual void getObjects(std::vector<Object>& result) const;
protected: protected:
class SeparateDetectionWork;
cv::Ptr<SeparateDetectionWork> separateDetectionWork;
friend void* workcycleObjectDetectorFunction(void* p);
struct InnerParameters struct InnerParameters
{ {
...@@ -54,6 +58,9 @@ class DetectionBasedTracker ...@@ -54,6 +58,9 @@ class DetectionBasedTracker
InnerParameters(); InnerParameters();
}; };
Parameters parameters;
InnerParameters innerParameters;
struct TrackedObject struct TrackedObject
{ {
typedef std::vector<cv::Rect> PositionsVector; typedef std::vector<cv::Rect> PositionsVector;
...@@ -77,50 +84,17 @@ class DetectionBasedTracker ...@@ -77,50 +84,17 @@ class DetectionBasedTracker
} }
}; };
Parameters parameters;
InnerParameters innerParameters;
int numTrackedSteps; int numTrackedSteps;
std::vector<TrackedObject> trackedObjects; std::vector<TrackedObject> trackedObjects;
std::vector<float> weightsPositionsSmoothing; std::vector<float> weightsPositionsSmoothing;
std::vector<float> weightsSizesSmoothing; std::vector<float> weightsSizesSmoothing;
cv::CascadeClassifier cascadeInThread;
cv::CascadeClassifier cascadeForTracking; 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); void updateTrackedObjects(const std::vector<cv::Rect>& detectedObjects);
cv::Rect calcTrackedObjectPositionToShow(int i) const; cv::Rect calcTrackedObjectPositionToShow(int i) const;
void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector<cv::Rect>& detectedObjectsInRegions); void detectInRegion(const cv::Mat& img, const cv::Rect& r, std::vector<cv::Rect>& detectedObjectsInRegions);
}; };
......
...@@ -51,235 +51,126 @@ static inline cv::Rect scale_rect(const cv::Rect& r, float scale) ...@@ -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)); return cv::Rect(x, y, cvRound(width), cvRound(height));
}; };
DetectionBasedTracker::Parameters::Parameters() void* workcycleObjectDetectorFunction(void* p);
class DetectionBasedTracker::SeparateDetectionWork
{ {
minObjectSize=96; public:
maxObjectSize=INT_MAX; SeparateDetectionWork(DetectionBasedTracker& _detectionBasedTracker, const std::string& cascadeFilename);
scaleFactor=1.1; virtual ~SeparateDetectionWork();
maxTrackLifetime=5; bool communicateWithDetectingThread(const Mat& imageGray, vector<Rect>& rectsWhereRegions);
minNeighbors=2; bool run();
minDetectionPeriod=0; 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() pthread_t second_workthread;
{ pthread_mutex_t mutex;
numLastPositionsToTrack=4; pthread_cond_t objectDetectorRun;
numStepsToWaitBeforeFirstShow=6; pthread_cond_t objectDetectorThreadStartStop;
numStepsToTrackWithoutDetectingIfObjectHasNotBeenShown=3;
numStepsToShowWithoutDetecting=3;
coeffTrackingWindowSize=2.0; std::vector<cv::Rect> resultDetect;
coeffObjectSizeToTrack=0.85; volatile bool isObjectDetectingReady;
coeffObjectSpeedUsingInPrediction=0.8; volatile bool shouldObjectDetectingResultsBeForgot;
} enum StateSeparatedThread {
DetectionBasedTracker::DetectionBasedTracker(const std::string& cascadeFilename, const Parameters& params) STATE_THREAD_STOPPED=0,
:innerParameters(), STATE_THREAD_WORKING,
numTrackedSteps(0), 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), cascadeInThread(cascadeFilename),
cascadeForTracking(cascadeFilename),
isObjectDetectingReady(false), isObjectDetectingReady(false),
shouldObjectDetectingResultsBeForgot(false), shouldObjectDetectingResultsBeForgot(false),
stateThread(STATE_THREAD_STOPPED), 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; 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) {
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()); throw(std::exception());
} }
res=pthread_cond_init (&objectDetectorRun, NULL); res=pthread_cond_init (&objectDetectorRun, NULL);
if (res) { 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); pthread_mutex_destroy(&mutex);
throw(std::exception()); throw(std::exception());
} }
res=pthread_cond_init (&objectDetectorThreadStartStop, NULL); res=pthread_cond_init (&objectDetectorThreadStartStop, NULL);
if (res) { 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_cond_destroy(&objectDetectorRun);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
throw(std::exception()); throw(std::exception());
} }
} }
DetectionBasedTracker::~DetectionBasedTracker()
DetectionBasedTracker::SeparateDetectionWork::~SeparateDetectionWork()
{ {
if(stateThread!=STATE_THREAD_STOPPED) { 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(&objectDetectorThreadStartStop);
pthread_cond_destroy(&objectDetectorRun); pthread_cond_destroy(&objectDetectorRun);
pthread_mutex_destroy(&mutex); pthread_mutex_destroy(&mutex);
} }
bool DetectionBasedTracker::SeparateDetectionWork::run()
void DetectionBasedTracker::process(const Mat& imageGray)
{ {
static long long timeWhenDetectingThreadStartedWork=-1; LOGD("DetectionBasedTracker::SeparateDetectionWork::run() --- start");
pthread_mutex_lock(&mutex);
CV_Assert(imageGray.type()==CV_8UC1); if (stateThread != STATE_THREAD_STOPPED) {
LOGE("DetectionBasedTracker::SeparateDetectionWork::run is called while the previous run is not stopped");
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);
}
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
return false;
} }
stateThread=STATE_THREAD_WORKING;
if (shouldHandleResult) { pthread_create(&second_workthread, NULL, workcycleObjectDetectorFunction, (void*)this); //TODO: add attributes?
LOGD("DetectionBasedTracker::process: get _rectsWhereRegions were got from resultDetect"); pthread_cond_wait(&objectDetectorThreadStartStop, &mutex);
} else { pthread_mutex_unlock(&mutex);
LOGD("DetectionBasedTracker::process: get _rectsWhereRegions from previous positions"); LOGD("DetectionBasedTracker::SeparateDetectionWork::run --- end");
for(size_t i=0; i < trackedObjects.size(); i++) { return true;
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);
}
} }
#ifdef __GNUC__ #ifdef __GNUC__
#define CATCH_ALL_AND_REPEATE(_block) \ #define CATCH_ALL_AND_LOG(_block) \
while(true) { \ do { \
try { \ try { \
_block; \ _block; \
break; \ break; \
...@@ -291,10 +182,10 @@ while(true) { ...@@ -291,10 +182,10 @@ while(true) {
} catch(...) { \ } catch(...) { \
LOGE("\n %s: ERROR: UNKNOWN Exception caught\n\n", __func__); \ LOGE("\n %s: ERROR: UNKNOWN Exception caught\n\n", __func__); \
} \ } \
} } while(0)
#else #else
#define CATCH_ALL_AND_REPEATE(_block) \ #define CATCH_ALL_AND_LOG(_block) \
while(true) { \ do { \
try { \ try { \
_block; \ _block; \
break; \ break; \
...@@ -306,47 +197,30 @@ while(true) { ...@@ -306,47 +197,30 @@ while(true) {
} catch(...) { \ } catch(...) { \
LOGE("\n ERROR: UNKNOWN Exception caught\n\n"); \ LOGE("\n ERROR: UNKNOWN Exception caught\n\n"); \
} \ } \
} } while(0)
#endif #endif
void* workcycleObjectDetectorFunction(void* p) void* workcycleObjectDetectorFunction(void* p)
{ {
CATCH_ALL_AND_REPEATE({ ((DetectionBasedTracker*)p)->workcycleObjectDetector(); }); CATCH_ALL_AND_LOG({ ((DetectionBasedTracker::SeparateDetectionWork*)p)->workcycleObjectDetector(); });
return NULL; return NULL;
} }
bool DetectionBasedTracker::run() void DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector()
{
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()
{ {
static double freq = getTickFrequency(); static double freq = getTickFrequency();
LOGD0("DetectionBasedTracker::workcycleObjectDetector() --- start"); LOGD0("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- start");
vector<Rect> objects; vector<Rect> objects;
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
{ {
pthread_cond_signal(&objectDetectorThreadStartStop); pthread_cond_signal(&objectDetectorThreadStartStop);
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- before waiting"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting");
stateSeparatedObjectDetector=OBJECT_DETECTOR_WAITING_IMAGE; stateSeparatedObjectDetector=OBJECT_DETECTOR_WAITING_IMAGE;
pthread_cond_wait(&objectDetectorRun, &mutex); pthread_cond_wait(&objectDetectorRun, &mutex);
stateSeparatedObjectDetector=OBJECT_DETECTOR_HANDLING_IMAGE; stateSeparatedObjectDetector=OBJECT_DETECTOR_HANDLING_IMAGE;
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- after waiting"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting");
} }
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
...@@ -356,54 +230,54 @@ void DetectionBasedTracker::workcycleObjectDetector() ...@@ -356,54 +230,54 @@ void DetectionBasedTracker::workcycleObjectDetector()
while(stateThread == STATE_THREAD_WORKING) while(stateThread == STATE_THREAD_WORKING)
{ {
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- next step"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- next step");
if (! isFirstStep) { if (! isFirstStep) {
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- before waiting"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- before waiting");
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
stateSeparatedObjectDetector=OBJECT_DETECTOR_WAITING_IMAGE; stateSeparatedObjectDetector=OBJECT_DETECTOR_WAITING_IMAGE;
pthread_cond_wait(&objectDetectorRun, &mutex); pthread_cond_wait(&objectDetectorRun, &mutex);
stateSeparatedObjectDetector=OBJECT_DETECTOR_HANDLING_IMAGE; stateSeparatedObjectDetector=OBJECT_DETECTOR_HANDLING_IMAGE;
pthread_mutex_unlock(&mutex); pthread_mutex_unlock(&mutex);
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- after waiting"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- after waiting");
} else { } else {
isFirstStep=false; isFirstStep=false;
} }
if (stateThread != STATE_THREAD_WORKING) { 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; break;
} }
if (imageSeparateDetecting.empty()) { if (imageSeparateDetecting.empty()) {
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- imageSeparateDetecting is empty, continue"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- imageSeparateDetecting is empty, continue");
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); imageSeparateDetecting.size().width, imageSeparateDetecting.size().height, (void*)imageSeparateDetecting.data);
int64 t1_detect=getTickCount(); int64 t1_detect=getTickCount();
int minObjectSize=parameters.minObjectSize; int minObjectSize=detectionBasedTracker.parameters.minObjectSize;
Size min_objectSize=Size(minObjectSize, minObjectSize); Size min_objectSize=Size(minObjectSize, minObjectSize);
int maxObjectSize=parameters.maxObjectSize; int maxObjectSize=detectionBasedTracker.parameters.maxObjectSize;
Size max_objectSize(maxObjectSize, maxObjectSize); Size max_objectSize(maxObjectSize, maxObjectSize);
cascadeInThread.detectMultiScale( imageSeparateDetecting, objects, cascadeInThread.detectMultiScale( imageSeparateDetecting, objects,
parameters.scaleFactor, parameters.minNeighbors, 0 detectionBasedTracker.parameters.scaleFactor, detectionBasedTracker.parameters.minNeighbors, 0
|CV_HAAR_SCALE_IMAGE |CV_HAAR_SCALE_IMAGE
, ,
min_objectSize, min_objectSize,
max_objectSize max_objectSize
); );
LOGD("DetectionBasedTracker::workcycleObjectDetector() --- end handling imageSeparateDetecting"); LOGD("DetectionBasedTracker::SeparateDetectionWork::workcycleObjectDetector() --- end handling imageSeparateDetecting");
if (stateThread != STATE_THREAD_WORKING) { 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; break;
} }
...@@ -411,7 +285,7 @@ void DetectionBasedTracker::workcycleObjectDetector() ...@@ -411,7 +285,7 @@ void DetectionBasedTracker::workcycleObjectDetector()
int64 dt_detect=t2_detect-t1_detect; int64 dt_detect=t2_detect-t1_detect;
double dt_detect_ms=((double)dt_detect)/freq * 1000.0; 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); pthread_mutex_lock(&mutex);
if (!shouldObjectDetectingResultsBeForgot) { if (!shouldObjectDetectingResultsBeForgot) {
...@@ -441,9 +315,10 @@ void DetectionBasedTracker::workcycleObjectDetector() ...@@ -441,9 +315,10 @@ void DetectionBasedTracker::workcycleObjectDetector()
pthread_mutex_unlock(&mutex); 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 //FIXME: TODO: should add quickStop functionality
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
...@@ -453,28 +328,27 @@ void DetectionBasedTracker::stop() ...@@ -453,28 +328,27 @@ void DetectionBasedTracker::stop()
return; return;
} }
stateThread=STATE_THREAD_STOPPING; 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_signal(&objectDetectorRun);
pthread_cond_wait(&objectDetectorThreadStartStop, &mutex); 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); pthread_mutex_unlock(&mutex);
} }
void DetectionBasedTracker::resetTracking() void DetectionBasedTracker::SeparateDetectionWork::resetTracking()
{ {
LOGD("DetectionBasedTracker::resetTracking"); LOGD("DetectionBasedTracker::SeparateDetectionWork::resetTracking");
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
if ((stateThread == STATE_THREAD_WORKING) && (stateSeparatedObjectDetector == OBJECT_DETECTOR_HANDLING_IMAGE)) { 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; shouldObjectDetectingResultsBeForgot=true;
//cascadeInThread.setStopFlag();//FIXME: TODO: this feature also should be contributed to OpenCV //cascadeInThread.setStopFlag();//FIXME: TODO: this feature also should be contributed to OpenCV
} else { } 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(); resultDetect.clear();
trackedObjects.clear();
isObjectDetectingReady=false; isObjectDetectingReady=false;
...@@ -482,6 +356,226 @@ void DetectionBasedTracker::resetTracking() ...@@ -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) void DetectionBasedTracker::updateTrackedObjects(const vector<Rect>& detectedObjects)
{ {
enum { enum {
...@@ -730,12 +824,9 @@ bool DetectionBasedTracker::setParameters(const Parameters& params) ...@@ -730,12 +824,9 @@ bool DetectionBasedTracker::setParameters(const Parameters& params)
return false; return false;
} }
pthread_mutex_lock(&mutex); separateDetectionWork->lock();
parameters=params; parameters=params;
separateDetectionWork->unlock();
pthread_mutex_unlock(&mutex);
return true; return true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment