Итерировать по пикселям изображения с помощью emgu cv - PullRequest
16 голосов
/ 24 февраля 2011

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

Обновление:

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

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

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

1 Ответ

49 голосов
/ 24 февраля 2011

Как состояние сайта 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);

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

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

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();

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...