Gaussian Blur Вопросы - PullRequest
       42

Gaussian Blur Вопросы

3 голосов
/ 05 марта 2011

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

Дальнейшее размытие изображения с помощью моего фильтра затемняет его, в то время как фотошоп, кажется, осветляет его.

Значение отклонения («сигма» в моем коде), которое я использую, равно r / 3, в результате чего кривая Гаусса приблизилась к матрице примерно на 0,0001 ... есть ли лучший способ определить это значение?

Как Photoshop (или большинство людей) обрабатывает границы изображения для этого типа размытия?

int matrixDimension = (radius*2)+1;
float sigma = radius/3;
float twoSigmaSquared = 2*pow(sigma, 2);
float oneOverSquareRootOfTwoPiSigmaSquared = 1/(sqrt(M_PI*twoSigmaSquared));

float kernel[matrixDimension];

int index = 0;
for (int offset = -radius; offset <= radius; offset++) {

    float xSquared = pow(offset, 2);
    float exponent = -(xSquared/twoSigmaSquared);
    float eToThePower = pow(M_E, exponent);
    float multFactor = oneOverSquareRootOfTwoPiSigmaSquared*eToThePower;

    kernel[index] = multFactor;

    index++;
}

//Normalize the kernel such that all its values will add to 1
float sum = 0;
for (int i = 0; i < matrixDimension; i++) {
    sum += kernel[i];
}
for (int i = 0; i < matrixDimension; i++) {
    kernel[i] = kernel[i]/sum;
}

//Blur horizontally
for (int row = 0; row < imageHeight; row++) {
    for (int column = 0; column < imageWidth; column++) {

        int currentPixel = (row*imageWidth)+column;

        int sum1 = 0;
        int sum2 = 0;
        int sum3 = 0;
        int sum4 = 0;

        int index = 0;
        for (int offset = -radius; offset <= radius; offset++) {
            if (!(column+offset < 0) && !(column+offset > imageWidth-1)) {

                int firstByteOfPixelWereLookingAtInSrcData = (currentPixel+offset)*4;

                int in1 = srcData[firstByteOfPixelWereLookingAtInSrcData];
                int in2 = srcData[firstByteOfPixelWereLookingAtInSrcData+1];
                int in3 = srcData[firstByteOfPixelWereLookingAtInSrcData+2];
                int in4 = srcData[firstByteOfPixelWereLookingAtInSrcData+3];

                sum1 += (int)(in1 * kernel[index]);
                sum2 += (int)(in2 * kernel[index]);
                sum3 += (int)(in3 * kernel[index]);
                sum4 += (int)(in4 * kernel[index]);
            }

            index++;
        }

        int currentPixelInData = currentPixel*4;

        destData[currentPixelInData] = sum1;
        destData[currentPixelInData+1] = sum2;
        destData[currentPixelInData+2] = sum3;
        destData[currentPixelInData+3] = sum4;

    }
}

//Blur vertically
for (int row = 0; row < imageHeight; row++) {
    for (int column = 0; column < imageWidth; column++) {

        int currentPixel = (row*imageWidth)+column;

        int sum1 = 0;
        int sum2 = 0;
        int sum3 = 0;
        int sum4 = 0;

        int index = 0;
        for (int offset = -radius; offset <= radius; offset++) {
            if (!(row+offset < 0) && !(row+offset > imageHeight-1)) {

                int firstByteOfPixelWereLookingAtInSrcData = (currentPixel+(offset*imageWidth))*4;

                int in1 = destData[firstByteOfPixelWereLookingAtInSrcData];
                int in2 = destData[firstByteOfPixelWereLookingAtInSrcData+1];
                int in3 = destData[firstByteOfPixelWereLookingAtInSrcData+2];
                int in4 = destData[firstByteOfPixelWereLookingAtInSrcData+3];

                sum1 += (int)(in1 * kernel[index]);
                sum2 += (int)(in2 * kernel[index]);
                sum3 += (int)(in3 * kernel[index]);
                sum4 += (int)(in4 * kernel[index]);
            }

            index++;
        }

        int currentPixelInData = currentPixel*4;

        finalData[currentPixelInData] = sum1;
        finalData[currentPixelInData+1] = sum2;
        finalData[currentPixelInData+2] = sum3;
        finalData[currentPixelInData+3] = sum4;

    }
}

Ответы [ 2 ]

8 голосов
/ 05 марта 2011

Для обратного инжиниринга фильтра вам необходимо найти его импульсный отклик.На фоне очень темного значения, скажем, 32, поместите почти белый пиксель, скажем, 223. Вы не хотите использовать 0 и 255, потому что некоторые фильтры будут пытаться создавать значения за пределами начальных значений.Запустите фильтр на этом изображении, возьмите выходные значения и растяните их от 0,0 до 1,0: (value-32)/(223-32).Теперь у вас есть точные веса, необходимые для эмуляции фильтра.

Существует множество способов обработки краев изображения.Я бы предложил взять веса фильтров и суммировать их, а затем разделить результат на эту сумму;если вы пытаетесь выйти за границы, используйте 0.0 для значения пикселя и веса фильтра для этого пикселя.

1 голос
/ 05 марта 2011

Граничные условия иногда зависят от того, что именно вы делаете и с какими данными вы работаете, но я думаю, что для общего назначения манипулирования изображениями лучше всего расширить значения награницы за пределами изображения.Конечно, не буквально, но если фильтр пытается прочитать пиксель, находящийся за пределами изображения, вы подставляете значение ближайшего пикселя на краю изображения.Это действительно то же самое, что просто зафиксировать строку, чтобы она была между 0 и высотой, и столбец, чтобы быть между 0 и шириной.

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