【问题标题】:Halcon FindNccModel causes memory leak in C#Halcon FindNccModel 导致 C# 中的内存泄漏
【发布时间】:2019-02-11 09:56:32
【问题描述】:

在 C# 中使用 Halcon 13 函数 FindNccModel 会导致以下错误: HALCON 错误 #6001:运算符 find_ncc_model 中没有足够的可用内存

class Program
{
    static void Main(string[] args)
    {
        HImage Image = new HImage(@"08_09_09_41_33_582_OK_000000153000.png");
        double MidpointRow = 1053.5210373923057, MidpointCol = 1223.5205413999142;

        int iCounter = 0;

        while (true)
        {
            HNCCModel model = new HNCCModel(@"000000135000Mark_0.ncm");

            HXLDCont hxCont = new HXLDCont();
            hxCont.GenRectangle2ContourXld(
                721.9213759213759,
                1775.862648221344,
                -0.99483767363676778,
                72,
                14.5);

            HTuple htRowXLD, htColXLD;
            hxCont.GetContourXld(out htRowXLD, out htColXLD);
            HTuple htRadius = new HTuple();
            htRadius = new HTuple(htRowXLD.TupleSub(MidpointRow).TuplePow(2) + htColXLD.TupleSub(MidpointCol).TuplePow(2)).TupleSqrt();
            HRegion hrAnnulus = new HRegion();
            hrAnnulus = hrAnnulus.GenAnnulus(MidpointRow, MidpointCol, htRadius.TupleMin() - 5.0, htRadius.TupleMax() + 5.0);

            HImage hiTemp = Image.Clone();
            HImage hiTemp2 = hiTemp.Rgb1ToGray();
            HImage hiTemp3 = hiTemp2.ReduceDomain(hrAnnulus);

            HTuple htRow, htColumn, Angle, Score;

            model.FindNccModel(hiTemp3, -0.39, 6.29, 0.65, 1, 0, "true", 0, out htRow, out htColumn, out Angle, out Score);

            hxCont.DisposeIfNotNull();
            hrAnnulus.DisposeIfNotNull();
            model.Dispose();

            hiTemp.DisposeIfNotNull();
            hiTemp2.DisposeIfNotNull();
            hiTemp3.DisposeIfNotNull();

            Console.WriteLine(iCounter++.ToString());
        }
    }
}

public static class DL_HalconUtilityClass
{
    public static HRegion GenAnnulus(this HRegion region, double dCenterRow, double dCenterColumn, double dRadiusSmall, double dRadiusBig)
    {
        region.GenEmptyRegion();

        if (dRadiusSmall > dRadiusBig)
        {
            throw new NotSupportedException("Wrong input parameters. Small radius is bigger than big radius.");
        }

        HRegion hrCircleSmall = new HRegion(dCenterRow, dCenterColumn, dRadiusSmall);
        HRegion hrCircleBig = new HRegion(dCenterRow, dCenterColumn, dRadiusBig);

        region = new HRegion();
        region = hrCircleBig.Difference(hrCircleSmall);

        hrCircleSmall.Dispose();
        hrCircleBig.Dispose();

        return region;
    }

    public static void DisposeIfNotNull(this HImage hiImage)
    {
        if (hiImage != null) hiImage.Dispose();
    }

    public static void DisposeIfNotNull(this HRegion hrRegion)
    {
        if (hrRegion != null) hrRegion.Dispose();
    }

    public static void DisposeIfNotNull(this HObject hoObject)
    {
        if (hoObject != null) hoObject.Dispose();
    }
}

函数本身可以在while循环中无限运行,但是如果它与我们的程序结合使用会导致内存异常。另一方面,程序本身可以在没有此功能的情况下无限运行。有趣的是,错误发生在程序达到典型的 1.1 Gb 内存之前,这意味着存在内存泄漏。

我在 Halcon 文档中没有找到任何关于这个问题的参考,升级到最新的 Halcon 13 版本或使用 Halcon XL 没有帮助。有谁知道什么可能导致这个问题?

【问题讨论】:

    标签: halcon


    【解决方案1】:

    Halcon 有两个内存管理优化系统设置:global_mem_cache 和temporary_mem_cache。 global_mem_cache 没有影响,但是将temporary_mem_cache 参数设置为“idle”或“shared”即可解决问题。

    默认设置为“独占”,其中为每个线程在本地缓存临时内存。这是 Halcon 文档的摘录:


    'temporary_mem_cache' *), 'tsp_temporary_mem_cache' 该参数控制临时内存缓存的操作模式。临时内存缓存用于通过缓存在操作符执行期间临时使用的内存来加速应用程序。对于大多数应用程序,默认设置(“独占”)将产生最佳结果。支持以下模式:

    • 'idle' 临时内存缓存已关闭。此模式将使用最少的内存,但与其他模式相比也会降低性能。

    • 'shared' 所有临时内存都全局缓存在临时内存库中。此模式将比“独占”模式使用更少的内存,但通常也会提供较低的性能。

    • 'exclusive' 所有临时内存都在本地为每个线程缓存。此模式将使用最多的内存,但通常也会提供最佳性能。

    • 'aggregate' 大于使用 'alloctmp_max_blocksize' 参数设置的阈值的临时内存块被缓存在全局内存库中,而所有较小的块被聚合成单个块,为每个线程在本地缓存.如果禁用全局内存库,则会释放大块。聚合块的大小将根据线程到目前为止看到的临时内存使用情况进行调整,但不会大于“alloctmp_max_blocksize”(如果设置)或小于“alloctmp_min_blocksize”(如果设置)。此模式平衡了内存使用和速度,但需要为应用程序的内存使用模式正确设置“alloctmp_min_blocksize”和“alloctmp_max_blocksize”才能有效。

    请注意,缓存模式“空闲”设置为独占运行模式,而其他模式设置为可重入模式。

    为了向后兼容,还接受值“false”和“true”;它们分别对应于“空闲”和“独占”。

    【讨论】:

      【解决方案2】:

      在您的代码中,您已经按照建议手动处置了大多数 HALCON 对象。您可能知道这是必要的,因为 .NET 垃圾收集器不知道托管对象可能使用的 HALCON 库处理的非托管内存量。

      但是,您错过了 Dispose 包含 FindNccModel htRowhtColumnAngleScore 结果的 HTuples。

      您可能还希望将 HNCCModel 的创建移出您的 while 循环。

      【讨论】:

      • HNCCModel 无法从循环中移除,因为每次需要根据产品类型加载不同的模型。我不认为 HTuples 会导致这个问题,但是你会如何处理它们呢?
      • 要处理 HTuples,您也​​可以简单地调用 htRow.Dispose(), ...,一旦您不再需要结果。
      • HTuple 没有 Dispose 方法。
      • 好的,抱歉,我正在检查 HALCON 18.05 Progress,HTuple 已经获得了 Dispose 方法
      猜你喜欢
      • 2017-02-20
      • 2019-10-21
      • 2016-03-14
      • 2018-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多