C++ OpenCV功能检测和匹配-图形匹配上的segfault

C++ OpenCV功能检测和匹配-图形匹配上的segfault,c++,opencv,segmentation-fault,surf,object-detection,C++,Opencv,Segmentation Fault,Surf,Object Detection,以下, 我正在尝试构建一个应用程序来识别视频中的对象。 我的程序由以下步骤组成(请参见下面每个步骤的代码示例): 将要识别的对象的图像读取到cv::Mat对象中 检测对象中的关键点并计算描述符 阅读视频的每一帧 检测关键点并计算帧描述符 将框架的描述符与对象的描述符匹配 得出结果 问题:第6步导致分段错误(参见下面的代码)。 问题:是什么原因造成的,我如何修复 谢谢大家! 注意事项: SurfFeatureDetector detector(500); SurfDescriptorExtract

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

  • 将要识别的对象的图像读取到
    cv::Mat
    对象中
  • 检测对象中的关键点并计算描述符
  • 阅读视频的每一帧
  • 检测关键点并计算帧描述符
  • 将框架的描述符与对象的描述符匹配
  • 得出结果
  • 问题:第6步导致分段错误(参见下面的代码)。
    问题:是什么原因造成的,我如何修复

    谢谢大家!

    注意事项:

    SurfFeatureDetector detector(500);
    SurfDescriptorExtractor extractor;
    vector<KeyPoint> keypoints_object;
    Mat descriptors_object;
    detector.detect(object , keypoints_object);
    extractor.compute(object, keypoints_object, descriptors_object);
    
    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);
    }
    
  • 程序在segfault之前运行数帧。崩溃发生在第23帧,该帧是视频中包含任何内容的第一帧(即并非完全黑色)
  • 通过删除
    drawMatches(…)的行没有故障
  • 在Windows7、OpenCV 2.4.2和MinGW上运行
  • 调试尝试:

    SurfFeatureDetector detector(500);
    SurfDescriptorExtractor extractor;
    vector<KeyPoint> keypoints_object;
    Mat descriptors_object;
    detector.detect(object , keypoints_object);
    extractor.compute(object, keypoints_object, descriptors_object);
    
    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);
    }
    
    通过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);
    
    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);
    }
    
    surfeaturedetector检测器(500);
    表面描述符牵引器;
    矢量关键点;
    Mat描述符\u对象;
    检测器。检测(对象、关键点和对象);
    计算(对象、关键点对象、描述符对象);
    
    步骤3-6:

    SurfFeatureDetector detector(500);
    SurfDescriptorExtractor extractor;
    vector<KeyPoint> keypoints_object;
    Mat descriptors_object;
    detector.detect(object , keypoints_object);
    extractor.compute(object, keypoints_object, descriptors_object);
    
    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);
    }
    
    视频捕获(视频文件);
    namedWindow(“输出”,0);
    BFMatcher匹配器(NORM_L2,true);
    矢量关键点;
    向量匹配;
    垫架,
    产出,
    描述符框架;
    while(true)
    {
    //步骤3:
    捕获>>帧;
    if(frame.empty())
    {
    打破
    }
    CVT颜色(边框、边框、CV_rgb2灰色);
    //步骤4:
    检测器。检测(帧、关键点和帧);
    计算(框架、关键点框架、描述符框架);
    //步骤5:
    匹配(描述符\框架,描述符\对象,匹配);
    //步骤6:
    drawMatches(对象、关键点\对象、帧、关键点\帧、匹配、输出);
    imshow(“输出”,Output);
    等待键(1);
    }
    
    故障前的屏幕截图:

    第22帧(全黑):

    第23帧(发生SEGFULT时):
    您是否尝试过在调试器中运行程序


    只是一个猜测,drawmatch在没有比赛的情况下会出错??如果(!matches.empty())
    drawMatches
    之前,请尝试添加
    。顺便问一下,在调用
    matcher.matches(…)
    之前,您确定
    matches
    已清空吗?如果没有,您应该在每次循环迭代时手动执行。

    问题在于
    drawMatches中参数的顺序。

    正确的顺序是:

    drawMatches(frame, keypoints_frame, object, keypoints_object, matches, output);
    
    说明:

    Mat object;
    object = imread(OBJECT_FILE, CV_LOAD_IMAGE_GRAYSCALE);
    
    在步骤5中,我使用
    matcher
    对象的
    match
    方法:

    matcher.match(descriptors_frame, descriptors_object, matches);
    
    问题是

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

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

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

    谢谢您的回复。是的,我确实尝试过通过调试器运行程序,但是因为我使用的是OpenCV DLL,所以我无法进入库的代码。我只知道问题出在
    drawMatches
    上。此外,我怀疑这是图书馆本身的问题;我想我用错了。另外,问题不在于
    匹配
    ,因为存在其他空帧,其中
    匹配
    为空,并且问题不会发生。顺便说一句,我在每次迭代中清空
    匹配的
    对象(尽管我认为这不是真的必要);我不是在这里写的。试着在调试模式下编译OpenCV。使用CMake应该非常简单。使用minGW,您应该生成linux生成文件。但它也适用于VC++2010 express,就在上周。谢谢你,这是个好主意,但解决方案实际上简单得多,由于注意力不够,我错过了它(见我的答案)。