图像处理 彩色图转化成灰度图

1、介绍。

    通道。三通道一般指彩色图片,分别为R、G、B通道,我们所见的彩色图片,则是这三个通道叠加的效果。四通道一般是指在三通道的基础上再加上一个透明度的通道。单通道一般指灰度图,但是三通道如果每个像素的三个通道值都相等的话,我们也称为灰度图。

    灰度图。Gray Scale Image 或是Grey Scale Image,又称灰阶图。把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶。因为彩色图片每个像素有三个字节(24bit)的值,怎么样才能取到一字节(8bit)的灰度等级呢。我们一般有7种方法:最小值法、最大值法、平均值法、加权法、红色值法、绿色值法和蓝色值法。

    下面我会介绍这7种方法,以下图所示的源图为例。

2、代码。生成两个文件夹,一个存放单通道的图像,另一个存放是三通道的图像。每个文件夹都会各生成7种不同方法灰度化处理的图像。至于使用哪种方法,要看具体的例子。

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

public class ImgTest {
    private static final byte Gray_Type_Min = 1;//最大值法
    private static final byte Gray_Type_Max = 2;//最小值法
    private static final byte Gray_Type_Average = 3;//平均值法
    private static final byte Gray_Type_Weight = 4;//加权法
    private static final byte Gray_Type_Red = 5;//红色值法
    private static final byte Gray_Type_Green = 6;//绿色值法
    private static final byte Gray_Type_Blue = 7;//蓝色值法

    private static final String File_Path = "G:\\xiaojie-java-test\\img\\%s\\%s.jpg";
    private static final String Source_Path = "G:\\xiaojie-java-test\\img\\source.jpg";

    public static void main(String[] args) {
        //图片灰度化
        toGrayImg(Gray_Type_Min, "gray_min");//最大值法
        toGrayImg(Gray_Type_Max, "gray_max");//最小值法
        toGrayImg(Gray_Type_Average, "gray_average");//平均值法
        toGrayImg(Gray_Type_Weight, "gray_weight");//加权法
        toGrayImg(Gray_Type_Red, "gray_color_red");//红色值法
        toGrayImg(Gray_Type_Green, "gray_color_green");//绿色值法
        toGrayImg(Gray_Type_Blue, "gray_color_blue");//蓝色值法
    }

    /**
     * 图片灰度化的方法
     *
     * @param type         灰度化方法
     * @param grayFileName 目标图片文件名
     */
    private static void toGrayImg(int type, String grayFileName) {
        try {
            BufferedImage image = ImageIO.read(new File(Source_Path));
            final int imgWidth = image.getWidth();
            final int imgHeight = image.getHeight();
            BufferedImage bufferedImage_1 = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_BYTE_GRAY);
            BufferedImage bufferedImage_3 = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
            //这边因为只是灰度操作,所以内外循环imgWidth和imgHeight可以随便放
            for (int i = 0; i < imgHeight; i++) {
                for (int j = 0; j < imgWidth; j++) {
                    final int pixel = image.getRGB(j, i);
                    final int[] grb = getRgb(pixel);
                    final int gray = getGray(grb, type);
                    bufferedImage_1.setRGB(j, i, (byte) gray);//这里一定要用byte类型的,不然图片会很暗
                    bufferedImage_3.setRGB(j, i, getPixel(gray, gray, gray));
                    //System.out.print(String.format("%4d ", gray));
                }
                //System.out.println();
            }
            ImageIO.write(bufferedImage_1, "JPEG", new File(String.format(File_Path, "单通道-灰度图", grayFileName)));
            Thread.sleep(1);
            ImageIO.write(bufferedImage_3, "JPEG", new File(String.format(File_Path, "三通道-灰度图", grayFileName)));
            Thread.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //将一个int值转化为3个r、g个b的byte值
    private 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;
    }

    //将3个r、g个b的byte值转化为一个int值
    private static int getPixel(int r, int g, int b) {
        int getPixel = b;
        getPixel += (r << 16);
        getPixel += (g << 8);
        return getPixel;
    }

    //根据不同的灰度化方法,返回byte灰度值
    private static int getGray(int[] rgb, int type) {
        if (type == Gray_Type_Average) {
            return (rgb[0] + rgb[1] + rgb[2]) / 3;   //rgb之和除以3
        } else if (type == Gray_Type_Weight) {
            return (int) (0.3 * rgb[0] + 0.59 * rgb[1] + 0.11 * rgb[2]);
        } else if (type == Gray_Type_Red) {
            return rgb[0];//取红色值
        } else if (type == Gray_Type_Green) {
            return rgb[1];//取绿色值
        } else if (type == Gray_Type_Blue) {
            return rgb[2];//取蓝色值
        }
        //比较三个数的大小
        int gray = rgb[0];
        for (int i = 1; i < rgb.length; i++) {
            if (type == Gray_Type_Min) {
                if (gray > rgb[i]) {
                    gray = rgb[i];//取最小值
                }
            } else if (type == Gray_Type_Max) {
                if (gray < rgb[i]) {
                    gray = rgb[i];//取最大值
                }
            }
        }
        return gray;
    }
}

3、结果。

发布了67 篇原创文章 · 获赞 401 · 访问量 41万+

猜你喜欢

转载自blog.csdn.net/qq_36511401/article/details/102808053
今日推荐