Как правильно использовать команду «using»? - PullRequest
3 голосов
/ 02 мая 2019

Я только что создал эту учетную запись, поэтому, пожалуйста, прости меня, если я забыл важную информацию.

У меня есть следующий код, но я подозреваю, что есть утечка памяти. Цель кода - получить байты из изображения с (смоделированной) камеры и с их помощью создать изображение EmguCV. Проблема в том, что длина сгенерированного массива никогда не остается прежней. Когда я генерирую изображение размером 300x300, я ожидаю, что массив будет содержать 90000 записей. Но это очень редко так. Номер постоянно меняется.

Я пытался следовать некоторым урокам о том, как правильно использовать команду «using» для удаления переменной, но до сих пор не получилось. Насколько я могу судить, похоже, что для списка байтов, который я использую, нет функции IDisposable. Так что это может быть причиной моей неудачи: /

using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Emgu.CV;
using Emgu.CV.Structure;

namespace opencv_test
{
    class Program
    {
        static void Main(string[] args)
        {
            Stemmer.Cvb.Image image = new Stemmer.Cvb.Image(300, 300);
            image.Initialize(125);
            List<byte> values = new List<byte>();
            CopyPixelWithValue(image, values);

            byte[] myArray = values.ToArray();

            Emgu.CV.Image<Gray, Byte> test = new Image<Gray, Byte>(300, 300);
            test.Bytes = myArray;
            test.Save("D:/abc.jpg");
        }

        static unsafe void CopyPixelWithValue(Stemmer.Cvb.Image toGetValuesFrom, List<byte> values)
        {
            int width = toGetValuesFrom.Width;
            int height = toGetValuesFrom.Height;
            var toCopyData = toGetValuesFrom.Planes[0].GetLinearAccess();

            byte* toCopyBase = (byte*)toCopyData.BasePtr;
            long toCopyYInc = toCopyData.YInc.ToInt64();
            long toCopyXInc = toCopyData.XInc.ToInt64();

            Parallel.For(0, height, y =>
            {
                var pSrcLine = toCopyBase + y * toCopyYInc;

                for (int x = 0; x < width; x++)
                {
                    var srcVal = *(pSrcLine + x * toCopyXInc);
                    values.Add(srcVal);
                }
            });
        }
    }
}

Любая помощь в том, как решить эту проблему, будет с благодарностью принята !!

Ответы [ 2 ]

3 голосов
/ 02 мая 2019

Ваша проблема в том, что вы используете параллельный цикл для добавления значений в список «значений», вы получаете доступ к одному и тому же списку в нескольких потоках одновременно, это небезопасно и портит данные. Измените его на обычный цикл, и у вас, вероятно, не возникнет проблем.

0 голосов
/ 02 мая 2019

Вы теряете байты из-за несинхронизированного многопоточного кода внутри Parallel.For. Ниже приведена попытка исправить это.

static void Main(string[] args)
{
    Stemmer.Cvb.Image image = new Stemmer.Cvb.Image(300, 300);
    image.Initialize(125);
    byte[] myArray = GetStemmerImageBytes(image);

    Emgu.CV.Image<Gray, Byte> test = new Image<Gray, Byte>(300, 300);
    test.Bytes = myArray;
    test.Save("D:/abc.jpg");
}

static unsafe byte[] GetStemmerImageBytes(Stemmer.Cvb.Image image)
{
    int width = image.Width;
    int height = image.Height;
    var linearAccess = image.Planes[0].GetLinearAccess();

    byte* sourceBase = (byte*)linearAccess.BasePtr;
    long sourceYInc = linearAccess.YInc.ToInt64();
    long sourceXInc = linearAccess.XInc.ToInt64();

    var result = new byte[width * height];
    Parallel.For(0, height, y =>
    {
        var sourceLine = sourceBase + y * sourceYInc;

        for (int x = 0; x < width; x++)
        {
            var srcVal = *(sourceLine + x * sourceXInc);
            result[y * width + x] = srcVal;
        }
    });
    return result;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...