4

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

  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 帧(全黑): 第 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

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

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

于 2012-10-22T18:02:58.527 回答