2

マルチスレッドの顔検出器を実装しようとしています。問題は、カメラからいくつかのフレームをキャプチャして処理した後、プログラムが予期せず動作を停止することです。コードは次のとおりです。

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 を独自のプライベート クラス メンバーとして指定すると、正常に動作していました。しかし、スレッドが作成されるたびにメインループで、カスケードファイルをロードするたびにパフォーマンスが低下するようです。だから私の質問は、スレッドに共通のカスケードファイルがあるときにプログラムが停止するのはなぜですか?

4

1 に答える 1

3

デッドロックがあるようです。関数 CascadeClassifier::detectMultiScale が原因であると思われます。まず、複数のスレッドに対して1 つの同じ cascadeClassifierがあります。これらのスレッドが detectMultiScale を呼び出す場合、同じインスタンスで呼び出します。(これは、すべての操作が同じファイルに送られる異なるスレッドで同じファイル ハンドルを使用するようなものです。)

さらにdetectMultiScaleはすでにマルチスレッド/並列化されています。ドキュメントではそれは言う

関数は TBB ライブラリで並列化されます。

そのため、異なるスレッドから detectMultiScale を数回呼び出すことで、CascadeClassifier の唯一のインスタンスをデッド ロックする可能性があります。

ところで、このスレッドはさらに役立つかもしれません

于 2013-03-15T09:59:33.560 に答える