Быстрое размытие по Гауссу на изображении без знака - ARM Neon Intrinsics - iOS Dev - PullRequest
1 голос
/ 06 февраля 2012

Может кто-нибудь сказать мне быструю функцию, чтобы найти гауссово размытие изображения, используя маску 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;
    }
}

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

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

Ответы [ 2 ]

5 голосов
/ 06 февраля 2012

Прежде чем приступить к оптимизации 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/

4 голосов
/ 06 февраля 2012
  1. Разделите ваше ядро, как описано Полом Р.
  2. Не изобретай колесо. Используйте vImage, который является частью инфраструктуры Accelerate и реализует для вас векторизованную многопоточную свертку. В частности, похоже, что вы хотите функцию vImageConvolve_Planar8.
...