高斯模糊算法

 一、定义:

高斯模糊(英语:Gaussian Blur),也叫高斯平滑。

        通常用它来减少图像噪声以及降低细节层次。这种模糊技术生成的图像,其视觉效果就像是经过一个毛玻璃在观察图像,这与镜头焦外成像效果散景以及普通照明阴影中的效果都明显不同。高斯平滑也用于计算机视觉算法中的预先处理阶段,以增强图像在不同比例大小下的图像效果(参见尺度空间表示以及尺度空间实现)。 从数学的角度来看,图像的高斯模糊过程就是图像与正态分布做卷积。由于正态分布又叫作高斯分布,所以这项技术就叫作高斯模糊。图像与圆形方框模糊做卷积将会生成更加精确的焦外成像效果。由于高斯函数的傅里叶变换是另外一个高斯函数,所以高斯模糊对于图像来说就是一个低通滤波器。(解释来源于百度百科https://baike.baidu.com/item/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A

二、理论原理(来源于百度百科)

        高斯模糊是一种图像模糊滤波器,它用正态分布计算图像中每个像素的变换。N维空间正态分布方程为

        在二维空间定义为

        其中r是模糊半径,σ是正态分布的标准偏差。在二维空间中,这个公式生成的曲面的等高线是从中心开始呈正态分布的同心圆。分布不为零的像素组成的卷积矩阵与原始图像做变换。每个像素的值都是周围相邻像素值的加权平均。原始像素的值有最大的高斯分布值,所以有最大的权重,相邻像素随着距离原始像素越来越远,其权重也越来越小。这样进行模糊处理比其它的均衡模糊滤波器更高地保留了边缘效果,参见尺度空间实现。

        理论上来讲,图像中每点的分布都不为零,这也就是说每个像素的计算都需要包含整幅图像。在实际应用中,在计算高斯函数的离散近似时,在大概3σ距离之外的像素都可以看作不起作用,这些像素的计算也就可以忽略。通常,图像处理程序只需要计算

 的矩阵就可以保证相关像素影响。对于边界上的点,通常采用复制周围的点到另一面再进行加权平均运算。

        ......(其余请自行查看百度百科https://baike.baidu.com/item/%E9%AB%98%E6%96%AF%E6%A8%A1%E7%B3%8A

三、实现原理

        先确定模糊半径,然后对每一个像素都取周边像素的平均值。

        模糊半径越大,图像就越模糊。从数值角度看,就是数值越平滑。

关于权重分配问题:

1、局部加权平均;

2、基于正态分布。

关于算力问题:使用多线程加速。

四、实现代码

package com.young;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class demo {
    public static void main(String[] args) {
        try {
            long l = System.currentTimeMillis();
            BufferedImage image = ImageIO.read(new File("beb9894fc1a505976f996163f8c20361.jpg"));
            BufferedImage image1 = new demo().GaussianBlur(image, 20);
            ImageIO.write(image1, "jpg", new File("a.jpg"));
            l = System.currentTimeMillis() - l;
            System.out.println(l);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 基于加权平均的权重分配(也可以基于正态分布等等)
     *
     * @param image 图像类
     * @param index 模糊半径
     */
    BufferedImage GaussianBlur(BufferedImage image, int index) {
        int width = image.getWidth();
        int height = image.getHeight();
        BufferedImage result = new BufferedImage(width, height, 1);
        System.out.println("宽度:" + width);
        System.out.println("高度:" + height);
        /**
         * 嵌套的for循环可以使用多线程进行加速处理
         */
        for (int i = 0; i < width; i++)
            for (int j = 0; j < height; j++)
                result.setRGB(i, j, getRGBAvg(image, i, j, index));
        return result;
    }

    int getRGBAvg(BufferedImage image, int x, int y, int index) {
        int RGBAvg = 0;
        int rAvg = 0;
        int gAvg = 0;
        int bAvg = 0;
        int[] point = new int[(index * 2 + 1) * (index * 2 + 1)];
        int size = 0;
        for (int i = Math.max(x - index, 0); i < Math.min(x + index + 1, image.getWidth()); i++) {
            for (int j = Math.max(y - index, 0); j < Math.min(y + index + 1, image.getHeight()); j++) {
                point[size++] = image.getRGB(i, j);
            }
        }
        for (int i : point) {
            rAvg += (i >> 16) & 0xff;
            gAvg += (i >> 8) & 0xff;
            bAvg += i & 0xff;
        }
        RGBAvg |= rAvg / size << 16;
        RGBAvg |= gAvg / size << 8;
        RGBAvg |= bAvg / size;
        return RGBAvg;
    }

    int getR(BufferedImage image, int x, int y) {
        return (image.getRGB(x, y) >> 16) & 0xff;
    }

    int getG(BufferedImage image, int x, int y) {
        return (image.getRGB(x, y) >> 8) & 0xff;
    }

    int getB(BufferedImage image, int x, int y) {
        return image.getRGB(x, y) & 0xff;
    }
}

四、结果

おすすめ

転載: blog.csdn.net/qq_40100414/article/details/120073578
おすすめ