Быстрое сложение изображений в C# — c# gpu emgucv

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Загрузка...

Вопрос:


Основная задача: мне необходимо в реальном времени (или около того) сложение двух Grayscale FullHD 8bit изображений (которые будут использованы как R и G каналы) с камеры (60fps, производитель Imaging Source) в одно FullHD 24bit изображение (R,G,coef*G). Необходимо все полученные изображения отображать на экране (в виде realtime трансляции). Язык разработки — c#. Ограничение на coef: 0 < coef < 1.

Заступорился на создании самой функции быстрого сложения. Необходима «очень быстрая» отработка. Подразумеваю «<=0.01с на получение результирующего изображения».

Попытка формулировки вопроса:
Какой специфический алгоритм обработки нужно использовать, чтобы решить подобную задачу, а именно проблему скорости? Через указатели я добился отработки примерно в 0.05с, что все еще долго.Буду рад полезным ссылкам (примеры, обучалки и прочее).
Функция, которой произвожу обработку:

    private unsafe Bitmap Create_RGB_BMP_FastUnsafe(Bitmap pBMP1, Bitmap pBMP2, bool GreenFirst)
    {
        int width = 1920;
        int height = 1080;
        int WH = width * height;
        var pRes = new Bitmap(width, height, System.Drawing.Imaging.PixelFormat.Format24bppRgb);
        BitmapData bd_red, bd_green, bd_res;
        if (GreenFirst)
        {
            bd_green = pBMP1.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);
            bd_red = pBMP2.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);
            bd_res = pRes.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite,
               PixelFormat.Format24bppRgb);//greenfirst=true;
        }
        else
        {
            bd_red = pBMP1.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);
            bd_green = pBMP2.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly,
                PixelFormat.Format8bppIndexed);
            bd_res = pRes.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite,
               PixelFormat.Format24bppRgb);//greenfirst=false;
        }
        try
        {
            int stride1 = bd_red.Stride;
            int sk;
            byte* curpos_red = (byte*)bd_red.Scan0;
            byte* curpos_green = (byte*)bd_green.Scan0;
            byte* _currentPX = (byte*)bd_res.Scan0;
            for (sk = 0; sk < WH; sk++)
            {
                *_currentPX = (byte)(*(curpos_green) * 0.1); ++_currentPX;
                *_currentPX = *(curpos_green++); ++_currentPX;
                *_currentPX = *(curpos_red++); ++_currentPX;
            }
        }
        finally
        {
            pBMP1.UnlockBits(bd_red);
            pBMP2.UnlockBits(bd_green);
            pRes.UnlockBits(bd_res);
        }
        return pRes;
    }

P.S.: Кое-что из того, что я уже прочитал, перед тем, как спросить у вас, профессионалы)…

  1. https://stackoverflow.com/questions/8687637/fastest-image-processing-library
  2. https://stackoverflow.com/questions/5101986/iterate-over-pixels-of-an-image-with-emgu-cv/5107490#5107490
  3. https://m.habrahabr.ru/company/newprolab/blog/328422/
  4. https://m.habrahabr.ru/company/intel/blog/256533/
  5. https://www.codeproject.com/Articles/33838/Image-Processing-using-C
Автор вопроса: Alexander Naumov

Что замедляет работу кода (что-то может быть не очень актуально, т.к. я не знаю точно, какой код генерирует шарп):

Необязательное здесь использование вещественной арифметики. Можно масштабировать коэффициент и после целочисленного умножения на него делить на 256 (возможно, нужно приводить к int для корректного умножения и потом к байту)

 cf256 = (int) 256 * coeff
 *_currentPX = (*(curpos_green) * сf256 >> 8); ++_currentPX;

Прыжки по памяти в три разных места — от этого полностью не избавиться, но в развертывание циклов может в какой-то мере помочь (возможно, кодогенератор сам умеет это делать, как некоторые плюсовые компиляторы в режиме суровой оптимизации)

Задача числомолотильная отлично подходит для MMX/SSE2/AVX2 блоков процессора. При этом несколько пикселов (сколько выходных пикселов влезет в 8/16/32 байта регистра SIMD) обрабатываются одновременно — при лобовом использовании можно ожидать ускорения раза в 4 (для SSE2). Можно ли это использовать в шарпе? Генерируется ли код для SIMD обработки?

(При использовании SIMD отказываться от float арифметики не обязательно)

