1. 程式人生 > >均值濾波,中值濾波,最大最小值濾波

均值濾波,中值濾波,最大最小值濾波

fin proc repeat 效果 mod ava rom static 包含

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

特別說明一點的是,均值濾波對於高斯噪聲的效果比較好,中值濾波對於椒鹽噪聲的效果比較好

想必大家從上面效果比較中也可以看到一點端倪。因為我選擇的噪聲圖片是椒鹽噪聲的,哈哈

自己讀吧,不解釋了,有問題的可以問,源代碼如下:

[java] view plaincopy
  1. package com.process.blur.study;
  2. import java.awt.image.BufferedImage;
  3. import java.util.ArrayList;
  4. import java.util.Arrays;
  5. public class SmoothFilter extends AbstractBufferedImageOp {
  6. public final static int MEAN_FILTER_TYPE = 1;
  7. public final static int MEADIAN_FILTER_TYPE = 2;
  8. public final static int MIN_MAX_FILTER_TYPE = 4;
  9. private int repeats = 3; // default 1
  10. private int kernel_size = 3; // default 3
  11. private int type = 1; // default mean type
  12. public int getRepeat() {
  13. return repeats;
  14. }
  15. public void setRepeat(int repeat) {
  16. this.repeats = repeat;
  17. }
  18. public int getKernelSize() {
  19. return kernel_size;
  20. }
  21. public void setKernelSize(int kernelSize) {
  22. this.kernel_size = kernelSize;
  23. }
  24. public int getType() {
  25. return type;
  26. }
  27. public void setType(int type) {
  28. this.type = type;
  29. }
  30. @Override
  31. public BufferedImage filter(BufferedImage src, BufferedImage dest) {
  32. int width = src.getWidth();
  33. int height = src.getHeight();
  34. if ( dest == null )
  35. dest = createCompatibleDestImage( src, null );
  36. int[] inPixels = new int[width*height];
  37. int[] outPixels = new int[width*height];
  38. getRGB( src, 0, 0, width, height, inPixels );
  39. // pick up one filter from here!!!
  40. if(this.type == MEAN_FILTER_TYPE)
  41. {
  42. for(int i=0; i<repeats; i++) {
  43. performMeanFilter(width, height, inPixels, outPixels);
  44. System.arraycopy(outPixels, 0, inPixels, 0, inPixels.length);
  45. }
  46. }
  47. else if(this.type == MEADIAN_FILTER_TYPE)
  48. {
  49. performMedianFilter(width, height, inPixels, outPixels);
  50. }
  51. else if(this.type == MIN_MAX_FILTER_TYPE)
  52. {
  53. performMinMaxFilter(width, height, inPixels, outPixels);
  54. }
  55. // return result
  56. setRGB( dest, 0, 0, width, height, outPixels );
  57. return dest;
  58. }
  59. /**
  60. * <p> perform convolution filter </p>
  61. *
  62. * @param width
  63. * @param height
  64. * @param inPixels
  65. * @param outPixels
  66. */
  67. public void performMeanFilter(int width, int height, int[] inPixels, int[] outPixels) {
  68. int rows2 = kernel_size/2;
  69. int cols2 = kernel_size/2;
  70. int index = 0;
  71. int index2 = 0;
  72. float total = kernel_size * kernel_size;
  73. for (int y = 0; y < height; y++) {
  74. for (int x = 0; x < width; x++) {
  75. float r = 0, g = 0, b = 0, a = 0;
  76. for (int row = -rows2; row <= rows2; row++) {
  77. int rowoffset = y + row;
  78. if(rowoffset < 0 || rowoffset >=height) {
  79. rowoffset = y;
  80. }
  81. //System.out.println("rowoffset == " + rowoffset);
  82. for(int col = -cols2; col <= cols2; col++) {
  83. int coloffset = col + x;
  84. if(coloffset < 0 || coloffset >= width) {
  85. coloffset = x;
  86. }
  87. index2 = rowoffset * width + coloffset;
  88. int rgb = inPixels[index2];
  89. a += ((rgb >> 24) & 0xff);
  90. r += ((rgb >> 16) & 0xff);
  91. g += ((rgb >> 8) & 0xff);
  92. b += (rgb & 0xff);
  93. }
  94. }
  95. int ia = 0xff;
  96. int ir = clamp((int)(r/total));
  97. int ig = clamp((int)(g/total));
  98. int ib = clamp((int)(b/total));
  99. outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
  100. }
  101. }
  102. }
  103. /**
  104. * <p> perform median filter </p>
  105. *
  106. * @param width
  107. * @param height
  108. * @param src
  109. * @param inPixels
  110. * @param outPixels
  111. */
  112. public void performMedianFilter(int width, int height, int[] inPixels, int[] outPixels) {
  113. int rows2 = kernel_size/2;
  114. int cols2 = kernel_size/2;
  115. int index = 0;
  116. int index2 = 0;
  117. float total = kernel_size * kernel_size;
  118. int[] matrix = new int[(int)total];
  119. for (int y = 0; y < height; y++) {
  120. for (int x = 0; x < width; x++) {
  121. int count = 0;
  122. for (int row = -rows2; row <= rows2; row++) {
  123. int rowoffset = y + row;
  124. if(rowoffset < 0 || rowoffset >=height) {
  125. rowoffset = y;
  126. }
  127. for(int col = -cols2; col <= cols2; col++) {
  128. int coloffset = col + x;
  129. if(coloffset < 0 || coloffset >= width) {
  130. coloffset = x;
  131. }
  132. index2 = rowoffset * width + coloffset;
  133. int rgb = inPixels[index2];
  134. matrix[count] = rgb;
  135. count++;
  136. }
  137. }
  138. Arrays.sort(matrix);
  139. int ia = 0xff;
  140. int ir = ((matrix[count/2] >> 16) & 0xff);
  141. int ig = ((matrix[count/2] >> 8) & 0xff);
  142. int ib = (matrix[count/2] & 0xff);
  143. outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
  144. }
  145. }
  146. }
  147. /**
  148. * <p> perform min/max pixel filter </p>
  149. *
  150. * @param width
  151. * @param height
  152. * @param src
  153. * @param inPixels
  154. * @param outPixels
  155. */
  156. public void performMinMaxFilter(int width, int height, int[] inPixels, int[] outPixels) {
  157. int rows2 = kernel_size/2;
  158. int cols2 = kernel_size/2;
  159. int index = 0;
  160. int index2 = 0;
  161. float total = kernel_size * kernel_size;
  162. int[] matrix = new int[(int)total];
  163. for (int y = 0; y < height; y++) {
  164. for (int x = 0; x < width; x++) {
  165. int count = 0;
  166. for (int row = -rows2; row <= rows2; row++) {
  167. int rowoffset = y + row;
  168. if(rowoffset < 0 || rowoffset >=height) {
  169. rowoffset = y;
  170. }
  171. for(int col = -cols2; col <= cols2; col++) {
  172. int coloffset = col + x;
  173. if(coloffset < 0 || coloffset >= width) {
  174. coloffset = x;
  175. }
  176. index2 = rowoffset * width + coloffset;
  177. int rgb = inPixels[index2];
  178. matrix[count] = rgb;
  179. count++;
  180. }
  181. }
  182. int ia = 0xff;
  183. int oldPixel = matrix[count/2];
  184. int targetRGB = findNewPixel(matrix, oldPixel);
  185. int ir = ((targetRGB >> 16) & 0xff);
  186. int ig = ((targetRGB >> 8) & 0xff);
  187. int ib = (targetRGB & 0xff);
  188. outPixels[index++] = (ia << 24) | (ir << 16) | (ig << 8) | ib;
  189. }
  190. }
  191. }
  192. private int findNewPixel(int[] matrix, int oldPixel) {
  193. ArrayList<Integer> list = new ArrayList<Integer>();
  194. for(int i=0; i<matrix.length; i++) {
  195. if(matrix[i] == oldPixel)
  196. continue;
  197. list.add(matrix[i]);
  198. }
  199. int[] filterData = new int[list.size()];
  200. int index = 0;
  201. for(Integer rgb : list) {
  202. filterData[index++] = rgb;
  203. }
  204. Arrays.sort(filterData);
  205. if(filterData.length == 0)
  206. return oldPixel;
  207. return (oldPixel > filterData[0]) ? filterData[0] : (oldPixel < filterData[filterData.length -1])? filterData[filterData.length -1] : oldPixel;
  208. }
  209. public static int clamp(int c) {
  210. if (c < 0)
  211. return 0;
  212. if (c > 255)
  213. return 255;
  214. return c;
  215. }
  216. }
[java] view plain copy

均值濾波,中值濾波,最大最小值濾波