前言:

先来看看下面这张图,我把一张图进行了二等份了,左边是经过高斯模糊过的,右边是原图。

图-1 高斯模糊效果对比图

概述:

高斯模糊也叫做高斯平滑,是一种图像平滑处理的技术。高斯模糊算法的原理是选取一个中心点,以及一个半径周围的所有点,再计算这些像素点的平均值,这个值就是目前这个中心点的值了。这样实现的效果是可以降低图像中的噪音干扰,以达到忽略图像中的细节的目的。

本文链接:http://blog.csdn.net/lemon_tree12138/article/details/50425793 -- Coding-Naga
                                                                 --转载请注明出处

原理说明:

上面说到高斯模糊是计算某些像素点的平均值,那么究竟是什么样的呢?看图-2。

图-2 像素点均值计算

现在我们假设我们就是按照上面的图形进行选取一些像素点的,可是我们的实际图像的像素可不止这些。所以,这里就涉及到另一个知识点了:卷积。不要被卷积这个字面上的词语所惊吓,如果你觉得书面上卷积晦涩难懂,那么你可以看看下面这幅图,它大致描绘了在本文中使用到的卷积基础。

从下面的图解中,我们可以看到,就像是有一块固定大小的区域在沿着横向或是纵向滑动一样。是的,这里我们是以亮绿色为中心点,包含一个半径为1的周围点进行向右和向下的平移。这个很像在计算机网络中学到的滑动窗口一样。

图-3 卷积概念图解(部分)

逻辑实现:

1.朴素的高斯模糊算法

如上面的图-2和图-3,我们知道模糊一张图片的做是可以卷积计算每个点的平均值。那么现在我们就选取以9个点为一个单位模块进行卷积计算,再求其平均值。效果如下图-4.

图-4 朴素高斯模糊效果对比图

从效果图中我们的确是可以看出有一些模糊的效果,不过感觉上像是图片进行了一定像素上的滑移。而且,图像很暗。结论:算法很糟糕。

2.基于正态分布的高斯模糊算法

上面朴素的做法是让中心点和它周围的点具有相同数值的权重。这样是不合理的,为什么?

我们知道图片是连续的,距离越近的像素点,数值应该是更相近的。那么,朴素高斯模糊中简单平均的做法肯定就不合理了。

所以这里我们是使用正态分布来分配权重。正态分布的分布图如下图-5所示:

图-5 一维正态分布图

这幅图相信大家都并不陌生,高中时的课本上就有的。不过因为我们的图片是一个二维的图像,那么单纯的一维还是解决不了问题,下面看看一下二维的高斯分布图吧。

图-6 二维高斯分布图

图-6中的说明之所以修改成了高斯分布图,是因为高斯模糊中使用的正态分布,跟我们在高中时期学习的正态分布公式有一些不一样。

一维高斯函数:

二维高斯函数:

二维高斯函数的实现如下:

/*** 二维高斯函数* * @param n*      二维高斯的范围[-n, n]* @param σ*      标准方差* @return*      范围[-n, n]之内的高斯函数值*/public static float[][] getTwoDimenGaussianFunction(int n, float σ) {        int size = 2 * n + 1;float σ22 = 2 * σ * σ;float σ22PI = (float)Math.PI * σ22;float[][] kernalData = new float[size][size];int row = 0;for(int i = -n; i <= n; i++) {int column = 0;for(int j = -n; j <= n; j++) {float xDistance = i * i;float yDistance = j * j;kernalData[row][column] = (float)Math.exp(-(xDistance + yDistance) / σ22) / σ22PI;column++;}row++;}return kernalData;}

根据以上内容我们可以编写以下高斯模糊核心算法的Java代码:

