首页 > 解决方案 > Halcon FindNccModel 导致 C# 中的内存泄漏

问题描述

在 C# 中使用 Halcon 13 函数 FindNccModel 会导致以下错误:HALCON error #6001: Not enough memory available in operator 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

解决方案


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”;它们分别对应于“空闲”和“独占”。


推荐阅读