java - 如何在java中制作平滑的模糊效果?

标签 java image

我已经模糊了图像。但它并不顺利。

我听说如果我使用高斯模糊技术就可以去除方 block 效果。

但我不知道如何用我的代码实现它(我做了一些随机技术,但它弄乱了颜色)。你能建议我如何用我的代码进行高斯模糊吗?

public class BlurImageDemo {

Color c[];

BlurImageDemo() throws IOException, InterruptedException {
    File f = new File("D:\\x.jpg");
    BufferedImage im = ImageIO.read(f);

    BufferedImage bi = new BufferedImage(im.getWidth(), im.getHeight(), BufferedImage.TYPE_INT_RGB);
    int i = 0;
    int max = 400, radius = 10;
    int a1 = 0, r1 = 0, g1 = 0, b1 = 0;
    c = new Color[max];
    int x = 1, y = 1, x1, y1, ex = 5, d = 0;
    for (x = radius; x < im.getHeight() - radius; x++) {
        for (y = radius; y < im.getWidth() - radius; y++) {

            //20x20 matrix
            for (x1 = x - radius; x1 < x + radius; x1++) {
                for (y1 = y - radius; y1 < y + radius; y1++) {
                    c[i++] = new Color(im.getRGB(y1, x1));
                    //System.out.println(i);
                }
            }
            i = 0;

            for (d = 0; d < max; d++) {
                a1 = a1 + c[d].getAlpha();
            }
            a1 = a1 / (max);

            for (d = 0; d < max; d++) {
                r1 = r1 + c[d].getRed();
            }
            r1 = r1 / (max);

            for (d = 0; d < max; d++) {
                g1 = g1 + c[d].getGreen();
            }
            g1 = g1 / (max);

            for (d = 0; d < max; d++) {
                b1 = b1 + c[d].getBlue();
            }
            b1 = b1 / (max);
            int sum1 = (a1 << 24) + (r1 << 16) + (g1 << 8) + b1;
            bi.setRGB(y, x, (int) (sum1));

        }
    }
    ImageIO.write(bi, "jpg", new File("D:\\x1.jpg"));
}

public static void main(String[] args) throws IOException, InterruptedException {
    new BlurImageDemo();
}
}

this is the final image, which is not smooth

最佳答案

高斯模糊的一个非常好的特性是它是可分离的,这意味着它可以表示为纯水平模糊和纯垂直模糊的组合。这样做的好处是,对于每个像素,它们需要 2N 次乘法(N 是内核的大小),而 2D 非分离版本需要 N2 次乘法。对于 N=7(如您所见),这已经是一个不错的差异。它也有一个小缺点,中间结果要么四舍五入(失去一些精度)要么很大(每个像素 3 个 float 而不是 1 个整数),但通常稍微四舍五入不是问题。

另一件事,更多的是实现细节,是可以将除以内核总权重的除法放入内核本身,从而节省一大堆(相当慢的)除法。

此外,您的内核实际上看起来并不像高斯,它太“尖”了。这取决于你,但高斯核是唯一一个也是可分离的循环对称核(如果你只看实值核)并且通常具有很好的特性,所以我建议只有在有充分理由的情况下才偏离它

无论如何,我现在会写一些示例代码,没有经过测试:

BufferedImage transposedHBlur(BufferedImage im) {
    int height = im.getHeight();
    int width = im.getWidth();
    // result is transposed, so the width/height are swapped
    BufferedImage temp =  new BufferedImage(height, width, BufferedImage.TYPE_INT_RGB);
    float[] k = new float[7] { 0.00598, 0.060626, 0.241843, 0.383103, 0.241843, 0.060626, 0.00598 };
    // horizontal blur, transpose result
    for (int y = 0; y < height; y++) {
        for (int x = 3; x < width - 3; x++) {
            float r = 0, g = 0, b = 0;
            for (int i = 0; i < 7; i++) {
                int pixel = im.getRGB(x + i - 3, y);
                b += (pixel & 0xFF) * k[i];
                g += ((pixel >> 8) & 0xFF) * k[i];
                r += ((pixel >> 16) & 0xFF) * k[i];
            }
            int p = (int)b + ((int)g << 8) + ((int)r << 16);
            // transpose result!
            temp.setRGB(y, x, p);
        }
    }
    return temp;
}

因为它也转置,你可以简单地调用它两次,第二次将有效地成为一个垂直模糊,同时恢复方向:

temp = transposedHBlur(input);
result = transposedHBlur(temp);

关于java - 如何在java中制作平滑的模糊效果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43743998/

相关文章:

java Android 反射

javascript - 在 JavaScript 中动态加载的绘制到 Canvas 上的图像具有不正确(但接近)的 RGB 值

c# - 如何根据宽高比调整图像大小而不损失质量?

JavaScript/jQuery UI : Changing element img src from an array of images based on current img src

java - 网页重定向如何在此页面中工作?

java - 验证 Intent 是否进行有效的 Activity

SwingWorker 线程中的 java.util.Timer 或 While 循环?

java - 是否可以创建一个等待整个 try block 执行的 catch block ?

python - 尝试运行简单的 PIL python 示例,无法将 jpeg 转换为 float

python PIL - 检查图像是否透明