public class GaussianBlur implements ImageInterface {private int radius;private int round;// 高斯函数的权重矩阵private float[][] normal_distribution = null;public GaussianBlur(int _round, int _radius) {... ...initEvent(radius, 1.5f);}public static void main(String[] args) {GaussianBlur blur = new GaussianBlur(5, 1);try {blur.gaussianBlur("F:\\Wall Paper\\9.jpg", "F:\\Wall Paper\\9-gb.jpg");} catch (IOException e) {e.printStackTrace();}}/*** 基于正态分布的图片高斯模糊*/public void gaussianBlur(String sourcePath, String targetPath) throws IOException {gaussianBlur(sourcePath, targetPath, round, radius);}/*** 基于正态分布的图片高斯模糊*/public void gaussianBlur(String sourcePath, String targetPath, int round, int radius) throws IOException {BufferedImage bufferedImage = ImageIO.read(new File(sourcePath));int height = bufferedImage.getHeight();int width = bufferedImage.getWidth();int matrixLength = 2 * radius + 1;int[][] matrix = new int[matrixLength][matrixLength];int[] values = new int[matrixLength * matrixLength];for (int r = 0; r < round; r++) {for (int i = 0; i < width / 2; i++) {for (int j = 0; j < height; j++) {readPixel(bufferedImage, i, j, values);fillMatrix(matrix, values);bufferedImage.setRGB(i, j, avgMatrix(matrix));}}}ImageIO.write(bufferedImage, "jpg", new File(targetPath));}/** 初始化任务*/private void initEvent(int n, float σ) {normal_distribution = MathUtils.getTwoDimenGaussianSumOne(n, σ);}/** 读取图片上的像素点*/private void readPixel(BufferedImage img, int x, int y, int[] pixels) {int radius = (int) ((Math.sqrt(pixels.length) - 1) / 2);int raw = 2 * radius + 1;int clo = 2 * radius + 1;int xStart = x - radius;int yStart = y - radius;int current = 0;for (int i = xStart; i < clo + xStart; i++) {for (int j = yStart; j < raw + yStart; j++) {int tx = i;// 边界处理if (tx < 0) {tx = -tx;} else if (tx >= img.getWidth()) {tx = x;}int ty = j;// 边界处理if (ty < 0) {ty = -ty;} else if (ty >= img.getHeight()) {ty = y;}pixels[current++] = img.getRGB(tx, ty);}}}/** 将读取的像素RGB值保存到二维数组中*/private void fillMatrix(int[][] matrix, int... values) {int filled = 0;for (int i = 0; i < matrix.length; i++) {int[] x = matrix[i];for (int j = 0; j < x.length; j++) {x[j] = values[filled++];}}}/** 计算平均值重新写入图片*/private int avgMatrix(int[][] matrix) {int red = 0;int green = 0;int blue = 0;for (int i = 0; i < matrix.length; i++) {for (int j = 0; j < matrix[i].length; j++) {Color color = new Color(matrix[i][j]);red += (normal_distribution[i][j] * color.getRed());green += (normal_distribution[i][j] * color.getGreen());blue += (normal_distribution[i][j] * color.getBlue());}}return new Color(red, green, blue).getRGB();}
}

效果图:

图-7 一轮高斯模糊

图-8 三轮高斯模糊

图-9 五轮高斯模糊

图-10 十轮高斯模糊

Ref:

高斯模糊的算法:http://www.ruanyifeng.com/blog/2012/11/gaussian_blur.html

图像处理之高斯模糊:http://blog.csdn.net/jia20003/article/details/7234741

注:本文部分图片也是来源于上面的两个博客,在此特作说明。

关联知识点:

1.正态分布

2.卷积图像处理

