Halcon FindNccModel вызывает утечку памяти в C # - PullRequest
0 голосов
/ 06 сентября 2018

Использование функции Halcon 13 FindNccModel в C # вызывает следующую ошибку: Ошибка 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 ГБ памяти, что означает утечку памяти.

Я не нашел ссылок на эту проблему в документации Halcon, и обновление до последней версии Halcon 13 или использование Halcon XL не помогли. Кто-нибудь знает, что может вызвать эту проблему?

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Halcon имеет две настройки системы оптимизации управления памятью: global_mem_cache и временный_mem_cache. Global_mem_cache не имел никакого влияния, но установив параметр временный_мем_cache равным «бездействующий» или «общий», решил проблему.

По умолчанию установлено «исключение», когда временная память кэшируется локально для каждого потока. Это выдержка из документации Halcon:


'period_mem_cache' *), 'tsp_teilitary_mem_cache' Этот параметр управляет режимом работы кеша временной памяти. Кэш временной памяти используется для ускорения приложения путем кэширования памяти, используемой временно во время выполнения оператора. Для большинства приложений настройка по умолчанию («эксклюзив») даст лучшие результаты. Поддерживаются следующие режимы:

  • 'idle' Кэш временной памяти отключен. Этот режим будет использовать наименьшее количество памяти, но также снизит производительность по сравнению с другими режимами.

  • 'shared' Вся временная память кэшируется глобально во временном хранилище памяти. В этом режиме будет использоваться меньше памяти, чем в «эксклюзивном» режиме, но, как правило, производительность будет меньше.

  • 'exclusive' Вся временная память кэшируется локально для каждого потока. В этом режиме используется больше всего памяти, но, как правило, он также обеспечивает наилучшую производительность.

  • «агрегат» Временные блоки памяти, превышающие пороговое значение, установленное параметром «alloctmp_max_blocksize», кэшируются в глобальном хранилище памяти, в то время как все меньшие блоки агрегируются в один блок, который кэшируется локально для каждого потока. , Если глобальный резервуар памяти отключен, большие блоки вместо этого освобождаются. Агрегированный блок будет иметь размер в соответствии с временным использованием памяти, которое поток видел до сих пор, но он не будет больше, чем 'alloctmp_max_blocksize' (если установлено) или меньше, чем 'alloctmp_min_blocksize' (если установлено). Этот режим балансирует использование памяти и скорость, но требует правильной установки alloctmp_min_blocksize и alloctmp_max_blocksize для шаблона использования памяти приложения для эффективности.

Обратите внимание, что режим кэширования 'idle' установлен в режиме исключительного запуска, тогда как другие режимы установлены в режиме повторного входа.

Для обратной совместимости также принимаются значения «ложь» и «истина»; они соответствуют «холостому» и «эксклюзивному» соответственно.

0 голосов
/ 06 сентября 2018

В вашем коде вы уже вручную избавляетесь от большинства объектов HALCON, как это предлагается делать. Как вы, вероятно, знаете, это необходимо, поскольку сборщик мусора .NET не знает об объеме неуправляемой памяти, обрабатываемой библиотекой HALCON, которая может использоваться управляемым объектом.

Однако вы упускаете возможность утилизировать HTuples, содержащие результат FindNccModel htRow, htColumn, Angle и Score.

Вы также можете переместить создание HNCCModel из цикла while.

...