Итерация над пикселями изображения с помощью emgu cv

Я хочу перебрать все пиксели изображения и сравнить с шаблоном поиска. С наилучшей производительностью и с С#. Я нашел emgu cv, обертку для Intels opencv. Но я не знаю, как правильно использовать эмгу. Кто-нибудь знает, как я могу это сделать? Каковы данные Property of Image? Это изображение? Если да, то какое значение? Благодаря

Обновление:

Я закодировал свою функцию на С#, и она работала хорошо, но слишком медленно! У меня уже был algorhytm в c, который я перевел на С#. С# в 3 - 4 раза медленнее, чем c! (Моя функция выполняет итерацию почти на каждом пикселе изображения для поиска фигуры на изображении. → Преобразование Хью)

Ну, я слышал, что небезопасный код может быть быстрее, потому что он не проверяет границы массивов и прочее. Это правда? Выполняет небезопасный код непосредственно на физическом компьютере?

Во всяком случае, я попытался включить небезопасный код в свою функцию. Но я не смог получить указатель на мой 3D-массив или получить доступ к 3D-массиву с помощью указателя. Как я могу переписать этот код сверху с помощью небезопасного кода? И это принесет дополнительный прирост производительности или даже будет работать так быстро, как c-code?

Ответ 1

В качестве состояния веб-сайта emgu существуют две стратегии:

Безопасный (медленный) способ

Предположим, что вы работаете над Image<Bgr, Byte>. Вы можете получить пиксель в y-й строке и x-м столбце, вызвав

Bgr color = img[y, x];

Установка пикселя в y-й строке и x-м столбце также проста

img[y,x] = color;

Быстрый способ

Значения пикселей изображения хранятся в свойстве Data, трехмерном массиве. Хорошо, так что это правда, но не говорит, как это сделать в реальном сценарии. Поэтому давайте посмотрим на некоторый рабочий код, а затем обсудим производительность и оптимизацию:

Image<Bgr, Byte> original = newImage<Bgr, byte>(1024, 768);
Stopwatch evaluator = newStopwatch(); 

int repetitions = 20;
Bgr color = newBgr(100, 40, 243);

evaluator.Start();

for (int run = 0; run < repetitions; run++)
{
    for (int j = 0; j < original.Cols; j++)
    {
        for (int i = 0; i < original.Rows; i++)
        {
            original[i, j] = color;
        }
    }
}

evaluator.Stop();
Console.WriteLine("Average execution time for {0} iteration \n using column per row access: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions);

Итак, это среднее время работы, которое у вас есть после 20 прогонов, используя безопасный медленный способ установки пикселя изображения На моей машине требуется 1021ms...

Так 1021 миллисекунды в качестве среднего времени для цикла и установки количества пикселей, равных 1024 * 768. Мы могли бы сделать немного лучше, перейдя по строке за строкой

Итак, давайте немного переработаем наш код и позволим использовать более быстрый способ, используя прямое свойство Image.Data:

evaluator.Reset();
evaluator.Start();

for (int run = 0; run < repetitions; run++)
{
    for (int i = 0; i < original.Rows; i++)
    {
        for (int j = 0; j < original.Cols; j++)
        {
            original.Data[i, j, 0] = 100;
            original.Data[i, j, 1] = 40;
            original.Data[i, j, 2] = 243;
        }
    }
}

evaluator.Stop();
Console.WriteLine("Average execution time for {0} iterations \n using Data property: {1}ms\n", repetitions, evaluator.ElapsedMilliseconds / repetitions);

На моей машине требуется 519ms. Таким образом, мы получили повышение производительности на 50%. Время выполнения было уменьшено в два раза.

Поэтому, внимательно изучая код, имея в виду, что мы используем С#, мы можем сделать небольшое изменение, которое решительно повысит производительность наших настроек пиксельных пикселей... мы не должны использовать свойство С# внутри цикла!!!

evaluator.Reset();
evaluator.Start();

byte[,,] data = original.Data;

for (int run = repetitions - 1; run >= 0; run--)
{
    for (int i = original.Rows - 1; i >= 0; i--)
    {
        for (int j = original.Cols - 1; j >= 0; j--)
        {
            data[i, j, 0] = 100;
            data[i, j, 1] = 40;
            data[i, j, 2] = 243;
        }
    }
}

evaluator.Stop();

Благодаря этому последнему фрагменту кода вы получите огромное повышение производительности (73 мс) из-за правильного использования языка С#.