OpenCV 指向位图处理的指针

发布于 2024-12-14 01:45:11 字数 2332 浏览 2 评论 0原文

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

这是库内的函数。参数“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;
    }
  }
}

从 Delphi 方面,我将一个指针传递给此结构的数组:

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

我需要在内存中处理位图,这就是为什么我不从库内部加载文件的原因。

问题是:这是将位图分配给 cv::Mat 的正确方法吗?

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

注意:它在这一行上失败并显示 SIGSEGV:

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

编辑:仅当我在发布模式下编译 OpenCV 时才会引发 SIGSEGV,在调试模式下它可以正常工作。

提前致谢, 莱昂纳多.

I've created a shared library for contour detection that is loaded from a Delphi/Lazarus application. The main app, passes a pointer to a bitmap to be processed by a function inside the library.

Here's the function inside the library. The parameter "img" is the pointer to my bitmap.

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;
    }
  }
}

From the Delphi side, I'm passing a pointer to an array of this structure:

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

I need to process the bitmap in-memory, that's why I'm not loading the file from inside the library.

The question is: Is this the right way to assign a bitmap to a cv::Mat ?

I ask this because the code works without problems in Linux, but fails on Windows compiled with Mingw.

Note: it fails with a SIGSEGV on this line:

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

EDIT: The SIGSEGV is raised only if I compile OpenCV in Release mode, in Debug mode it works ok.

Thanks in advance,
Leonardo.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

时光是把杀猪刀 2024-12-21 01:45:11

因此,您可以通过以下方式创建图像:

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

src.data = img;

第一个声明和实例化
Mat src(imgHeight, imgWidth, CV_8UC4) 将为新图像分配内存,并使用引用计数器自动跟踪对已分配内存的引用数量。
改变实例变量

然后通过src.data = img;

当实例 src 超出范围时,析构函数会被调用,并且很可能会尝试释放您分配的 src.data 处的内存,这可能会导致分段错误。正确的方法是不更改对象的实例变量,而是在实例化 src 时简单地使用正确的构造函数:

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

这样,您只需创建一个矩阵头,并且析构函数不会执行引用计数器或释放操作源代码。

祝你好运!

编辑:我不确定段错误实际上是由于尝试错误地释放内存而引起的,但最好不要通过直接分配给实例变量来破坏数据抽象。

So you are creating an image this way:

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

src.data = img;

The first declaration and instantiation
Mat src(imgHeight, imgWidth, CV_8UC4) will allocate memory for a new image and a reference counter that automatically keeps track of the number of references to the allocated memory.
Then you mutate an instance variable through

src.data = img;

When the the instance src goes out of scope, the destructor is called and most likely tries to deallocate the memory at src.data, which you assigned and this might cause a segmentation fault. The right way to do it is to not change instance variable of an object, but to simply use the right constructor when you instantiate src:

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

This way, you just create a matrix header and no reference counter or deallocation will be performed by the destructor of src.

Good luck!

EDIT: I am not sure that the segfault is actually caused by an attempt to deallocate memory incorrectly, but it is a good practice not to break data abstraction by assigning directly to instance variables.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文