OpenCV具有检测和匹配功能 - 绘图匹配时的段错误

Eya*_*lAr 4 c++ opencv object-detection segmentation-fault surf

这个例子之后,
我正在尝试构建一个应用程序来识别视频中的对象.
我的程序由以下步骤组成(请参阅下面每个步骤的代码示例):

  1. 读取要识别的对象的图像到cv::Mat对象中.
  2. 检测对象和计算描述符中的关键点.
  3. 阅读视频的每一帧,
  4. 检测帧的关键点和计算描述符,
  5. 将框架的描述符与对象的描述符相匹配,
  6. 画出结果.

问题:第6步导致分段错误(参见下面的代码).
问题:是什么导致它,我该如何解决?

谢谢!

笔记:

  1. 该程序在segfault之前运行几帧.崩溃发生在帧23上,帧23是具有任何内容(即,不是完全黑色)的视频的第一帧.
  2. 通过消除线路drawMatches(...);没有崩溃.
  3. 在Windows 7,OpenCV 2.4.2,MinGW上运行.

Debuggind尝试:

通过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
Run Code Online (Sandbox Code Playgroud)

第1步 - 读取对象的图像:

Mat object;
object = imread(OBJECT_FILE, CV_LOAD_IMAGE_GRAYSCALE);
Run Code Online (Sandbox Code Playgroud)

第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);
Run Code Online (Sandbox Code Playgroud)

步骤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);
}
Run Code Online (Sandbox Code Playgroud)

在segfault之前的屏幕截图: 截图

第22帧(全黑): 框架22

第23帧(发生段错误): 第23帧

Eya*_*lAr 5

问题在于参数的顺序drawMatches.
正确的顺序是:

drawMatches(frame, keypoints_frame, object, keypoints_object, matches, output);
Run Code Online (Sandbox Code Playgroud)

说明:

在第5步中,我正在使用对象的match方法matcher:

matcher.match(descriptors_frame, descriptors_object, matches);
Run Code Online (Sandbox Code Playgroud)

这种方法签名

void match( const Mat& queryDescriptors, const Mat& trainDescriptors,
            CV_OUT vector<DMatch>& matches, const Mat& mask=Mat() ) const;
Run Code Online (Sandbox Code Playgroud)

这意味着,matches包含比赛 trainDescriptors queryDescriptors.
在我的情况下,列车描述符的object和查询描述符的frame,所以matches包含比赛object frame.

签名drawMatchesIS

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

drawMatches使用不正确的参数顺序调用时:

drawMatches(object, keypoints_object, frame, keypoints_frame, matches, output);
Run Code Online (Sandbox Code Playgroud)

该方法在不正确的图像中查找匹配的坐标,这可能导致尝试访问"越界"像素; 因此分割错误.