均值滤波
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了均值滤波相关的知识,希望对你有一定的参考价值。
参考技术A 均值滤波是指用当前像素点周围N·N个像素值的均值来代替当前像素值。使用该方法遍历处理图像内的每一个像素点,即可完成整幅图像的均值滤波。例如,希望对图7-7中位于第5行第5列的像素点进行均值滤波。
根据上述运算,针对每一个像素点,都是与一个内部值均为1/25的5×5矩阵相乘,得到均值滤波的计算结果,如图7-11所示。
将使用的5×5矩阵一般化,可以得到如图7-12所示的结果。
式中,M和N分别对应高度和宽度。一般情况下,M和N是相等的,例如比较常用的3×3、5×5、7×7等。如果M和N的值越大,参与运算的像素点数量就越多,图像失真越严重。
在OpenCV中,实现均值滤波的函数是cv2.blur(),其语法格式为:
式中:
通常情况下,使用均值滤波函数时,对于锚点anchor和边界样式borderType,直接采用其默认值即可。
【例7.2】针对噪声图像,使用不同大小的卷积核对其进行均值滤波,并显示均值滤波的情况。
从图中可以看出,使用5×5的卷积核进行滤波处理时,图像的失真不明显;而使用30×30的卷积核进行滤波处理时,图像的失真情况较明显。
卷积核越大,参与到均值运算中的像素就会越多,即当前点计算的是更多点的像素值的平均值。因此,卷积核越大,去噪效果越好,当然花费的计算时间也会越长,同时让图像失真越严重。在实际处理中,要在失真和去噪效果之间取得平衡,选取合适大小的卷积核。
均值滤波,中值滤波,最大最小值滤波
http://blog.csdn.net/fastbox/article/details/7984721
讨论如何使用卷积作为数学工具来处理图像,实现图像的滤波,其方法包含以下几种,均值
滤波,中值滤波,最大最小值滤波,关于什么是卷积以及理解卷积在图像处理中作用参见这
里–http://blog.csdn.net/jia20003/article/details/7038938
均值滤波:
均值滤波,是图像处理中最常用的手段,从频率域观点来看均值滤波是一种低通滤波器,高
频信号将会去掉,因此可以帮助消除图像尖锐噪声,实现图像平滑,模糊等功能。理想的均
值滤波是用每个像素和它周围像素计算出来的平均值替换图像中每个像素。采样Kernel数
据通常是3X3的矩阵,如下表示:
从左到右从上到下计算图像中的每个像素,最终得到处理后的图像。均值滤波可以加上两个
参数,即迭代次数,Kernel数据大小。一个相同的Kernel,但是多次迭代就会效果越来越好。
同样,迭代次数相同,Kernel矩阵越大,均值滤波的效果就越明显。
中值滤波
中值滤波也是消除图像噪声最常见的手段之一,特别是消除椒盐噪声,中值滤波的效果要比
均值滤波更好。中值滤波是跟均值滤波唯一不同是,不是用均值来替换中心每个像素,而是
将周围像素和中心像素排序以后,取中值,一个3X3大小的中值滤波如下:
最大最小值滤波
最大最小值滤波是一种比较保守的图像处理手段,与中值滤波类似,首先要排序周围像素和
中心像素值,然后将中心像素值与最小和最大像素值比较,如果比最小值小,则替换中心像
素为最小值,如果中心像素比最大值大,则替换中心像素为最大值。一个Kernel矩阵为3X3的最大最小值滤波如下:
原图如下:
分别实现中值和均值滤波以后效果如下:
代码就不解释了,原理已经解释得很清楚了,全部算法源代码都是基于Java
特别说明一点的是,均值滤波对于高斯噪声的效果比较好,中值滤波对于椒盐噪声的效果比较好
想必大家从上面效果比较中也可以看到一点端倪。因为我选择的噪声图片是椒盐噪声的,哈哈
自己读吧,不解释了,有问题的可以问,源代码如下:
- package com.process.blur.study;
- import java.awt.image.BufferedImage;
- import java.util.ArrayList;
- import java.util.Arrays;
- public class SmoothFilter extends AbstractBufferedImageOp {
- public final static int MEAN_FILTER_TYPE = 1;
- public final static int MEADIAN_FILTER_TYPE = 2;
- public final static int MIN_MAX_FILTER_TYPE = 4;
- private int repeats = 3; // default 1
- private int kernel_size = 3; // default 3
- private int type = 1; // default mean type
- public int getRepeat() {
- return repeats;
- }
- public void setRepeat(int repeat) {
- this.repeats = repeat;
- }
- public int getKernelSize() {
- return kernel_size;
- }
- public void setKernelSize(int kernelSize) {
- this.kernel_size = kernelSize;
- }
- public int getType() {
- return type;
- }
- public void setType(int type) {
- this.type = type;
- }
- @Override
- public BufferedImage filter(BufferedImage src, BufferedImage dest) {
- int width = src.getWidth();
- int height = src.getHeight();
- if ( dest == null )
- dest = createCompatibleDestImage( src, null );
- int[] inPixels = new int[width*height];
- int[] outPixels = new int[width*height];
- getRGB( src, 0, 0, width, height, inPixels );
- // pick up one filter from here!!!
- if(this.type == MEAN_FILTER_TYPE)
- {
- for(int i=0; i<repeats; i++) {
- performMeanFilter(width, height, inPixels, outPixels);
- System.arraycopy(outPixels, 0, inPixels, 0, inPixels.length);
- }
- }
- else if(this.type == MEADIAN_FILTER_TYPE)
- {
- performMedianFilter(width, height, inPixels, outPixels);
- }
- else if(this.type == MIN_MAX_FILTER_TYPE)
- {
- performMinMaxFilter(width, height, inPixels, outPixels);
- }
- // return result
- setRGB( dest, 0, 0, width, height, outPixels );
- return dest;
- }
- /**
- * <p> perform convolution filter </p>
- *
- * @param width
- * @param height
- * @param inPixels
- * @param outPixels
- */
- public void performMeanFilter(int width, int height, int[] inPixels, int[] outPixels) {
- int rows2 = kernel_size/2;
- int cols2 = kernel_size/2;
- int index = 0;
- int index2 = 0;
- float total = kernel_size * kernel_size;
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- float r = 0, g = 0, b = 0, a = 0;
- for (int row = -rows2; row <= rows2; row++) {
- int rowoffset = y + row;
- if(rowoffset < 0 || rowoffset >=height) {
- rowoffset = y;
- }
- //System.out.println("rowoffset == " + rowoffset);
- for(int col = -cols2; col <= cols2; col++) {
- int coloffset = col + x;
- if(coloffset < 0 || coloffset >= width) {
- coloffset = x;
- }
- index2 = rowoffset * width + coloffset;
- int rgb = inPixels[index2];
- a += ((rgb >> 24) & 0xff);
- r += ((rgb >> 16) & 0xff);
- g += ((rgb >> 8) & 0xff);
- b += (rgb & 0xff);
- }
- }
- int ia = 0xff;
- int ir = clamp((int)(r/total));
- int ig = clamp((int)(g/total));
- int ib = clamp((int)(b/total));
- outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
- }
- }
- }
- /**
- * <p> perform median filter </p>
- *
- * @param width
- * @param height
- * @param src
- * @param inPixels
- * @param outPixels
- */
- public void performMedianFilter(int width, int height, int[] inPixels, int[] outPixels) {
- int rows2 = kernel_size/2;
- int cols2 = kernel_size/2;
- int index = 0;
- int index2 = 0;
- float total = kernel_size * kernel_size;
- int[] matrix = new int[(int)total];
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- int count = 0;
- for (int row = -rows2; row <= rows2; row++) {
- int rowoffset = y + row;
- if(rowoffset < 0 || rowoffset >=height) {
- rowoffset = y;
- }
- for(int col = -cols2; col <= cols2; col++) {
- int coloffset = col + x;
- if(coloffset < 0 || coloffset >= width) {
- coloffset = x;
- }
- index2 = rowoffset * width + coloffset;
- int rgb = inPixels[index2];
- matrix[count] = rgb;
- count++;
- }
- }
- Arrays.sort(matrix);
- int ia = 0xff;
- int ir = ((matrix[count/2] >> 16) & 0xff);
- int ig = ((matrix[count/2] >> 8) & 0xff);
- int ib = (matrix[count/2] & 0xff);
- outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
- }
- }
- }
- /**
- * <p> perform min/max pixel filter </p>
- *
- * @param width
- * @param height
- * @param src
- * @param inPixels
- * @param outPixels
- */
- public void performMinMaxFilter(int width, int height, int[] inPixels, int[] outPixels) {
- int rows2 = kernel_size/2;
- int cols2 = kernel_size/2;
- int index = 0;
- int index2 = 0;
- float total = kernel_size * kernel_size;
- int[] matrix = new int[(int)total];
- for (int y = 0; y < height; y++) {
- for (int x = 0; x < width; x++) {
- int count = 0;
- for (int row = -rows2; row <= rows2; row++) {
- int rowoffset = y + row;
- if(rowoffset < 0 || rowoffset >=height) {
- rowoffset = y;
- }
- for(int col = -cols2; col <= cols2; col++) {
- int coloffset = col + x;
- if(coloffset < 0 || coloffset >= width) {
- coloffset = x;
- }
- index2 = rowoffset * width + coloffset;
- int rgb = inPixels[index2];
- matrix[count] = rgb;
- count++;
- }
- }
- int ia = 0xff;
- int oldPixel = matrix[count/2];
- int targetRGB = findNewPixel(matrix, oldPixel);
- int ir = ((targetRGB >> 16) & 0xff);
- int ig = ((targetRGB >> 8) & 0xff);
- int ib = (targetRGB & 0xff);
- outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
- }
- }
- }
- private int findNewPixel(int[] matrix, int oldPixel) {
- ArrayList<Integer> list = new ArrayList<Integer>();
- for(int i=0; i<matrix.length; i++) {
- if(matrix[i] == oldPixel)
- continue;
- list.add(matrix[i]);
- }
- int[] filterData = new int[list.size()];
- int index = 0;
- for(Integer rgb : list) {
- filterData[index++] = rgb;
- }
- Arrays.sort(filterData);
- if(filterData.length == 0)
- return oldPixel;
- return (oldPixel > filterData[0]) ? filterData[0] : (oldPixel < filterData[filterData.length -1])? filterData[filterData.length -1] : oldPixel;
- }
- public static int clamp(int c) {
- if (c < 0)
- return 0;
- if (c > 255)
- return 255;
- return c;
- }
- }
以上是关于均值滤波的主要内容,如果未能解决你的问题,请参考以下文章