0

Below is the code for a tracking module. A detector is launched and when it detects the object of interest, it creates a tracker object to track the object using camshift on a number of frames until the detector finds another object. The code seems to work fine when I comment out imshow and waitkey in the tracker. But when I call those functions, I get the following error when a new tracker (apart from the first one) is created:

QMetaMethod::invoke: Unable to invoke methods with return values in queued connections
QObject::startTimer: QTimer can only be used with threads started with QThread

I don't know if this is something happening within boost or opencv. Any ideas how I can fix this problem? Is there a better way to go about showing the user the position of the object of interest? Thanks a lot!

main:

#define FACE_DETECT_RATE 10
Tracker *currentTracker;

boost::mutex displayedImageMutex;
Mat imageToShow;     // image displayed by the main thread

void updateDisplayedImage(Mat image){
    if (displayedImageMutex.try_lock()){
       image.copyTo(imageToShow);
       displayedImageMutex.unlock()
    }
}

Rect detectorCallback(Rect faceRect){
    // the detector object returns the face it found here
    //  a tracker is supposed to track the face in the next set of frames
    Tracker tracker(faceRect);
    tracker.start(&updateDisplayedImage);
    currentTracker = &tracker;
    currentTracker->join();
}

int main(int argc, char **argv){
    VideoCapture capture(0);
    currentTracker = NULL;

    int frameCount = 0;

    while (true){
        Mat frame;
        capture >> frame;

        if (frameCount % FACE_DETECT_RATE == 0){
            Detector detector;
            detector.start(frame, &detectorCallback);
        }

        if (displayedImageMutex.try_lock()){
            if (imageToShow.data){
                imshow("Results", imageToShow);
                waitKey(1);
            }
            displayedImageMutex.unlock();
        }
    }
}

Tracker:

class Tracker{
private:
    boost::thread *trackerThread;

    void run(void (*imageUpdateFunc)(Mat)){
        while (true){
            try{
                ...
                //do camshift and stuff

                //show results
                //imshow("Stream", imageWithFace);
                //waitKey(10);
                imageUpdateFunc(imageWithFace);
                ...
                boost::this_thread::interruption_point();

            } catch (const boost::thread::interrupted&){
                break;
            }
        }
    }


public:
    Tracker(Rect faceRect){
        ...
    }   

    void start(void (*imageUpdateFunc)(Mat)){
        trackerThread = new boost::thread(&Tracker::run, this, imageUpdateFunc);
    }

    void stop(){
        trackerThread->interrupt();
    }

    void join(){
        trackerThread->join();
    }
};
Stralo
  • 474
  • 4
  • 16
  • 1
    what if you take the error msg serious, and ditch the boost::thread for a Qt one ? besides that, imshow()/waitKey() are a very fragile thing, don#t play nice with multithreading in general. if you want to use them, keep them in the main thread, and outsource your *processing* instead. – berak Aug 18 '14 at 21:49
  • @berak - I don't know much about Qt threads and I don't know how I can fix the problem by using Qthreads since the error message seems to imply I'm using a QTimer, which I'm not using in my code directly. I just tried having a method containing imshow() and waitKey() in my main thread and having my tracker call that method, but I still get the error. – Stralo Aug 18 '14 at 22:04
  • 1
    Maybe try sending images You want to show back to the main thread, and show them from there? The worker thread was still the caller of the method judging from Your last comment. The GUI functions are multithreaded themselves, and as @berak said, have problems with being in non-main threads.. – morynicz Aug 19 '14 at 12:16
  • @morynicz - I added a function that the tracker thread calls to update the image that will be later displayed by the main thread. And I added a mutex for the displayed image (please see modified code). Is this what you suggested? It works now, but I'm quite new to multithreading in c++, and I don't know if this might lead to problems in the future. How does it look to you guys? Thanks once again! – Stralo Aug 19 '14 at 14:37
  • Yep, that's what I had in mind. Not a multithreading grand master, but this looks decent IMHO. – morynicz Aug 19 '14 at 18:44
  • Sweet! Thanks a lot for the suggestions. I really appreciate it. – Stralo Aug 19 '14 at 21:26

0 Answers0