Быстрое размытие по Гауссу на изображении без знака — ARM Neon Intrinsics — iOS Dev

Может ли кто-нибудь сказать мне быструю функцию для поиска размытия изображения по Гауссу с использованием маски 5x5. Мне это нужно для разработки приложений для iOS. Я работаю непосредственно с памятью изображения, определенного как

unsigned char *image_sqr_Baseaaddr = (unsigned char *) malloc(noOfPixels);

for (row = 2; row < H-2; row++) 
{
    for (col = 2; col < W-2; col++) 
    {
        newPixel = 0;
        for (rowOffset=-2; rowOffset<=2; rowOffset++)
        {
            for (colOffset=-2; colOffset<=2; colOffset++) 
            {
                rowTotal = row + rowOffset;
                colTotal = col + colOffset;
                iOffset = (unsigned long)(rowTotal*W + colTotal);
                newPixel += (*(imgData + iOffset)) * gaussianMask[2 + rowOffset][2 + colOffset];
            }
        }
        i = (unsigned long)(row*W + col);
        *(imgData + i) = newPixel / 159;
    }
}

Это, очевидно, самая медленная функция из возможных. Я слышал, что встроенные функции ARM Neon на iOS можно использовать для выполнения нескольких операций за 1 цикл. Может быть, это путь?

Проблема в том, что я не очень хорошо знаком с ассемблером и у меня нет времени на изучение ассемблера. Так что было бы здорово, если бы кто-нибудь мог опубликовать встроенный код Neon для упомянутой выше проблемы или любой другой быстрой реализации на C/C++.


person shreyas253    schedule 06.02.2012    source источник


Ответы (2)


Прежде чем вы приступите к оптимизации SIMD с помощью NEON, вы должны сначала улучшить свою скалярную реализацию. Самая большая проблема с вашим кодом в его нынешнем виде заключается в том, что он был реализован так, как если бы он был неотделимым фильтром, тогда как гауссово ядро ​​отделимо. Переключившись на разделяемую реализацию, вы уменьшите количество операций от N^2 до 2N, что в вашем случае ядра 5x5 будет сокращением с 25 умножения-сложения до 10, т. е. 2,5-кратное ускорение при очень небольших усилиях.

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


http://en.wikipedia.org/wiki/Gaussian_blur

http://blogs.mathworks.com/steve/2006/11/28/separable-convolution-part-2/

person Paul R    schedule 06.02.2012
comment
так как мне преобразовать мою 2D-маску 5x5 в две 1D-маски?? - person shreyas253; 06.02.2012
comment
Я добавил несколько полезных ссылок выше - person Paul R; 06.02.2012

  1. Отделите ядро, как описано Полом Р.
  2. Не изобретайте велосипед. Используйте vImage, который является частью инфраструктуры Accelerate и реализует для вас векторизованную многопоточную свертку. В частности, кажется, что вам нужна функция vImageConvolve_Planar8.
person Stephen Canon    schedule 06.02.2012
comment
+1 для vImage, если это должно быть только решение для iOS (и, возможно, OS X) - person Paul R; 07.02.2012