Многопоточное распознавание лиц перестает работать

Я пытаюсь реализовать многопоточный детектор лиц. Проблема в том, что после захвата и обработки некоторых кадров с камеры программа неожиданно перестает работать. Вот код:

cascadeClassifier cad;

class myThread: public QThread
{
private:
    Mat threadRoi;
    vector<Rect> faces;
protected:
    void run()
    {
        cad.detectMultiScale(threadRoi,faces,1.4,4,CV_HAAR_DO_CANNY_PRUNING|CV_HAAR_FIND_BIGGEST_OBJECT,Size(30,30));
        if ( !faces.empty())
                  rectangle(threadRoi,faces[0],Scalar(0,255,0),2);
    }
public:
    myThread(Mat &r)
    {
        threadRoi = r;
    }
    vector<Rect> getFaces()
    {
        return faces;
    }
};
int main()
{
    cad.load("C:/opencv/data/lbpcascades/lbpcascade_frontalface.xml");
    VideoCapture cap(0);
    Mat frame;
    while(1)
    {
       if(!cap.read(frame))   break;
       cvtColor(frame,frame_gray));
       myThread a(frame_gray(Rect(0,0,frame.cols/2,frame.rows/2));
       myThread b(frame_gray(Rect(frame.cols/4,0,frame.cols/2,frame.rows/2));
       myThread c(frame_gray(Rect(frame.cols/2,0,frame.cols/2,frame.rows/2));
       a.start();
       b.start();
       c.start();
       a.wait();
       b.wait();
       c.wait();
    }
    return 0;
}

Я заметил, что если я использую общий cascadeClassifier для всех потоков, возникает эта проблема. Когда я дал каждому потоку отдельные cascadeClassifiers как свои собственные частные члены класса, они работали нормально. Но в основном цикле всякий раз, когда создаются потоки, каждый раз загрузка каскадного файла не способствует производительности. Итак, мой вопрос: почему программа останавливается, когда потоки имеют общий каскадный файл?


person Barshan Das    schedule 15.03.2013    source источник
comment
хм, вы пытаетесь разделить его на 4 патча? в этом случае ваши цифры неверны (Тема b). Кроме того, почему тогда только 3 потока/патча? и это никогда не сработает, если лицо находится прямо посередине вашего исходного изображения, поскольку каждый из потоков видит только его часть.   -  person berak    schedule 15.03.2013
comment
Я делю один кадр (изображение) на три части. нить а для левой половины, нить с для правой половины, нить б для случая, когда лицо находится на линии отвода области а и области с. Проверьте параметры Rect(). На самом деле это отлично работает, когда у потоков есть свои собственные файлы классификатора.   -  person Barshan Das    schedule 15.03.2013


Ответы (1)


Кажется, что есть мертвый замок. Я подозреваю, что за это отвечает функция CascadeClassifier::detectMultiScale. Прежде всего, у вас есть один и тот же один и тот же cascadeClassifier для нескольких потоков. Когда эти потоки вызывают detectMultiScale, они вызывают его в одном и том же экземпляре. (Это похоже на использование одного и того же дескриптора файла в разных потоках, когда все операции выполняются в одном и том же файле.)

Далее, detectMultiScale уже многопоточен/распараллелен. В документах говорится

Функция распараллелена с помощью библиотеки TBB.

поэтому вполне возможно, что вы заблокируете единственный экземпляр CascadeClassifier, вызвав detectMultiScale несколько раз из разных потоков.

Кстати, этот поток может помочь вам в дальнейшем

person Philipp Sch    schedule 15.03.2013