Собственно, перечисленное реализовано опытными людьми в OpenCV, поэтому при возможности стоит эту библиотеку использовать.

Есть еще вариант, если это будет единственная вычислительно тяжелая задача — написать функцию на C/C++ с использованием SIMD инструкций (интринсики или вообще компилятор обеспечит автоматическую векторизацию) и вызывать её из C# (вероятно, нужно будет делать DLL).

И напоследок — если обработка 60 кадров в секунду нужна только для отображения — не разумно ли ограничиться обработкой и выводом 30 кадров?

Источник

Вам также может быть интересно:

Drag and Drop UWP — c# xaml mvvm
Вопрос: Нужно иметь возможность добавлять изображения в приложение путем перетаскивания из файловой системы У Grid включил AllowDrop. Но как добавить перетаскиваемые изображения в коллекцию? Т.к. те ...
Растягивание Высоты , Резина — html css html5
Вопрос: Здравствуйте! Реализовал резиновый дизайн. Растягивается ширина, но длина по % не растягивается. Возможно ли это реализовать? Или так и задумано, растягивание только на ширину ...
Jquery position().left Как быть на мобильниках? — javascript jquery css
Вопрос: На мобильных устройствах, если зумишь экран, position всегда разный. $('g').position().left Как сделать так, чтобы он не менял свои значения? Автор вопроса: ...
Jquery position().left Как быть на мобильниках? — javascript jquery css
Вопрос: На мобильных устройствах, если зумишь экран, position всегда разный. $('g').position().left Как сделать так, чтобы он не менял свои значения? Автор вопроса: ...
requestAnimation и очередность отрисовки — javascript canvas
Вопрос: Здравствуйте! Реализовал 2D игру и в Edge работает все плавно и круто, но в Firefox'e подвисает, сказали, что нужно сделать, чтобы раз-два момент и все ...
Контекстное/всплывающее меню в Android — java android popup
Вопрос: Есть ли техническая возможность сделать приложение, добавляющее свое контекстное или всплывающее меню в любом месте системы? Хочу, чтобы при выделении любого текста появлялась дополнительная кнопка ...
Контекстное/всплывающее меню в Android — java android popup
Вопрос: Есть ли техническая возможность сделать приложение, добавляющее свое контекстное или всплывающее меню в любом месте системы? Хочу, чтобы при выделении любого текста появлялась дополнительная кнопка ...
Завершить службы циклом — c# windows-service
Вопрос: Можно ли остановить службы циклом? У меня есть список служб, занёс их в List List<string> name = new List<string> { "AdobeARMservice", "RemoteRegistry", "TermService", "Messenger", "SSDPSRV", ...
Завершить службы циклом — c# windows-service
Вопрос: Можно ли остановить службы циклом? У меня есть список служб, занёс их в List List<string> name = new List<string> { "AdobeARMservice", "RemoteRegistry", "TermService", "Messenger", "SSDPSRV", ...
RecyclerView — разная разметка — android recyclerview
Вопрос: Смотрел, я смотрел в сторону RecyclerView и наконец решил кинуть ListView и на тебе! В "плохом прошлом" мой ListView использовался для двух разметок. Сейчас я ...
RecyclerView — разная разметка — android recyclerview
Вопрос: Смотрел, я смотрел в сторону RecyclerView и наконец решил кинуть ListView и на тебе! В "плохом прошлом" мой ListView использовался для двух разметок. Сейчас я ...
Как правильно передать массив аргументом для пользовательской функции — php
Вопрос: Если не брать в функцию все это, тогда результат работает. А если вот так в функции все выполнять, тогда PHP ругается: «Invalid ...
Как правильно передать массив аргументом для пользовательской функции — php
Вопрос: Если не брать в функцию все это, тогда результат работает. А если вот так в функции все выполнять, тогда PHP ругается: «Invalid ...
ViewPager внутри ViewPager — такие матрешки работают? — android viewpager
Вопрос: Доброго времени суток. Назрела новая задача. Есть каталог мастеров. При выборе конкретного мастера открывается его страница (активити с ViewPager), и теперь мастеров можно перелистывать свайпом. ...
Почему id всегда 1 Yii2 — yii авторизация
Вопрос: Использую все как по документации. Для получения информации о пользователе использую $identity = $model->findOne(]); И каким бы не был email, id пользователя всегда ...

Оставьте ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *