2011-11-04 58 views
6

我创建了一个共享库,用于从Delphi/Lazarus应用程序加载的轮廓检测。主应用程序将指针传递给库中的函数处理的位图。OpenCV指向位图处理的指针

下面是库中的函数。参数“img”是指向我的位图的指针。

extern "C" { 

    void detect_contour(int imgWidth, int imgHeight, unsigned char * img, int &x, int &y, int &w, int &h) 
    { 
    Mat threshold_output; 
    vector<vector<Point> > contours; 
    vector<Vec4i> hierarchy; 

    Mat src_gray; 
    int thresh = 100; 
     int max_thresh = 255; 
    RNG rng(12345); 

    /// Load source image and convert it to gray 
    Mat src(imgHeight, imgWidth, CV_8UC4); 
    int idx; 

    src.data = img; 

    /// Convert image to gray and blur it 
    cvtColor(src, src_gray, CV_BGRA2GRAY); 

    blur(src_gray, src_gray, Size(10,10)); 

    /// Detect edges using Threshold 
    threshold(src_gray, threshold_output, thresh, 255, THRESH_BINARY); 
    /// Find contours 
    findContours(threshold_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0)); 

    /// Approximate contours to polygons + get bounding rects and circles 
    vector<vector<Point> > contours_poly(contours.size()); 
    vector<Rect> boundRect(contours.size()); 
    vector<Point2f>center(contours.size()); 
    vector<float>radius(contours.size()); 

    int lArea = 0; 
    int lBigger = -1; 

    for(int i = 0; i < contours.size(); i++) 
     { 
     approxPolyDP(Mat(contours[i]), contours_poly[i], 3, true); 
     boundRect[i] = boundingRect(Mat(contours_poly[i])); 
     if(lArea < boundRect[i].width * boundRect[i].height) 
     { 
      lArea = boundRect[i].width * boundRect[i].height; 
      lBigger = i; 
     } 
     } 

    if(lBigger > -1) 
    { 
     x = boundRect[lBigger].x; 
     y = boundRect[lBigger].y; 
     w = boundRect[lBigger].width; 
     h = boundRect[lBigger].height; 
    } 
    } 
} 

从德尔福的一面,我传递一个指向该结构的阵列:

TBGRAPixel = packed record 
    blue, green, red, alpha: byte; 
end; 

我需要处理内存中的位图,这就是为什么我不加载来自库内的文件。

问题是:这是一个正确的方式来分配一个位图到cv :: Mat吗?

我问这是因为代码在Linux中没有问题,但在与Mingw编译的Windows上失败。

注:它无法与这条线SIGSEGV:

blur(src_gray, src_gray, Size(10,10)); 

编辑:只有当我编译的OpenCV在Release模式,在调试模式下它的工作原理确定的SIGSEGV提高。

在此先感谢, 莱昂纳多。

回答

1

所以要创建的图像是这样的:

Mat src(imgHeight, imgWidth, CV_8UC4); 
int idx; 

src.data = img; 

第一个声明和实例化 垫SRC(imgHeight,imgWidth,CV_8UC4)将分配内存为新的图像和自动跟踪一个引用计数器对分配内存的引用数量。 然后你通过

变异实例变量src.data = img;

当实例src超出作用域时,析构函数被调用并且极有可能试图释放src.data中的内存,这是您分配的内存,这可能会导致分段错误。正确的方法来做到这一点是不会改变对象的实例变量,而是简单地使用正确的构造函数时你实例源:

Mat src(imgHeight, imgWidth, CV_8UC4, img); 

这样一来,您只需创建一个矩阵头,并没有引用计数器或释放将由src的析构函数执行。

祝你好运!

编辑:我不确定段错误实际上是由于尝试错误地释放内存导致的,但不通过直接分配实例变量来中断数据抽象是一种很好的做法。

+0

谢谢乔纳斯。我尝试了你的建议,它可以在Linux上运行,但SIGSEGV在Windows上仍然存在。 – leonardorame