图像基本变换---图像快速高斯模糊算法
2016-05-13 08:50
357 查看
本文将详细介绍经典高斯滤波的相关内容。
高斯滤波器实质上是一种信号的滤波器,其用途是信号的平滑处理。它是一类根据高斯函数的形状来选择权重的线性平滑滤波器,该滤波器对于抑制服从正态分布的噪声非常有效。高斯函数的公式如下所示:
一维高斯函数:
二维高斯函数:
对于二维高斯函数,它的分布如下图所示:
Fig.1二维Gauss分布
对于二维高斯函数,我们设置两个参数:高斯半径r和方差sigma,由半径r我们可以得到一个(2r+1)*(2r+1)大小的高斯核模板,计算函数代码如下(其中k是高斯模板的权系数,即归一化系数):
private static double[,] GaussFuc(int r, double sigma)
{
int size = 2 * r + 1;
double[,] gaussResult = new double[size, size];
double k = 0.0;
for (int y = -r, h =
0; y <= r; y++, h++)
{
for (int x = -r, w =
0; x <= r; x++, w++)
{
gaussResult[w, h]
= (1.0 / (2.0 * Math.PI * sigma * sigma)) * (Math.Exp(-((double)x *
(double)x + (double)y * (double)y) / (2.0 * sigma * sigma)));
k += gaussResult[w, h];
}
}
return gaussResult;
}
我们设置参数r=1,sigma=1.0,则得到一个3*3的高斯模板如下:
Fig.2 3*3高斯模板
通常,我们在图像处理中使用的高斯函数定义如下:
使用该公式得到3*3高斯模板如下:
Fig.3 3*3高斯模板
对模板修正,即可得到我们常用的3*3经典模板:
Fig.4经典3*3高斯模板
这就是经典高斯模板的计算过程,半径不同,我们可以得到不同的模板。通常使用了3*3和5*5的经典模板:
Fig.5 Gauss 模板
得到高斯模板后,我们用它对图像进行卷积,就可以得到高斯滤波的结果图像了。
由于直接使用公式2-(97),计算量巨大,影响图像处理的,因此,我们采用快速算法,即将公式2-(97)分解为如下公式:
这个公式可以理解为先对图像按行进行一次一维高斯滤波,在对结果图像按列进行一次一维高斯滤波,这样速度将大大提高。
一维高斯滤波代码如下(包含归一化):
private static double[] GaussKernel1D(int r, double sigma)
{
double[] filter = new double[2 * r + 1];
double sum = 0.0;
for (int i = 0; i < filter.Length; i++)
{
filter[i] = Math.Exp((double)(-(i - r) * (i - r)) / (2.0 * sigma * sigma));
sum += filter[i];
}
for (int i = 0; i < filter.Length; i++)
{
filter[i] = filter[i] / sum;
}
return filter;
}
private static double[] GaussKernel(int radius, double sigma)
{
int length=2*radius+1;
double[] kernel = new double[length];
double sum = 0.0;
for (int i = 0; i < length; i++)
{
kernel[i] = Math.Exp((double)(-(i - radius) * (i - radius)) / (2.0 * sigma * sigma));
sum += kernel[i];
}
for (int i = 0; i < length; i++)
{
kernel[i] = kernel[i] / sum;
}
return kernel;
}
///
/// Gauss filter process
///
/// The source image.
/// The radius of gauss kernel,from 0 to 100.
/// The convince of gauss kernel, from 0 to 30.
///
public static WriteableBitmap GaussFilter(WriteableBitmap src,int radius,double sigma) ////高斯滤波
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] srcValue = src.PixelBuffer.ToArray();
byte[] tempValue=(byte[])srcValue.Clone();
double[] kernel = GaussKernel(radius, sigma);
double tempB = 0.0, tempG = 0.0, tempR = 0.0;
int rem = 0;
int t = 0;
int v = 0;
double K = 0.0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
tempB = tempG = tempR = 0.0;
for (int k = -radius; k <= radius; k++)
{
rem = (Math.Abs(x + k) % w);
t = rem * 4 + y * w * 4;
K=kernel[k+radius];
tempB += srcValue[t] * K;
tempG += srcValue[t + 1] * K;
tempR += srcValue[t + 2] * K;
}
v = x * 4 + y * w * 4;
tempValue[v] = (byte)tempB;
tempValue[v + 1] = (byte)tempG;
tempValue[v + 2] = (byte)tempR;
}
}
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
tempB = tempG = tempR = 0.0;
for (int k = -radius; k <= radius; k++)
{
rem = (Math.Abs(y + k) % h);
t = rem * w * 4 + x * 4;
K = kernel[k + radius];
tempB += tempValue[t] * K;
tempG += tempValue[t + 1] * K;
tempR += tempValue[t + 2] * K;
}
v = x * 4 + y * w * 4;
srcValue[v] = (byte)tempB;
srcValue[v + 1] = (byte)tempG;
srcValue[v + 2] = (byte)tempR;
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(srcValue, 0, w * 4 * h);
return srcImage;
}
else
{
return null;
}
}
demo: http://www.zealfilter.com/forum.php?mod=viewthread&tid=26&extra=page%3D2
高斯滤波器实质上是一种信号的滤波器,其用途是信号的平滑处理。它是一类根据高斯函数的形状来选择权重的线性平滑滤波器,该滤波器对于抑制服从正态分布的噪声非常有效。高斯函数的公式如下所示:
一维高斯函数:
二维高斯函数:
对于二维高斯函数,它的分布如下图所示:
Fig.1二维Gauss分布
对于二维高斯函数,我们设置两个参数:高斯半径r和方差sigma,由半径r我们可以得到一个(2r+1)*(2r+1)大小的高斯核模板,计算函数代码如下(其中k是高斯模板的权系数,即归一化系数):
private static double[,] GaussFuc(int r, double sigma)
{
int size = 2 * r + 1;
double[,] gaussResult = new double[size, size];
double k = 0.0;
for (int y = -r, h =
0; y <= r; y++, h++)
{
for (int x = -r, w =
0; x <= r; x++, w++)
{
gaussResult[w, h]
= (1.0 / (2.0 * Math.PI * sigma * sigma)) * (Math.Exp(-((double)x *
(double)x + (double)y * (double)y) / (2.0 * sigma * sigma)));
k += gaussResult[w, h];
}
}
return gaussResult;
}
我们设置参数r=1,sigma=1.0,则得到一个3*3的高斯模板如下:
Fig.2 3*3高斯模板
通常,我们在图像处理中使用的高斯函数定义如下:
使用该公式得到3*3高斯模板如下:
Fig.3 3*3高斯模板
对模板修正,即可得到我们常用的3*3经典模板:
Fig.4经典3*3高斯模板
这就是经典高斯模板的计算过程,半径不同,我们可以得到不同的模板。通常使用了3*3和5*5的经典模板:
Fig.5 Gauss 模板
得到高斯模板后,我们用它对图像进行卷积,就可以得到高斯滤波的结果图像了。
由于直接使用公式2-(97),计算量巨大,影响图像处理的,因此,我们采用快速算法,即将公式2-(97)分解为如下公式:
这个公式可以理解为先对图像按行进行一次一维高斯滤波,在对结果图像按列进行一次一维高斯滤波,这样速度将大大提高。
一维高斯滤波代码如下(包含归一化):
private static double[] GaussKernel1D(int r, double sigma)
{
double[] filter = new double[2 * r + 1];
double sum = 0.0;
for (int i = 0; i < filter.Length; i++)
{
filter[i] = Math.Exp((double)(-(i - r) * (i - r)) / (2.0 * sigma * sigma));
sum += filter[i];
}
for (int i = 0; i < filter.Length; i++)
{
filter[i] = filter[i] / sum;
}
return filter;
}
private static double[] GaussKernel(int radius, double sigma)
{
int length=2*radius+1;
double[] kernel = new double[length];
double sum = 0.0;
for (int i = 0; i < length; i++)
{
kernel[i] = Math.Exp((double)(-(i - radius) * (i - radius)) / (2.0 * sigma * sigma));
sum += kernel[i];
}
for (int i = 0; i < length; i++)
{
kernel[i] = kernel[i] / sum;
}
return kernel;
}
///
/// Gauss filter process
///
/// The source image.
/// The radius of gauss kernel,from 0 to 100.
/// The convince of gauss kernel, from 0 to 30.
///
public static WriteableBitmap GaussFilter(WriteableBitmap src,int radius,double sigma) ////高斯滤波
{
if (src != null)
{
int w = src.PixelWidth;
int h = src.PixelHeight;
WriteableBitmap srcImage = new WriteableBitmap(w, h);
byte[] srcValue = src.PixelBuffer.ToArray();
byte[] tempValue=(byte[])srcValue.Clone();
double[] kernel = GaussKernel(radius, sigma);
double tempB = 0.0, tempG = 0.0, tempR = 0.0;
int rem = 0;
int t = 0;
int v = 0;
double K = 0.0;
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
tempB = tempG = tempR = 0.0;
for (int k = -radius; k <= radius; k++)
{
rem = (Math.Abs(x + k) % w);
t = rem * 4 + y * w * 4;
K=kernel[k+radius];
tempB += srcValue[t] * K;
tempG += srcValue[t + 1] * K;
tempR += srcValue[t + 2] * K;
}
v = x * 4 + y * w * 4;
tempValue[v] = (byte)tempB;
tempValue[v + 1] = (byte)tempG;
tempValue[v + 2] = (byte)tempR;
}
}
for (int x = 0; x < w; x++)
{
for (int y = 0; y < h; y++)
{
tempB = tempG = tempR = 0.0;
for (int k = -radius; k <= radius; k++)
{
rem = (Math.Abs(y + k) % h);
t = rem * w * 4 + x * 4;
K = kernel[k + radius];
tempB += tempValue[t] * K;
tempG += tempValue[t + 1] * K;
tempR += tempValue[t + 2] * K;
}
v = x * 4 + y * w * 4;
srcValue[v] = (byte)tempB;
srcValue[v + 1] = (byte)tempG;
srcValue[v + 2] = (byte)tempR;
}
}
Stream sTemp = srcImage.PixelBuffer.AsStream();
sTemp.Seek(0, SeekOrigin.Begin);
sTemp.Write(srcValue, 0, w * 4 * h);
return srcImage;
}
else
{
return null;
}
}
demo: http://www.zealfilter.com/forum.php?mod=viewthread&tid=26&extra=page%3D2
相关文章推荐
- axes对象的句柄会消失,即首次调用有效,第二次就出现
- java-多线程概述
- WTL学习日志 程序更新管理系统
- 图像基本变换---图像伪色彩
- Spring Boot普通类调用bean
- 五子棋棋型源码
- C语言连接mysql,用GCC编译
- Spring Boot普通类调用bean
- 图像基本变换---快速均值模糊算法
- memcache经典介绍
- Solaris 指令两则
- ios runtime IMP指针 消息转发机制
- Java多线程与并发(四)之中断线程
- 面向对象之魔术方法__get()和__set()
- memcache的一致性hash算法使用
- Linux 将成为 21 世纪汽车主流操作系统
- 如何查看Python的内置函数
- 哈希分布与一致性哈希算法简介
- 如何实现Docker镜像和容器实例的备份迁移
- centos6.5下mysql无法登陆的问题