镇江建设网站,免费网站建设一级,计算机一级网页制作教程,现在流行用什么做网站图像平滑 一、图像的噪声1.1、噪声来源1.2、噪声类型1.3、噪声模拟 二、滤波器三、线性滤波3.1、均值滤波3.2、方框滤波3.3、高斯滤波 四、非线性滤波4.1、中值滤波4.2、双边滤波 图像在采集和传输过程中容易受到各种因素的影响而产生噪声#xff0c;而噪声会对图像的正确解读… 图像平滑 一、图像的噪声1.1、噪声来源1.2、噪声类型1.3、噪声模拟 二、滤波器三、线性滤波3.1、均值滤波3.2、方框滤波3.3、高斯滤波 四、非线性滤波4.1、中值滤波4.2、双边滤波 图像在采集和传输过程中容易受到各种因素的影响而产生噪声而噪声会对图像的正确解读和处理产生干扰因此去除图像中的噪声十分重要。去除图像中噪声的过程为图像平滑或图像去噪、图像模糊。 噪声信号主要集中在高频段图像平滑从信号处理的角度看就是去除高频信号保留低频信号因而属于低通滤波。与低通滤波相对应的是高通滤波边缘检测、锐化等操作就属于高通滤波。
图像滤波是指在尽可能保留图像细节特征的前提下去除噪声或者提取需要的信息。图像滤波又可分为线性滤波和非线性滤波。滤波器的种类很多在OpenCV中用于图像平滑处理的滤波器主要有5种这5种滤波器及相应的函数如下
均值滤波blur()函数方框滤波boxFilter()函数高斯滤波GaussianBlur()函数中值滤波medianBlur()函数双边滤波bilateralFilter()函数
这5种滤波器中均值滤波、方框滤波和高斯滤波属于线性滤波中值滤波和双边滤波则属于非线性滤波。
一、图像的噪声
噪声在图像上常表现为随机的、离散的、孤立的像素或像素块而且往往比较显眼。噪声通常是不必要或多余的信息不但无用还会干扰人们对有用信息的接受。
1.1、噪声来源
噪声的产生主要有以下有两个来源
1. 图像获取过程
图像传感器在采集图像过程中受传感器材料属性、工作环境等因素的影响会引入各种噪声。
2. 图像传输过程 由于传输介质和存储设备等方面的原因数字图像在传输过程中受到各种噪声的污染。另外在图像处理的某些环节也可能产生噪声。
1.2、噪声类型
噪声通常可分为高斯噪声、椒盐噪声、泊松噪声和乘性噪声等
椒盐噪声椒盐噪声也称为脉冲噪声是一种随机生成的亮点或暗点因为形似椒盐而得名。椒盐噪声的成因可能是传感器等硬件问题也可能是环境中强烈的电磁干扰。高斯噪声高斯噪声是指概率密度函数符合高斯分布的一类噪声。高斯分布有均值u和标准差a两个参数其中u是正态分布的位置参数用于描述正态分布的集中趋势位置a则用于描述正态分布的离散程度。高斯噪声产生的主要原因如下 拍摄时照明不够且亮度不均匀元器件自身的噪声及相互影响相机等设备长时间工作导致温度过高
1.3、噪声模拟
OpenCV中没有专门产生椒盐噪声和高斯噪声的函数不过都可以通过随机函数来模拟。
public class Peppersalt {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat img Imgcodecs.imread(F:/IDEAworkspace/opencv/src/main/java/demo2/shaomai.png);HighGui.imshow(img, img);HighGui.waitKey(0);int row img.rows();int col img.cols();//定义黑白两种颜色double[] black new double[] {0, 0, 0};double[] white new double[] {255, 255, 255};//用于获取随机数的RandomRandom r new Random();for (int n 0; n 20000; n) {//随机获得行号、列号及噪点颜色int i r.nextInt(row);int j r.nextInt(col);boolean isBlack r.nextBoolean();//在相应的像素上加上黑白噪点if (isBlack) {img.put(i, j, black);} else {img.put(i, j, white);}}//在屏幕上显示加了椒盐噪声的图像HighGui.imshow(Peppersalt, img);HighGui.waitKey(0);System.exit(0);}
}原图 添加噪声后
二、滤波器
为了去除图像中的噪声需要对图像进行平滑处理而滤波器可以实现这个功能。滤波器和像素运算的区别在于像素运算只作用于一像素而滤波器则通常会用到原图像中的多像素进行计算。
一些常见的滤波器如下
//均值滤波1 1 1
1/9 1 1 11 1 1
//边缘检测
0 1 0
1 -4 1
0 1 0
//高斯滤波1 2 1
1/16 2 4 21 2 1
//锐化0 -1 0
-1 5 -10 -1 0滤波器在某些情况下也被称为卷积核下面为一个基础的卷积函数
void Imgproc.filter2D(Mat src, Mat dst, int ddepth, Mat Kernel)src输入图像dst输出图像与src具有相同的尺寸和通道数ddepth输出图像的深度如设置为-1则表示自动选择Kernel卷积核要求是单通道浮点类型矩阵如果不同的通道需要应用不同的卷积核则应将图像拆分后单独处理。卷积核的锚点应该位于卷积核中。默认状态下锚点位于卷积核的中心。
public class Filter2D {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src Imgcodecs.imread(F:/IDEAworkspace/opencv/src/main/java/demo/fish.png);HighGui.imshow(src, src);HighGui.waitKey(0);//用于均值滤波的卷积核Mat k1 new Mat(3, 3, CvType.CV_64F);double[] data3 new double[]{0.111, 0.111, 0.111,0.111, 0.111, 0.111,0.111, 0.111, 0.111};k1.put(0, 0, data3);//均值滤波并显示Mat dst new Mat();Imgproc.filter2D(src, dst, -1, k1);HighGui.imshow(blur, dst);HighGui.waitKey(0);//用于锐化的卷积核Mat k2 new Mat(3, 3, CvType.CV_64F);double[] data new double[] {0, -1, 0,-1, 5, -1};k2.put(0, 0, data);//锐化操作并在屏幕上显示Imgproc.filter2D(src, dst, -1, k2);HighGui.imshow(Sharpen1, dst);HighGui.waitKey(0);//调整过的锐化卷积核Mat k3 new Mat(3, 3, CvType.CV_64F);double[] data2 new double[] {0, -0.5, 0,-0.5, 2.5, -0.5};k3.put(0, 0, data2);//用调整过的锐化卷积核进行锐化并显示Imgproc.filter2D(src, dst, -1, k3);HighGui.imshow(Sharpen2, dst);HighGui.waitKey(0);System.exit(0);}
}程序定义了3个卷积核其中第一个用于均值滤波第二个用于锐化由于这个卷积核相加并不等于1卷积操作后的图像偏亮第三个卷积核对第二个进行了调整。 原图像 均值滤波后
锐化后 调整锐化后 由此可见卷积核设置不当会使输出图像异常通常情况下需要通过处理使卷积核中所有数字相加等于1。 在介绍具体的滤波函数之前需要了解一下图像的边界处理。边界处理的必要性可以用卷积计算过程来说明如下所示。这是均值滤波时卷积计算的过程输入矩阵尺寸为33其中中央像素的值为5。经过卷积计算以后该像素的值变为20在计算过程中用到了该像素周边33区域的所有像素值。在计算其余像素的值时由于外围已经没有像素取值会出现问题。假如规定在卷积计算时必须取到9个数那么其余像素就会因为无法计算而使输出矩阵的尺寸缩小。这样33的矩阵经过卷积运算后尺寸会缩小为11。如果每次滤波矩阵尺寸都要缩小则经过多次处理后的矩阵会小得不成样子而这通常是不可接受的因此在大多数滤波器的实现过程中需要对图像的边界做特殊处理。
在处理边界区域问题时常有以下几种方法
将未处理的边界像素赋值为常数例如黑色。这种方法非常简单但滤波后图像的有效尺寸黑色以外部分还是缩小了。将未处理的边界像素赋值为原图像相同位置的像素值。这种方法也不理想因为滤波前后的像素值往往存在明显的差异。在边界外填充额外的像素对图像进行扩充然后对边界区域进行滤波。这种方法又可细分为以下几种 将图像边界外的像素设为常数例如黑色或灰色。这种方式虽然简单但滤波后的图像边界处仍会有明显的差异特别是滤波器尺寸较大时。将图像的边界像素填充至边界外。相对来讲这种方法的差异不算明显也比较容易实现因而常被选用。其他填充法。
1 15 27 1 1 1
25 5 3 * 1/9 1 1 1 20
11 3 90 1 1 1三、线性滤波
3.1、均值滤波
均值滤波用邻域内所有像素值的平均值来取代原来的像素值。卷积核内的每个数值代表对应像素在计算时的权重而均值滤波的卷积核内所有数值都是相同的这意味着邻域内所有像素的权重相同。均值滤波后某像素的值等于邻域内所有像素的算数平均值计算过程如下
1 15 27 1 1 1
25 5 3 * 1/9 1 1 1 20
11 3 90 1 1 1(11527255311390)/920均值滤波时邻域的大小会直接影响平滑的效果。邻域越大平滑的效果越好但图像也会变得越模糊。邻域过大还会使图像的边缘信息损失严重因此合理选择邻域的大小非常重要。
均值滤波可以消除像素值急剧变化引起的噪声从而使图像趋于平滑但均值滤波也会使图像失去某些细节而变得模糊。OpenCV中用于均值滤波的函数原型如下
//用归一化的方框滤波器对图像进行平滑处理
void Imgproc.blur(Mat src, Mat dst, Size ksize, Point anchor, int borderType)src输入图像通道数不限但图像深度必须是CV_8U、CV_16U、CV_16S、CV_32F或CV_64Fdst输出图像和src具有相同的尺寸和数据类型ksize卷积核尺寸anchor锚点默认值-1, -1表示锚点位于卷积核的中心borderType像素外推法的边界类型可选参数如下 Core.BORDER_CONSTANT用特定值填充如iiiiii|abcdefgh|iiiiiii中用i填充Core.BORDER_REPLICATE两端复制填充如aaaaaa|abcdefgh|hhhhhhhCore.BORDER_REFLECT倒序填充如fedcba|abcdefgh|hgfedcbCore.BORDER_WRAP正序填充如cdefgh|abcdefgh|abcdefgCore.BORDER_REFLECT_101不含边界值的倒序填充如gfedcb|abcdefgh|gfedcbaCore.BORDER_TRANSPARENT随机填充如uvwxyz|abcdefgh|ijklmnoCore.BORDER_REFLECT101同Core.BORDER_REFLECT_101Core.BORDER_DEFAULT同Core.BORDER_REFLECT_101Core.BORDER_ISOLATED忽略感兴趣区域ROI以外部分
public class Blur {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src Imgcodecs.imread(F:/IDEAworkspace/opencv/src/main/java/demo2/pond.png);HighGui.imshow(src, src);HighGui.waitKey(0);//对图像进行均值滤波5*5并显示Mat dst new Mat();Point anchor new Point(-1, -1);int borderType Core.BORDER_REPLICATE;Imgproc.blur(src, dst, new Size(5, 5), anchor, borderType);HighGui.imshow(blur 5*5, dst);HighGui.waitKey(0);//对图像进行均值滤波7*7并显示Imgproc.blur(src, dst, new Size(7, 7));HighGui.imshow(blur 7*7, dst);HighGui.waitKey(0);//对图像进行均值滤波11*11并显示Imgproc.blur(src, dst, new Size(11, 11));HighGui.imshow(blur 11*11, dst);HighGui.waitKey(0);System.exit(0);}
}原图
5*5滤波
7*7滤波
11*11滤波
3.2、方框滤波
实际上均值滤波是方框滤波的一种特殊形式。均值滤波对窗口内的像素计算算术平均值是归一化以后的结果而方框滤波则可以选择不进行归一化。
//用方框滤波器对图像进行平滑处理
void Imgproc.boxFilter(Mat src, Mat dst, int ddepth, Size ksize, Point anchor, boolean normallize)src输入图像dst输出图像和src具有相同的尺寸和数据类型ddepth输出图像的深度。-1表示使用输入图像的深度ksize卷积核的尺寸anchor卷积核的锚点默认值-1-1表示锚点位于卷积核的中心normalize是否进行归一化
public class BoxFilter {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src Imgcodecs.imread(/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/pond.png);HighGui.imshow(src, src);HighGui.waitKey(0);//对图像进行方框滤波不归一化并在屏幕上显示Mat dst new Mat();Imgproc.boxFilter(src, dst, -1, new Size(3, 3), new Point(-1, -1), false);HighGui.imshow(Unnormalized, dst);HighGui.waitKey(0);//对图像进行方框滤波归一化并在屏幕上显示Imgproc.boxFilter(src, dst, -1, new Size(3, 3), new Point(-1, -1), true);HighGui.imshow(normlized, dst);HighGui.waitKey(0);System.exit(0);}
}原图
不归一化方框滤波
归一化滤波 其中未归一化的图像白化严重。未归一化的方框滤波将像素值相加却不平均如果相加后超过255就会变成白色于是图像中出现了大片白色。
3.3、高斯滤波
高斯滤波也是一种线性滤波。高斯滤波实际上是对邻域内的像素值进行加权平均但高斯滤波器考虑了像素离过滤器中心的距离因素距离越近权重越大距离越远权重越小。
1 15 27 1 2 1
25 5 3 * 1/10 2 4 2 15
11 3 90 1 2 1
//加权平均 (1*115*227*125*25*43*211*13*290*1)/1615//用高斯滤波器对图像进行平滑处理
void Imgproc.GaussianBlur(Mat src, Mat dst, Size ksize, double sigmax, double sigmay)src输入图像。图像的通道数不限但深度必须是CV_8U、CV_16U、CV_16S、CV_32F或CV_64F。dst输出图像和src具有相同的尺寸和数据类型ksize高斯滤波器尺寸该尺寸必须是正奇数。如尺寸为0则根据sigma计算尺寸sigmax高斯滤波器在X方向的标准差sigmay高斯滤波器在Y方向的标准差如果sigmay为0则认为其等于sigmax如果sigmax和sigmay均为0则根据ksize计算
public class GaussianBlur {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src Imgcodecs.imread(/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/pond.png);HighGui.imshow(src, src);HighGui.waitKey(0);//对图像进行高斯滤波5*5并显示Mat dst new Mat();Imgproc.GaussianBlur(src, dst, new Size(5, 5), 10, 10);HighGui.imshow(Gaussian 5*5, dst);HighGui.waitKey(0);//对图像进行高斯滤波7*7并显示Imgproc.GaussianBlur(src, dst, new Size(7, 7), 10, 10);HighGui.imshow(Gaussian 7*7, dst);HighGui.waitKey(0);//对图像进行高斯滤波11*11并显示Imgproc.GaussianBlur(src, dst, new Size(11, 11), 10, 10);HighGui.imshow(Gaussian 11*11, dst);HighGui.waitKey(0);System.exit(0);}
}5*5 7*7
11*11:
四、非线性滤波
与线性滤波不同非线性滤波时的像素值不是通过线性运算得来的而是通过排序或逻辑运算等方式得来的。
4.1、中值滤波
中值滤波是一种典型的非线性滤波奇数具体方法是邻域内像素值的中值来取代原有像素值。中值也叫中位数是指把多个数值按升序或降序进行排序位于序列中央位置的数字就是中位数。
1 15 27
25 5 3
11 3 90
//排序
1,3,3,5, 11, 15,25,27,90
//中位数为11中值滤波用于某像素邻域内的中值代替该像素利于消除孤立的噪声点从而使周围的像素更接近真实值因而对于椒盐噪声和斑点噪声非常有效。中值是一个排序后的值可以认为其结果是由邻域像素中的大多数决定的。邻域中出现的个别特别高或特别低的像素值并不会对结果产生太大影响只是使排序结果向前或向后移动了一位因此相对于均值而言中值对邻域中的像素值更具有代表性。在均值滤波或高斯滤波中由于噪声成分也被加入计算之中所以输出或多或少会受到噪声的影响而在中值滤波器中噪声在排序中很难被选上所以对输出几乎没有影响因此中值滤波的去噪效果比线性滤波更好一些但是中值滤波也有其缺陷。由于需要对邻域内所有像素值进行排序中值滤波花费的时间可能达到均值滤波的5倍以上。
//用中值滤波器对图像进行平滑处理
void Imgproc.medianBlur(Mat src, Mat dst, int ksize)src输入图像通道数可以是1、3或4.如果滤波器尺寸是3或5则图像深度应为CV_8U、CV_16U或CV_32F如尺寸更大则必须是CV_8U。dst输出图像和src具有相同的尺寸的数据类型ksize滤波器尺寸必须是大于1的奇数如3、5、7等
public class MedianBlur {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src Imgcodecs.imread(/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/peppersalt.png);HighGui.imshow(src, src);HighGui.waitKey(0);//对图像进行中中值滤波并显示Mat dst new Mat();Imgproc.medianBlur(src, dst, 5);HighGui.imshow(MedianBlur, dst);HighGui.waitKey(0);//对图像进行均值滤波并显示Imgproc.blur(src, dst, new Size(5, 5));HighGui.imshow(Blur, dst);HighGui.waitKey(0);//对图像进行高斯滤波并显示Imgproc.GaussianBlur(src, dst, new Size(5, 5), 10, 10);HighGui.imshow(Gaussian Blur, dst);HighGui.waitKey(0);System.exit(0);}
}原图 中值滤波
均值滤波
高斯滤波 4.2、双边滤波
双边滤波Bilateral Filter也是一种非线性的滤波方法是一种常用的能够保留边缘信息的滤波方法。双边滤波实际上是空间域Spatial Domain和值域Range Domain两个滤波器综合作用的结果。在图像的平坦区域像素值变化很小空间域权重起主导作用此时的双边滤波相当于高斯滤波在图像的边缘区域像素值变化很大值域权重变大边缘信息得以保留。
//用双边滤波器对图像进行处理
void Imgproc.bilateralFilter(Mat src, Mat dst, int d, double sigmaColor, double sigmaSpace)src输入图像必须是单通道或三通道图像深度应为CV_8U、CV_32F或CV_64F。dst输出图像和src具有相同的尺寸和数据类型d滤波时每像素邻域的直径。如为非正数则由sigmaSpace计算而来sigmaColor颜色空间的sigma参数。此参数越大意味着像素邻域中有越多颜色被混合在一起。半相等色的面积也越大。sigmaSpace坐标空间的sigma参数。此参数越大意味着只要像素的颜色足够接近更远的像素会彼此影响。当d0时邻域尺寸不考虑sigamaSpace否则d与sigamaSpace成正比
双边滤波器能在消减噪声的同时保持边缘的清晰但双边滤波器比大多数滤波器要慢很多。在设置双边滤波的参数时应注意以下两点
为了简单起见可以将两个sigma值设为同一个值。当sigma值小于10时效果并不明显但当数值较大150时效果会非常显著图像还会带有卡通风格滤波器的直径较大5时速度非常慢因此实时处理时推荐值为5在离线处理含有大量噪声的图像时可设为9
public class BilateralFilter {static {OpenCV.loadLocally(); // 自动下载并加载本地库}public static void main(String[] args) {//读取图像并显示Mat src Imgcodecs.imread(/Users/acton_zhang/J2EE/MavenWorkSpace/opencv_demo/src/main/java/demo1/butterfly.png);HighGui.imshow(src, src);HighGui.waitKey(0);//对图像进行双边滤波并在屏幕上显示Mat dst new Mat();Imgproc.bilateralFilter(src, dst, 9, 20, 20);HighGui.imshow(Bilateral, dst);HighGui.waitKey(0);//对图像进行均值滤波并显示Imgproc.blur(src, dst, new Size(5, 5));HighGui.imshow(Blur, dst);HighGui.waitKey(0);//对图像进行高斯滤波并显示Imgproc.GaussianBlur(src, dst, new Size(5, 5), 10, 10);HighGui.imshow(Gaussian, dst);HighGui.waitKey(0);System.exit(0);}
}原图 双边滤波
均值滤波
高斯滤波