4

この例に従って、
ビデオ内のオブジェクトを認識するアプリケーションを構築しようとしています。
私のプログラムは次のステップで構成されています (以下の各ステップのコード サンプルを参照してください)。

  1. 認識対象の画像をオブジェクトに読み込みcv::Matます。
  2. オブジェクト内のキーポイントを検出し、記述子を計算します。
  3. ビデオの各フレームを読み取り、
  4. キーポイントを検出し、フレームの記述子を計算します。
  5. フレームの記述子をオブジェクトの記述子に一致させます。
  6. 結果を描画します。

問題: 6 番目のステップでセグメンテーション違反が発生します (以下のコードを参照)。
質問:何が原因で、どうすれば修正できますか?

ありがとうございました!

ノート:

  1. プログラムは、segfault の前に数フレーム実行されます。クラッシュはフレーム 23 で発生します。フレーム 23 は、コンテンツを含む (完全に黒ではない) ビデオの最初のフレームです。
  2. の行を削除することにより、クラッシュdrawMatches(...);はありません。
  3. Windows 7、OpenCV 2.4.2、MinGW で動作します。

デバッグ試行:

gdb を介してプログラムを実行すると、次のメッセージが表示されます。

Program received signal SIGSEGV, Segmentation fault.
0x685585db in _fu156___ZNSs4_Rep20_S_empty_rep_storageE () from c:\opencv\build\install\bin\libopencv_features2d242.dll

ステップ 1 - オブジェクトの画像の読み取り:

Mat object;
object = imread(OBJECT_FILE, CV_LOAD_IMAGE_GRAYSCALE);

ステップ 2 - オブジェクト内のキーポイントの検出と記述子の計算:

SurfFeatureDetector detector(500);
SurfDescriptorExtractor extractor;
vector<KeyPoint> keypoints_object;
Mat descriptors_object;
detector.detect(object , keypoints_object);
extractor.compute(object, keypoints_object, descriptors_object);

手順 3 ~ 6:

VideoCapture capture(VIDEO_FILE);
namedWindow("Output",0);
BFMatcher matcher(NORM_L2,true);
vector<KeyPoint> keypoints_frame;
vector<DMatch> matches;
Mat frame,
    output,
    descriptors_frame;

while (true)
{
    //step 3:
    capture >> frame;
    if(frame.empty())
    {
        break;
    }
    cvtColor(frame,frame,CV_RGB2GRAY);

    //step 4:
    detector.detect(frame, keypoints_frame);
    extractor.compute(frame, keypoints_frame, descriptors_frame);

    //step 5:
    matcher.match(descriptors_frame, descriptors_object, matches);

    //step 6:
    drawMatches(object, keypoints_object, frame, keypoints_frame, matches, output);
    imshow("Output", output);
    waitKey(1);
}

セグメンテーション違反直前のスクリーンショット: スクリーンショット

フレーム 22 (完全な黒): フレーム 22

フレーム 23 (セグメンテーション違反が発生): フレーム 23

4

2 に答える 2

5

問題は、のパラメータの順序にありましたdrawMatches
正しい順序は次のとおりです。

drawMatches(frame, keypoints_frame, object, keypoints_object, matches, output);

説明:

ステップ5では、オブジェクトのmatchメソッドを使用しています。matcher

matcher.match(descriptors_frame, descriptors_object, matches);

このメソッドのシグネチャは次のとおりです。

void match( const Mat& queryDescriptors, const Mat& trainDescriptors,
            CV_OUT vector<DMatch>& matches, const Mat& mask=Mat() ) const;

これは、からmatchesの一致が含まれていることを意味します。 私の場合、トレイン記述子はとのであり、クエリ記述子はのであるため、からの一致が含まれています。 trainDescriptors queryDescriptors
objectframematchesobject frame

drawMatches署名

void drawMatches( const Mat& img1, const vector<KeyPoint>& keypoints1,
                  const Mat& img2, const vector<KeyPoint>& keypoints2,
                  const vector<DMatch>& matches1to2,
                  ... );

パラメータの順序がdrawMatches正しくない場合:

drawMatches(object, keypoints_object, frame, keypoints_frame, matches, output);

このメソッドは、誤った画像内の一致の座標を検索します。これにより、「範囲外」のピクセルにアクセスしようとする可能性があります。したがって、セグメンテーション違反。

于 2012-10-23T09:17:45.233 に答える
0

デバッガーでプログラムを実行してみましたか?

推測ですが、ドローマッチはドローマッチがない場合にセグメンテーション違反ですか?? if (!matches.empty())の前に追加してみてくださいdrawMatches。ところで、matches呼び出す前に は本当に空matcher.matches(...)ですか? そうでない場合は、ループの繰り返しごとに手動で行う必要があります。

于 2012-10-22T18:02:58.527 に答える