2014-11-03 116 views
2

我试图使用OpenCV 2.4.9从图像中提取轮廓线。
findContours函数完成大部分工作,但它返回类型为vector < vector <Point> >的轮廓线
。 我需要将它们转换为vector <Mat>以供以后使用。
我使用Mat类的构造函数来完成这项工作,一切正常,直到我通过引用调用将一个函数的结果传递给另一个函数为止。 下面的代码重新错误:在主要发生OpenCV:矢量<vector <Point>>转换为矢量<Mat>,引用问题引用

#include <iostream> 
#include <opencv2/opencv.hpp> 
using namespace std; 
using namespace cv; 

void getCont(Mat& img, vector<Mat>& cLines, int thresh) 
{ 
    //binarize the image 
    Mat imgBin; 
    threshold(img, imgBin, thresh, 255, THRESH_BINARY_INV); 

    //find contour lines 
    vector<vector<Point>> contours; 
    findContours(imgBin, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE); 

    //convert vector<vector<Point>> to vector<Mat> 
    for (int i = 0; i < contours.size(); i++) 
     cLines.push_back(Mat(contours[i])); 

    cerr << "cLines[0] in getCont:\n"; 
    cerr << "cLines[0].rows: " << cLines[0].rows << "\n"; 
    cerr << "cLines[0].cols: " << cLines[0].cols << "\n"; 
    cerr << "cLines[0].channels(): " << cLines[0].channels() << "\n"; 
    cerr << "cLines[0].type(): " << cLines[0].type() << "\n"; 
    cerr << "cLines[0].row(0): " << cLines[0].row(0) << "\n"; 
    cerr << endl << endl; 
} 

int main() 
{ 
    Mat img = imread("leaf.jpg", 0); 
    int thresh = 124; 

    vector<Mat> cLines; 
    getCont(img, cLines, thresh); 

    cerr << "cLines[0] in main:\n"; 
    cerr << "cLines[0].rows: " << cLines[0].rows << "\n"; 
    cerr << "cLines[0].cols: " << cLines[0].cols << "\n"; 
    cerr << "cLines[0].channels(): " << cLines[0].channels() << "\n"; 
    cerr << "cLines[0].type(): " << cLines[0].type() << "\n"; 
    cerr << "cLines[0].row(0): " << cLines[0].row(0) << "\n"; 

    return 0; 
} 

的错误,在return语句前行,当我试图打印出的cLines第一要素的第一行。对于不同的输入图像,我要么收到一条消息,告诉我,.exe工作不正常,必须退出或实际打印输出值,但它们与getCont函数的输出不同(在main中,I得到负值,所以它看起来像有一些溢出)。我在Windows 8,64位机器上使用Visual Studio 2013 Express(但我使用的是OpenCV的x86 DLL库)。任何人都可以在不同的系统上重现错误?

我以为有一些隐式类型转换,所以我在getContmain中打印出cLines的大小和类型,但结果是一样的。当我将getCont函数的代码写入main时,错误不会发生,这样我就可以避免附加的函数调用。 此外,一切正常,当我通过以下替换循环

for (int i = 0; i < contours.size(); i++) 
    cLines.push_back(Mat(contours[i])); 

for (int i = 0; i < contours.size(); i++) 
{ 
    vector<Point> currPts = contours.at(i); 
    Mat currLine(currPts.size(), 1, CV_32SC2); 
    for (int j = 0; j < currPts.size(); j++) 
    { 
     currLine.at<Vec2i>(j, 0).val[0] = currPts.at(j).x; 
     currLine.at<Vec2i>(j, 0).val[1] = currPts.at(j).y; 
    } 
    cLines.push_back(currLine); 
} 

有谁知道这是怎么回事?

+0

不应该声明'cLines'类似于'Mat currLine(currPts.size(),1,CV_32SC2);'?在你的主体中,没有任何地方说'CV_32SC2'。 – 2014-11-03 12:56:52

+0

@ a-Jays:谢谢你的回答。当我声明cLines时,我没有明确地设置类型,但cLines [0] .type()的输出是12(它是枚举中的CV_32SC2),都在main和getCont中。 – Kuchenschaf 2014-11-03 13:31:03

+0

适合我。您是否成功加载图像?你可以尝试'imshow'来验证。 – herohuyongtao 2014-11-03 14:17:11

回答

2

您正在使用正确的构造函数,但错误地接受了第二个参数的默认值。为Mat构造以std::vector作为输入声明:

//! builds matrix from std::vector with or without copying the data 
template<typename _Tp> explicit Mat(const vector<_Tp>& vec, bool copyData=false); 

online documentation为CV ::垫构造规定:

copyData – Flag to specify whether the underlying data of the STL vector or the old-style CvMat or IplImage should be copied to (true) or shared with (false) the newly constructed matrix. When the data is copied, the allocated buffer is managed using Mat reference counting mechanism. While the data is shared, the reference counter is NULL, and you should not deallocate the data until the matrix is not destructed.

你需要做的:

cLines.push_back(Mat(contours[i],true));

否则,当您返回到main和数据缓冲区时,向量将超出范围在getCont中声明的vector<vector<Point>> contours将被释放。

对于cv::VecPoint_,并且Point3_,为copyData默认为真,不像std::vector

相关问题