圖像處理 均值濾波

1、選擇一張高斯噪聲比較明顯的圖片。高斯噪聲是指它的概率密度函數服從高斯分佈(即正態分佈)的一類噪聲。如果一個噪聲,它的幅度分佈服從高斯分佈,而它的功率譜密度又是均勻分佈的,則稱它爲高斯白噪聲。

2、代碼。生成模版半徑分別是3、5和7的圖片。

private static final String File_Path = "G:\\xiaojie-java-test\\img\\";

public static void main(String[] args) {
    String gaussSourcePath = File_Path + "濾波\\高斯濾波\\高斯噪聲.jpg";
    String gaussTargetPath = File_Path + "濾波\\高斯濾波\\均值濾波_";
    ImageService.averageFilter(gaussSourcePath, gaussTargetPath, ImageUtils.Gray_Type_Default, 3);//均值過濾
    ImageService.averageFilter(gaussSourcePath, gaussTargetPath, ImageUtils.Gray_Type_Default, 5);//均值過濾
    ImageService.averageFilter(gaussSourcePath, gaussTargetPath, ImageUtils.Gray_Type_Default, 7);//均值過濾
}
package com.zxj.reptile.utils.image;

import com.zxj.reptile.utils.number.ArrayUtils;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;

public class ImageService {
    /**
     * 均值過濾
     *
     * @param sourcePath   原圖像
     * @param targetPath   目標圖像
     * @param filterLength 過濾的長度
     */
    public static void averageFilter(String sourcePath, String targetPath, int grayType, int filterLength) {
        try {
            //獲取原圖像對象,並獲取原圖像的二維數組
            BufferedImage image = ImageIO.read(new File(sourcePath));
            int[][] imgArrays = ImageUtils.getTwoDimension(image);
            //生成新圖像的二維數組
            imgArrays = ImageUtils.getGrayImg(imgArrays, grayType);//均值過濾
            int[][] newImgArrays = ImageUtils.getAverageFilter(imgArrays, filterLength);//二值化
            //生成新圖片對象,填充像素
            BufferedImage newImage = new BufferedImage(image.getWidth(), image.getHeight(), BufferedImage.TYPE_BYTE_GRAY);
            ImageUtils.setTwoDimension(newImage, newImgArrays, ImageUtils.Channel_Type_1);
            //生成圖片文件
            ImageIO.write(newImage, "JPEG", new File(targetPath + filterLength + ".jpg"));
            Thread.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
package com.zxj.reptile.utils.image;

import java.awt.image.BufferedImage;

public class ImageUtils {
    public static int[][] getAverageFilter(int[][] imgArrays, int filterLength) {
        final int imgHeight = imgArrays.length;
        final int imgWidth = imgArrays[0].length;
        //模版半徑
        int[][] newImgArrays = new int[imgHeight][imgWidth];
        int filterRadius = (filterLength - 1) / 2;
        //均值過濾
        for (int h = 0; h < imgHeight; h++) {//圖片第幾行
            for (int w = 0; w < imgWidth; w++) {//圖片第幾列
                int count = 0;
                int sum = 0;
                for (int templateH = -filterRadius; templateH <= filterRadius; templateH++) {//模版第幾行
                    int rowIndex = h + templateH;
                    if (rowIndex < 0 || rowIndex > imgHeight - 1) {
                        continue;
                    }
                    for (int templateW = -filterRadius; templateW < filterRadius; templateW++) {//模版第幾列
                        int columnIndex = w + templateW;
                        if (columnIndex < 0 || columnIndex > imgWidth - 1) {
                            continue;
                        }
                        sum += imgArrays[rowIndex][columnIndex];
                        count++;
                    }
                }
                newImgArrays[h][w] = sum / count;
            }
        }
        return newImgArrays;
    }

    //灰度處理的方法
    public static final byte Gray_Type_Default = 0;//默認加權法
    public static final byte Gray_Type_Min = 1;//最大值法
    public static final byte Gray_Type_Max = 2;//最小值法
    public static final byte Gray_Type_Average = 3;//平均值法
    public static final byte Gray_Type_Weight = 4;//加權法
    public static final byte Gray_Type_Red = 5;//紅色值法
    public static final byte Gray_Type_Green = 6;//綠色值法
    public static final byte Gray_Type_Blue = 7;//藍色值法

    //生成的圖片是幾通道的
    public static final byte Channel_Type_Default = 0;//默認三通道
    public static final byte Channel_Type_1 = 1;//單通道
    public static final byte Channel_Type_3 = 3;//三通道


    /**
     * 灰度化處理
     *
     * @param imgArrays 圖像二維數組
     * @param grayType  灰度化方法
     */
    public static int[][] getGrayImg(int[][] imgArrays, int grayType) throws Exception {
        final int imgHeight = imgArrays.length;
        final int imgWidth = imgArrays[0].length;
        int[][] newImgArrays = new int[imgHeight][imgWidth];
        for (int h = 0; h < imgHeight; h++) {
            for (int w = 0; w < imgWidth; w++) {
                final int[] grb = getRgb(imgArrays[h][w]);
                newImgArrays[h][w] = getGray(grb, grayType);
            }
        }
        return newImgArrays;
    }


    /**
     * 通過像素值,返回r、g、b顏色通道的值
     *
     * @param pixel 像素值
     */
    public static int[] getRgb(int pixel) {
        int[] rgb = new int[3];
        rgb[0] = (pixel >> 16) & 0xff;
        rgb[1] = (pixel >> 8) & 0xff;
        rgb[2] = pixel & 0xff;
        return rgb;
    }

    /**
     * 根據不同的灰度化方法,返回灰度值
     *
     * @param rgb      r、g、b顏色通道的值
     * @param grayType 不同灰度處理的方法
     */
    public static int getGray(int[] rgb, int grayType) throws Exception {
        if (grayType == Gray_Type_Average) {
            return (rgb[0] + rgb[1] + rgb[2]) / 3;   //rgb之和除以3
        } else if (grayType == Gray_Type_Weight || grayType == Gray_Type_Default) {
            return (int) (0.3 * rgb[0] + 0.59 * rgb[1] + 0.11 * rgb[2]);
        } else if (grayType == Gray_Type_Red) {
            return rgb[0];//取紅色值
        } else if (grayType == Gray_Type_Green) {
            return rgb[1];//取綠色值
        } else if (grayType == Gray_Type_Blue) {
            return rgb[2];//取藍色值
        }
        //比較三個數的大小
        int gray = rgb[0];
        for (int i = 1; i < rgb.length; i++) {
            if (grayType == Gray_Type_Min) {
                if (gray > rgb[i]) {
                    gray = rgb[i];//取最小值
                }
            } else if (grayType == Gray_Type_Max) {
                if (gray < rgb[i]) {
                    gray = rgb[i];//取最大值
                }
            } else {
                throw new Exception("grayType出錯");
            }
        }
        return gray;
    }

    /**
     * 獲取二維像素
     *
     * @param image BufferedImage圖像對象
     */
    public static int[][] getTwoDimension(BufferedImage image) {
        final int imgWidth = image.getWidth();
        final int imgHeight = image.getHeight();
        int[][] imgArrays = new int[imgHeight][imgWidth];
        for (int i = 0; i < imgHeight; i++) {
            for (int j = 0; j < imgWidth; j++) {
                imgArrays[i][j] = image.getRGB(j, i);
            }
        }
        return imgArrays;
    }

    /**
     * 將二維像素填充到圖像中
     *
     * @param image       BufferedImage圖像對象
     * @param imgArrays   二維像素
     * @param channelType 單通道還是三通道
     */
    public static void setTwoDimension(BufferedImage image, int[][] imgArrays, int channelType) throws Exception {
        final int imgWidth = image.getWidth();
        final int imgHeight = image.getHeight();
        for (int i = 0; i < imgHeight; i++) {
            for (int j = 0; j < imgWidth; j++) {
                if (channelType == Channel_Type_1) {
                    image.setRGB(j, i, (byte) imgArrays[i][j]);
                } else if (channelType == Channel_Type_3 || channelType == Channel_Type_Default) {
                    image.setRGB(j, i, imgArrays[i][j]);
                } else {
                    throw new Exception("channelType錯誤");
                }
            }
        }
    }

}

3、結果。半徑越長,圖像越模糊。

4、結論。

        均值濾波採用線性的方法,平均整個窗口範圍內的像素值,均值濾波本身存在着固有的缺陷。它不能很好地保護圖像細節,在圖像去噪的同時也破壞了圖像的細節部分,從而使圖像變得模糊。均值濾波只適合處理高斯噪聲的圖片,而對椒鹽噪聲的處理則十分的不理想。當模版的長度越長,則圖像就會越加的模糊。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章