【问题标题】:Who should care of MemStorage deallocation when contour is created?创建轮廓时谁应该关心 MemStorage 释放?
【发布时间】:2011-11-30 11:43:15
【问题描述】:

我为OpenCV 使用Emgu CV 包装器。

我想创建以某种方式生成轮廓并返回它的函数。

要创建轮廓,我使用以下类似:

Contour<PointF> contour = new Contour<PointF>(new MemStorage());

谁应该关心MemStorage的释放?
我应该执行额外的操作还是 EmguCV 会在没有额外代码的情况下正确处理这种情况?

或者下面的代码是否正确:

MemStorage memStorage = new MemStorage();
Contour<PointF> contour = new Contour<PointF>(memStorage);

并且memStorage 应该被显式释放?

【问题讨论】:

    标签: c# .net memory-management opencv emgucv


    【解决方案1】:

    好问题因此赞成,我希望内存存储(Memstorage)的使用与.Net中的任何其他变量相同。如果您打算在调用时在多个方法中创建它,那么创建全局内存存储分配会更有效。由于 Memstorage 是指向存储变量的物理地址的指针,因此最好覆盖其中的单个变量,然后创建一个新的 Memstorage,其中必须重新汇集和重新分配资源。

    谢天谢地,垃圾收集器非常高效,当您退出收集 Memstorage 的方法时,它所占用的资源将在需要或您的程序不做任何事情时重新分配。您总是可以通过将 Memstorage 变量设置为 null 并调用 GB.Collect() 方法来告诉垃圾收集器手动执行此操作,当然这依赖于 Memstorage 类可以为空。

    为确保尽可能高效地处理内存分配,应使用using 语句。这将释放 Memstrage 变量使用的资源。这是我从 opencv 转换为完成与 Matlabs bwareopen 相同的示例,其中较小的项目或被压制。它确实需要工作,但这是在数据抑制方面。但是,using 语句仅在不多次访问函数时(例如在循环内)才有效。

    在具体回答您的问题时,您应该考虑使用 using 语句来确保 MemStorage 被正确释放,但这应该只有在调用该方法时有足够的中断。如果要在 for 循环中按顺序调用此方法,则应将 MemStorage 声明为类中的全局变量,然后在调用垃圾收集器之前在类的 IDisposable 方法中尽可能将其设为 null。一旦循环完成,就可以调用类的 dispose 方法来有效地重新分配资源。如果你也想要这样的例子,请告诉我,我会相应地更新我的答案。

    using 和 MemStorage 的示例:

    private Image<Bgr, byte> bwareaopen(Image<Bgr, byte> Input_Image, int threshold)
    {
    
        Image<Bgr, byte> bwresults = Input_Image.Copy();
    
        using (MemStorage storage = new MemStorage())
        {
            for (Contour<Point> contours = Input_Image.Convert<Gray, byte>().FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST, storage); contours != null; contours = contours.HNext)
            {
                Contour<Point> currentContour = contours.ApproxPoly(contours.Perimeter * 0.05, storage);
                if (currentContour.Area < threshold) 
                {
                    for (int i = currentContour.BoundingRectangle.X; i < currentContour.BoundingRectangle.X + currentContour.BoundingRectangle.Width; i++)
                    {
                        for (int j = currentContour.BoundingRectangle.Y; j < currentContour.BoundingRectangle.Y + currentContour.BoundingRectangle.Height; j++)
                        {
                            bwresults.Data[j, i, 0] = 0;
                            bwresults.Data[j, i, 1] = 0;
                            bwresults.Data[j, i, 2] = 0;
                        }
                    }
                }
            }
        }
        return bwresults;
    }
    

    openCV 代码在这里http://tech.groups.yahoo.com/group/OpenCV/message/27345 所有功劳归功于 M.Klien 在 matlab 中转换方法。

    对于那些有兴趣让这个函数正常工作的人来说,抑制数据的 for 循环应该使用轮廓的边界约束而不是 Bounding Rectangle。一旦我对此进行了调整,我将相应地更新代码。

    我希望这有助于回答你的问题,

    干杯,

    克里斯

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多