基于正态分布的图片高斯模糊算法相关推荐

  1. HitPaw Photo Enhancer(图片无损放大软件)官方正式版V1.0.1.7 | 基于ai人工智能图片清晰算法的增强照片清晰度的软件

    HitPaw Photo Enhancer 是一款优秀的图片无损放大软件,采用了先进的ai人工智能图片清晰放大技术,只需三步就能帮助用户一键放大图片并修复模糊的图像使之质量更好,也就是大家常说的增强照 ...

  2. 【SIFT,FPGA】基于FPGA的图片sift算法,图像的配准融合在上位机上实现

    目录 1.软件版本 2.本算法理论知识 1.图像存储和预处理 2.Hessian 3.FIFO 4.非最大值抑制

  3. c语言编程图片识别条形码,基于Zbar的条形码图像识别算法的制作方法

    本发明涉及条形码识别技术领域,特别是涉及一种基于Zbar的条形码图像识别算法. 背景技术: 条形码是将宽度不等的多个黑条和空白,按一定的编码规则排列,用以表达一组信息的图形标识符.随着科技的迅速发展, ...

  4. ML之SVM:基于SVM(支持向量机)之SVC算法对手写数字图片识别进行预测

    ML之SVM:基于SVM(支持向量机)之SVC算法对手写数字图片识别进行预测 目录 输出结果 设计思路 核心代码 输出结果 设计思路 核心代码 X_train = ss.fit_transform(X ...

  5. CV之FR之MTCNN:基于TF框架利用MTCNN算法检测并对齐人脸图像进(人脸识别/人脸相似度)而得出人脸特征向量从而计算两张人脸图片距离案例应用之详细攻略

    CV之FR之MTCNN:基于TF框架利用MTCNN算法检测并对齐人脸图像进(人脸识别/人脸相似度)而得出人脸特征向量从而计算两张人脸图片距离案例应用之详细攻略 目录 基于TF框架利用MTCNN算法检测 ...

  6. canvas换图时候会闪烁_基于Canvas实现的高斯模糊(上)「JS篇」

    作者:iNahoo 转发链接:https://mp.weixin.qq.com/s/5TxPjznpEBku_ybSMBdnfw 目录 基于Canvas实现的高斯模糊(上)「JS篇」本篇 基于Canv ...

  7. 高斯平滑算法 c语言,高斯模糊算法(gaussian)

    项目上对图像处理需要用到点高斯算法,网上找到一篇对原理及部分问题分析讲解的还不错的文章,分享一下,后付自己的一段代码 - 理论 - 高斯分布函数可表示为一个一维的函数G(x) 或者一个二维的函数G(x ...

  8. 什么是高斯模糊算法?

    通常,图像处理软件将提供模糊滤镜以使图像模糊. 有许多算法可以实现模糊,其中一种称为高斯模糊算法.它利用高斯分布来处理图像. 本文是介绍高斯模糊算法,你会发现这是一个简单的算法.实际上,它是一种可以在 ...

  9. 高斯模糊java代码_Java实现高斯模糊算法处理图像

    高斯模糊(英语:Gaussian Blur),也叫高斯平滑,是在Adobe Photoshop.GIMP以及Paint.NET等图像处理软件中广泛使用的处理效果,通常用它来减少图像噪声以及降低细节层次 ...

最新文章

  1. C# 获取指定目录下所有文件信息、移动目录、拷贝目录
  2. php自动断词,PHP自动分页、防止英文单词被截段、去除HTML代码
  3. 【效率】推荐几个不错的网站!
  4. QT之error: cannot bind non-const lvalue reference of type ‘CBaowen’ to an rvalue of type ‘CBaowen
  5. 【Maven】Maven POM配置详解
  6. airflow sql_alchemy_conn mysql_airflow使用mysql数据库,LocalExecutor并发调度
  7. 【零基础学Java】—LinkedList集合(四十)
  8. 云南民大java期中考试_中南民族大学Java语言程序设计期末试卷A卷
  9. 当我们点击一个文本域在IE下会发生的事件
  10. Java版本中最好用的网易云音乐、qq音乐api请求工具,你还在忙于如何使用java调音乐api?来看下这里的实现
  11. IO流缓冲流等高级流
  12. 特殊矩阵——n阶对称矩阵
  13. 【源码解析】豆瓣电影推荐卡片效果实现原理
  14. R数据分析:生存分析的列线图的理解与绘制详细教程
  15. 百度地图搜索框在弹出层中无法显示问题
  16. kalibr标定realsense鱼眼相机
  17. 可视化拖拽组件库一些技术要点原理分析(二)
  18. C++实现员工工资管理系统
  19. stata:时间变量格式转换
  20. 年后找工作的你,如何写一封好的简历?

热门文章

  1. 密码学信息理论基础2
  2. [optee]-optee中的异常向量表的实现
  3. [ARM-assembly]-ARM ASM内联汇编学习
  4. 后台服务显示右下角弹窗 -- system权限创建用户权限进程
  5. 去除C++中string前面和后面的空白符
  6. 广西中专机器人应用与维护_我校2018级工业机器人应用与维护专业跟岗实习
  7. 2020-12-6(从反汇编理解指针和引用的区别)
  8. 160个Crackme030之一元一次方程
  9. 通过SEH 非inline hook
  10. JavaScript 特有奇葩问题“字符串类型与数字类型混乱”的分析与解决,与类型转换