图像处理 图片二值化和获取不同图像通道的图片

1、介绍。

    二值化。图像二值化( Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。

    图像通道。在Photoshop中有一个很重要概念叫图像通道,在RGB色彩模式下就是指那单独的红色、绿色、蓝色部分。也就是说,一幅完整的图像,是由红色绿色蓝色三个通道组成的。他们共同作用产生了完整的图像。

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

2、代码

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) {
        //获取不同通道图片的方法
        toChannelImg();

        //先灰度化,再二值化(灰度化暂时使用加权法)
        toBinaryImg(20);
        toBinaryImg(40);
        toBinaryImg(60);
        toBinaryImg(80);
        toBinaryImg(100);
        toBinaryImg(120);
        toBinaryImg(140);
        toBinaryImg(160);
        toBinaryImg(180);
        toBinaryImg(200);
        toBinaryImg(220);
        toBinaryImg(240);
    }

    /**
     * 获取不同通道图片的方法
     */
    private static void toChannelImg() {
        try {
            BufferedImage image = ImageIO.read(new File(Source_Path));
            final int imgWidth = image.getWidth();
            final int imgHeight = image.getHeight();
            BufferedImage bufferedImage_red = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
            BufferedImage bufferedImage_green = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_INT_RGB);
            BufferedImage bufferedImage_blue = 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);
                    bufferedImage_red.setRGB(j, i, pixel & 0xff0000);
                    bufferedImage_green.setRGB(j, i, pixel & 0x00ff00);
                    bufferedImage_blue.setRGB(j, i, pixel & 0x0000ff);
                    //System.out.print(String.format("%4d ", gray));
                }
                //System.out.println();
            }
            ImageIO.write(bufferedImage_red, "JPEG", new File(String.format(File_Path, "三通道-图像通道", "red")));
            Thread.sleep(1);
            ImageIO.write(bufferedImage_green, "JPEG", new File(String.format(File_Path, "三通道-图像通道", "green")));
            Thread.sleep(1);
            ImageIO.write(bufferedImage_blue, "JPEG", new File(String.format(File_Path, "三通道-图像通道", "blue")));
            Thread.sleep(1);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //先灰度化,再二值化(灰度化暂时使用加权法)
    private static void toBinaryImg(int threshold) {
        try {
            BufferedImage image = ImageIO.read(new File(Source_Path));
            final int imgWidth = image.getWidth();
            final int imgHeight = image.getHeight();
            BufferedImage bufferedImage = new BufferedImage(imgWidth, imgHeight, BufferedImage.TYPE_BYTE_BINARY);
            //这边因为只是灰度操作,所以内外循环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, Gray_Type_Weight);
                    bufferedImage.setRGB(j, i, (byte) (gray < threshold ? 0 : 255));
                    //System.out.print(String.format("%4d ", gray));
                }
                //System.out.println();
            }
            ImageIO.write(bufferedImage, "JPEG", new File(String.format(File_Path, "单通道-二值图", "binary_" + threshold)));
            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;
    }

    //根据不同的灰度化方法,返回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/102808820