【问题标题】:OpenCV features detection and matching - segfault on drawing matchesOpenCV 特征检测和匹配 - 绘图匹配时的段错误
【发布时间】:2012-10-11 15:45:14
【问题描述】:

关注this example,
我正在尝试构建一个应用程序来识别视频中的对象。
我的程序由以下步骤组成(参见下面每个步骤的代码示例):

  1. 将要识别的对象的图像读入cv::Mat对象。
  2. 检测对象中的关键点并计算描述符。
  3. 阅读视频的每一帧,
  4. 检测关键点并计算帧的描述符,
  5. 将帧的描述符与对象的描述符相匹配,
  6. 绘制结果。

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

谢谢!

注意事项:

  1. 程序在段错误之前运行了几帧。崩溃发生在第 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 帧(全黑):

第 23 帧(发生段错误):

【问题讨论】:

    标签: c++ opencv segmentation-fault surf object-detection


    【解决方案1】:

    您是否尝试过在调试器中运行您的程序?

    只是猜测,当没有可绘制的匹配项时,drawmatch 会出现段错误?尝试在drawMatches 之前添加if (!matches.empty())。顺便问一下,你确定matches 在调用matcher.matches(...) 之前已经清空了吗?如果不是,您应该在每次循环迭代时手动执行。

    【讨论】:

    • 谢谢您的回复。是的,我确实尝试通过调试器运行程序,但由于我使用的是 OpenCV DLL,我无法进入库的代码。我只知道问题出在drawMatches。此外,我怀疑这是图书馆本身的问题;我假设我以某种方式错误地使用它。此外,问题不在于matches,因为还有其他空帧,其中matches 为空,因此不会出现问题。顺便说一句,我每次迭代都会清空 matches 对象(尽管我认为这不是真的必要);我只是没有在这里写。
    • 尝试在调试模式下编译 OpenCV。使用 CMake 应该非常简单。使用 minGW,您应该生成 linux makefile。但它也适用于 VC++ 2010 express,就在上周。
    • 谢谢,这是个好主意,但解决方案实际上要简单得多,由于缺乏关注,我错过了它(见我的回答)。
    【解决方案2】:

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

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

    说明:

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

    matcher.match(descriptors_frame, descriptors_object, matches);
    

    signature of this method

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

    这意味着matches 包含匹配来自 trainDescriptors queryDescriptors
    在我的例子中,列车描述符属于object,查询描述符属于frame,所以matches 包含匹配from object to frame

    drawMatches 中的The signature

    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);
    

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

    【讨论】:

      猜你喜欢
      • 2014-04-04
      • 2015-04-01
      • 2018-04-27
      • 1970-01-01
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多