1

顔を検出するために OpenCV の Cascade Classifier を使用しています。Webcam のチュートリアルに従い、detectMultiScale を使用して、ラップトップの Webcam からビデオをストリーミングしている間に自分の顔を見つけて追跡することができました。

しかし、ラップトップの Web カメラから自分の写真を撮るとき、その画像を OpenCV にロードし、その画像に detectMultiScale を適用すると、何らかの理由で、カスケード分類子はその静止画像の顔を検出できません!

その静止画像は、ウェブカメラ ストリームからの 1 フレームであれば確実に検出されたはずですが、その 1 枚の画像を単独で撮影すると、何も検出されません。

これが私が使用するコードです(関連する行を選んだだけです):

共通のコード:

String face_cascade_name = "/path/to/data/haarcascades/haarcascade_frontalface_alt.xml";
CascadeClassifier face_cascade;

Mat imagePreprocessing(Mat frame) {
    Mat processed_frame;
    cvtColor( frame, processed_frame, COLOR_BGR2GRAY );
    equalizeHist( processed_frame, processed_frame );
    return processed_frame;
}

Web カメラ ストリーミングの顔検出の場合:

int detectThroughWebCam() {
    VideoCapture capture;
    Mat frame;
    if( !face_cascade.load( face_cascade_name ) ){ printf("--(!)Error loading face cascade\n"); return -1; };


    //-- 2. Read the video stream
    capture.open( -1 );
    if ( ! capture.isOpened() ) { printf("--(!)Error opening video capture\n"); return -1; }

    while ( capture.read(frame) )
    {
         if(frame.empty()) {
             printf(" --(!) No captured frame -- Break!");
             break;
         }
         //-- 3. Apply the classifier to the frame
         Mat processed_image = imagePreprocessing( frame);
         vector<Rect> faces;
         face_cascade.detectMultiScale( processed_frame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, Size(30, 30) );
         if (faces.size() > 0) cout << "SUCCESS" << endl;
         int c = waitKey(10);
         if( (char)c == 27 ) { break; } // escape
    }
    return 0;
}

私の静止画像の顔検出の場合:

void staticFaceDetection() {
    Mat image = imread("path/to/jpg/image");
    Mat processed_frame = imagePreprocessing(image);
    std::vector<Rect> faces;
    //-- Detect faces
    face_cascade.detectMultiScale( processed_frame, faces, 1.1, 2, 0|CV_HAAR_SCALE_IMAGE|CV_HAAR_FIND_BIGGEST_OBJECT, Size(30, 30) );
    if (faces.size() > 0) cout << "SUCCESS" << endl;
}

私の目には、これらのプロセスはどちらも同じですが (唯一の違いは、元の画像を取得する場所です)、ビデオ ストリーム バージョンは定期的に顔を検出しますが、静的メソッドは顔を見つけることができないようです。

ここで何か不足していますか?

4

2 に答える 2

0

それにはいくつかの理由が考えられます。

  1. 画像を低解像度で保存します。元の解像度で保存してみてください

  2. 非可逆圧縮。画像を .jpg ファイルに保存しますか? 圧縮が強すぎるのかもしれません。BMP ファイルとして保存してみてください (元の品質が保持されます)。

  3. 画像のフォーマット。メソッドが何をするのかわかりませんimagePreprocessing()が、次の問題が発生する可能性があります。カメラは特定の形式でビデオをキャプチャします (ほとんどのカメラは YUV を使用します)。通常、顔検出は最初の平面 Y で実行されます。画像を保存してディスクから RGB として読み取る場合、最初の平面で顔検出を実行してはなりません。これは「B」平面であり、青色には面に関する情報がほとんど保存されません。顔検出を実行する前に、画像が正しくグレースケールに変換されていることを確認してください。

  4. 画像の範囲。これはよくある間違いです。画像のダイナミック レンジが正しいことを確認します。場合によっては、誤ってすべての値に 255 を掛けて、画像全体を事実上白くすることがあります。

  5. faces画像の顔検出は正常に機能するかもしれませんが、顔検出後にベクトルを何らかの形でクリアします。別の間違いとして、別の画像ファイルを読み取った可能性があります。たとえば、画像をディレクトリ 'A' に保存したが、誤ってディレクトリ 'B' から読み取ったとします。

上記のいずれも役に立たない場合。以下のデバッグを行います。ビデオ フレーム 'i' の場合 - メモリに保存します。次に、それをディスクに保存し、ファイルからメモリに読み戻します。ここで最も重要な部分は、画像を比較することです。それらが異なる場合 - それが異なる顔検出結果の理由です。そうでない場合は、さらに調査が必要です。画像が同一ではないことは確かであり、それが問題です。ピクセル値の違いを取得し、差分画像を表示することで、画像が同一でない場所を確認できます。memcmp()2 つのメモリブロックを比較する機能を使用して画像を比較できます。幸運を

于 2015-05-31T09:24:16.763 に答える