Skip to content

Commit

Permalink
Removed async thread timing API, added async thread shutdown
Browse files Browse the repository at this point in the history
  • Loading branch information
ayberkozgur committed Nov 29, 2014
1 parent dfe4740 commit fe35288
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 99 deletions.
26 changes: 0 additions & 26 deletions include/chilitags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,32 +204,6 @@ TagCornerMap find(
*/
void setDetectionPeriod(int period);

#ifdef HAS_MULTITHREADING
/**
* @brief Gets the latest idle time in case of asynchronous detection
*
* In `ASYNC_DETECT_PERIODICALLY` and `ASYNC_DETECT_ALWAYS` triggers, returns
* the latest idle time of the asynchronous detection thread. Together with
* `getLatestAsyncDetectionWorkMillis()`, they make 100% of the detection
* thread's time.
*
* @return Detection thread's latest idle time in ms
*/
float getLatestAsyncDetectionIdleMillis();

/**
* @brief Gets the latest work time in case of asynchronous detection
*
* In `ASYNC_DETECT_PERIODICALLY` and `ASYNC_DETECT_ALWAYS` triggers, returns
* the latest work time of the asynchronous detection thread.Together with
* `getLatestAsyncDetectionIdleMillis()`, they make 100% of the detection
* thread's time.
*
* @return Detection thread's latest work time in ms
*/
float getLatestAsyncDetectionWorkMillis();
#endif

/**
Preset groups of parameters (for setPerformance()) to adjust the
compromise between processing time and accuracy of detection.
Expand Down
48 changes: 21 additions & 27 deletions samples/multithreaded/async-detection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,48 +70,42 @@ int main(int argc, char* argv[])

cv::namedWindow("DisplayChilitags");

bool showPeriodic = true;

char keyPressed;
float trackTime = 0, idleTime = 0, detectTime = 0;
const char* trigName = "DETECT_PERIODICALLY";
chilitags::Chilitags::DetectionTrigger trig = chilitags::Chilitags::DETECT_PERIODICALLY;
while ('q' != (keyPressed = (char) cv::waitKey(1))) {

// toggle the processing mode, according to user input
if (keyPressed == 't') showPeriodic = !showPeriodic;
if(keyPressed == 't'){
if(trig == chilitags::Chilitags::DETECT_PERIODICALLY){
trig = chilitags::Chilitags::ASYNC_DETECT_PERIODICALLY;
trigName = "ASYNC_DETECT_PERIODICALLY";
}
else if(trig == chilitags::Chilitags::ASYNC_DETECT_PERIODICALLY){
trig = chilitags::Chilitags::ASYNC_DETECT_ALWAYS;
trigName = "ASYNC_DETECT_ALWAYS";
}
else{
trig = chilitags::Chilitags::DETECT_PERIODICALLY;
trigName = "DETECT_PERIODICALLY";
}
}

capture.read(inputImage);

cv::Mat outputImage = inputImage.clone();

int64 startTime = cv::getTickCount();
auto tags = chilitags.find(inputImage, showPeriodic ? chilitags::Chilitags::ASYNC_DETECT_PERIODICALLY : chilitags::Chilitags::ASYNC_DETECT_ALWAYS);
int64 endTime = cv::getTickCount();
auto tags = chilitags.find(inputImage, trig);
drawTags(outputImage, tags);

//Print tracking time
trackTime = 0.98f*trackTime + 0.02f*1000.0f*(((float)endTime - (float)startTime)/cv::getTickFrequency());
cv::putText(outputImage,
cv::format("[Main thread] Tracking time %4.2f ms", trackTime),
cv::Point(8,20),
cv::FONT_HERSHEY_SIMPLEX, 0.5, COLOR);

//Print detection idle time
idleTime = 0.98f*idleTime + 0.02f*chilitags.getLatestAsyncDetectionIdleMillis();
cv::putText(outputImage,
cv::format("[Detection thread] Idle time %4.2f ms", idleTime),
cv::Point(8,36),
cv::FONT_HERSHEY_SIMPLEX, 0.5, COLOR);

//Print detection work time
detectTime = 0.98f*detectTime + 0.02f*chilitags.getLatestAsyncDetectionWorkMillis();
//Print detection trigger
cv::putText(outputImage,
cv::format("[Detection thread] Work time %4.2f ms", detectTime),
cv::Point(8,52),
cv::format("Detection trigger: %s (press 't' to toggle)", trigName),
cv::Point(8,yRes - 24),
cv::FONT_HERSHEY_SIMPLEX, 0.5, COLOR);

//Print detection trigger
cv::putText(outputImage,
cv::format("Detection trigger: %s (press 't' to toggle)", showPeriodic ? "ASYNC_DETECT_PERIODICALLY" : "ASYNC_DETECT_ALWAYS"),
cv::format("Run 'top -H -p `pgrep async-detection`' to see running threads", trigName),
cv::Point(8,yRes - 8),
cv::FONT_HERSHEY_SIMPLEX, 0.5, COLOR);

Expand Down
38 changes: 16 additions & 22 deletions src/Chilitags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -105,16 +105,6 @@ void setDetectionPeriod(int period) {
mCallsBeforeDetection = period;
}

#ifdef HAS_MULTITHREADING
float getLatestAsyncDetectionIdleMillis(){
return mDetect.getLatestAsyncIdleMillis();
}

float getLatestAsyncDetectionWorkMillis(){
return mDetect.getLatestAsyncWorkMillis();
}
#endif

TagCornerMap find(
const cv::Mat &inputImage,
DetectionTrigger detectionTrigger){
Expand All @@ -130,6 +120,22 @@ TagCornerMap find(
mResizedGrayscaleInput = mEnsureGreyscale(inputImage);
}

//Take care of the background thread (if exists)
#ifdef HAS_MULTITHREADING
switch(detectionTrigger){
case DETECT_ONLY:
case TRACK_ONLY:
case TRACK_AND_DETECT:
case DETECT_PERIODICALLY:
mDetect.shutdownBackgroundThread();
break;
case ASYNC_DETECT_PERIODICALLY:
case ASYNC_DETECT_ALWAYS:
mDetect.launchBackgroundThread(mTrack);
break;
}
#endif

// Do detection/tracking/both depending on detection trigger
TagCornerMap tags;
switch(detectionTrigger){
Expand Down Expand Up @@ -167,7 +173,6 @@ TagCornerMap find(

#ifdef HAS_MULTITHREADING
case ASYNC_DETECT_PERIODICALLY:
mDetect.launchBackgroundThread(mTrack);
mCallsBeforeNextDetection--;

//If the detection period is reached, deliver new frame to background detection thread
Expand All @@ -178,7 +183,6 @@ TagCornerMap find(
return scaleBy(mTrack(mResizedGrayscaleInput), scaleFactor);

case ASYNC_DETECT_ALWAYS:
mDetect.launchBackgroundThread(mTrack);
mDetect(mResizedGrayscaleInput, tags); //This does not update tags, nor does it block for computation
return scaleBy(mTrack(mResizedGrayscaleInput), scaleFactor);
#endif
Expand Down Expand Up @@ -277,16 +281,6 @@ void Chilitags::setMinInputWidth(int minWidth) {
mImpl->setMinInputWidth(minWidth);
}

#ifdef HAS_MULTITHREADING
float Chilitags::getLatestAsyncDetectionIdleMillis(){
return mImpl->getLatestAsyncDetectionIdleMillis();
}

float Chilitags::getLatestAsyncDetectionWorkMillis(){
return mImpl->getLatestAsyncDetectionWorkMillis();
}
#endif

TagCornerMap Chilitags::find(
const cv::Mat &inputImage,
DetectionTrigger trigger
Expand Down
28 changes: 11 additions & 17 deletions src/Detect.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ Detect::Detect() :
mBackgroundRunning(false),
mNeedFrame(true),
mInputCond(PTHREAD_COND_INITIALIZER),
mInputLock(PTHREAD_MUTEX_INITIALIZER),
mLatestAsyncIdleMillis(0),
mLatestAsyncWorkMillis(0)
mInputLock(PTHREAD_MUTEX_INITIALIZER)
#endif
{
}
Expand Down Expand Up @@ -126,6 +124,16 @@ void Detect::launchBackgroundThread(Track& track)
}
}

void Detect::shutdownBackgroundThread()
{
if(mBackgroundRunning){
pthread_mutex_lock(&mInputLock);
mBackgroundShouldRun = false;
pthread_cond_signal(&mInputCond);
pthread_mutex_unlock(&mInputLock);
}
}

void* Detect::dispatchRun(void* args)
{
static_cast<Detect*>(args)->run();
Expand All @@ -138,33 +146,19 @@ void Detect::run()
pthread_mutex_lock(&mInputLock);

//Wait for the input frame to arrive
int64 startTime = cv::getTickCount();
pthread_cond_wait(&mInputCond, &mInputLock); //This releases the lock while waiting
mLatestAsyncIdleMillis = 1000.0f*(((float)cv::getTickCount() - (float)startTime)/cv::getTickFrequency());

mNeedFrame = false;

startTime = cv::getTickCount();
doDetection(mTags);
mTrack->update(mTags);
mLatestAsyncWorkMillis = 1000.0f*(((float)cv::getTickCount() - (float)startTime)/cv::getTickFrequency());

mNeedFrame = true;

pthread_mutex_unlock(&mInputLock);
}
mBackgroundRunning = false;
}

float Detect::getLatestAsyncIdleMillis()
{
return mLatestAsyncIdleMillis;
}

float Detect::getLatestAsyncWorkMillis()
{
return mLatestAsyncWorkMillis;
}
#endif

} /* namespace chilitags */
Expand Down
9 changes: 2 additions & 7 deletions src/Detect.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,9 @@ class Detect {
void operator()(cv::Mat const& inputImage, TagCornerMap& tags);

#ifdef HAS_MULTITHREADING
float getLatestAsyncIdleMillis();

float getLatestAsyncWorkMillis();

void launchBackgroundThread(Track& track);

void shutdownBackgroundThread();
#endif

protected:
Expand Down Expand Up @@ -83,9 +81,6 @@ class Detect {
pthread_cond_t mInputCond;
pthread_mutex_t mInputLock;

float mLatestAsyncIdleMillis;
float mLatestAsyncWorkMillis;

static void* dispatchRun(void* args);
void run();
#endif
Expand Down

0 comments on commit fe35288

Please sign in to comment.