高斯模糊问题

3
我正在编写一个高斯滤波器,我的目标是尽可能地匹配Photoshop中的高斯模糊滤镜。这是我进行的第一个图像处理尝试。我遇到了一些问题/疑问...
使用我的滤波器进一步模糊图像会使其变暗,而Photoshop似乎会使其变亮。
我正在使用r/3作为偏差值(在我的代码中称为“sigma”),这将导致高斯曲线在矩阵内接近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个回答

9
要反向工程一个滤波器,你需要找到它的脉冲响应。在一个非常暗的值(比如32)的背景上,放置一个几乎是白色的像素(比如223)。不要使用0和255,因为一些滤波器会试图创建超出起始值的值。在这个图像上运行滤波器,取输出值并将它们从0.0拉伸到1.0:(value-32)/(223-32)。现在你有了模拟滤波器所需精确权重。
有很多处理图像边缘的方法。我建议将滤波器权重相加,然后将结果除以该总和;如果你试图超越边缘,则在该像素上的像素值和滤波器权重都使用0.0。

看起来 Photoshop 使用盒状模糊来近似高斯模糊。 - Royi

2
边界条件有时取决于您正在做什么以及您正在处理的数据类型,但我认为对于通用图像处理,最好的做法是将边界处的值延伸到图像边缘之外。当然不是字面意义上的延伸,而是如果滤波器尝试读取超出图像边界的像素,则替换为图像边缘上最近的像素的值。这实际上与将行夹紧在0和高度之间,将列夹紧在0和宽度之间是相同的。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接