2012-10-21 38 views
4

正在关注this example
我试图构建一个应用程序来识别视频中的对象。
我的程序由以下步骤(见下面每一个步骤的代码示例):OpenCV功能检测和匹配 - 在绘图匹配上的段错误

  1. 阅读对象的图像被识别为cv::Mat对象。
  2. 检测对象中的关键点和计算描述符。
  3. 阅读视频的每个帧,
  4. 检测关键点,并计算帧的描述符,
  5. 匹配帧的对象的描述符的描述符,
  6. 绘图结果。

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

谢谢!

注:

  1. 程序运行的内存设计缺陷前几帧。崩溃发生在第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 

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

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

步骤P 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); 
} 

截图只是段错误之前: Screenshot

帧22(全黑): Frame 22

框架23(其中段错误发生时): Frame 23

回答

5

问题出在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包含匹配项trainDescriptorsqueryDescriptors
在我的情况下,列车的描述是object和查询描述符是在frame,所以matches包含匹配objectframe

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

的方法寻找不正确的图像在比赛中的坐标,这可能导致试图访问“越界”像素;因此分段错误。

+0

你是一个救命的人:)很多谢谢 –

0

您是否尝试过在一个调试器中运行你的前卫?

只是一个猜测,当没有匹配绘制时,drawmatch是segfaulting?尝试在drawMatches之前加if (!matches.empty())。顺便问一下,你确定matches在致电matcher.matches(...)之前被清空了吗?如果不是,您应该在每次循环迭代时手动执行。

+0

谢谢你的回复。是的,我曾尝试通过调试器来运行该程序,但由于我使用的是OpenCV DLL,因此无法进入库的代码。我所知道的是,问题出在'drawMatches'上。此外,我怀疑这是图书馆本身的问题。我假设我以某种方式使用它错了。另外,这个问题与'matches'不匹配,因为还有其他空框架,'matches'是空的,并且不会发生问题。顺便说一句,我每次迭代都清空'matches'对象(尽管我不认为这是必要的)。我只是没有写在这里。 – EyalAr

+1

尝试在调试模式下编译OpenCV。这应该是非常简单的使用CMake。使用minGW,你应该生成linux makefiles。但它也适用于VC++ 2010 express,上周才这样做。 – remi

+0

谢谢,这是一个好主意,但解决方案实际上要简单得多,而我由于缺乏关注而错过了它(请参阅我的答案)。 – EyalAr