无法在 java 中获取图像的灰度

Can't get gray scale of an image in java

我在获取 .jpg 文件的灰度时遇到问题。我正在尝试创建一个新的灰度 .jpg 文件,但我只是复制图像而已。这是我的代码:

package training01;

import java.awt.*;
import java.awt.image.BufferedImage;

import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.JFrame;

public class GrayScale {
    BufferedImage image;
    int width;
    int height;
    public GrayScale() {
        try {
            File input = new File("digital_image_processing.jpg");
            image = ImageIO.read(input);
            width = image.getWidth();
            height = image.getHeight();
            for(int i = width;i < width;i++) {
                for(int j = height;j < height;j++) {
                    Color c =  new Color(image.getRGB(i, j));
                    int red = c.getRed();
                    int green = c.getGreen();
                    int blue = c.getBlue();
                    int val = (red+green+blue)/3;
                    Color temp = new Color(val,val,val);
                    image.setRGB(i, j, temp.getRGB());
                }
            }
            File output = new File("digital_image_processing1.jpg");
            ImageIO.write(image, "jpg", output);
        }catch(Exception e) {
            System.out.println(e);
        }
    }
    public static void main(String[] args) {
        GrayScale gs = new GrayScale();
    }
}

您需要更改以下内容。从 0 开始你的 i 和 j。

      for(int i = width;i < width;i++) {  
         for(int j = height;j < height;j++) {

但是,这里有一个更快的方法。将其写入为灰度设置的新 BufferedImage 对象。

      image = ImageIO.read(input);
      width = image.getWidth();
      height = image.getHeight();
      bwImage = new BufferedImage(width,
            height, BufferedImage.TYPE_BYTE_GRAY);
      Graphics g = bwImage.getGraphics();
            g.drawImage(image,0,0,null);

然后保存bwImage。

你的代码的主要问题是它不会循环,因为你将 i, j 初始化为 width, height 这已经大于 for 循环的退出条件(i < width, j < height)。通过将 ij 初始化为 0 从 0 开始迭代,您的代码将按预期工作。

为了获得更好的性能,您还想更改循环的顺序。由于 BufferedImage 逐行存储为连续数组,如果在内循环中遍历 x 轴(行),您将更好地利用 CPU 缓存。

旁注:我还建议将 ij 重命名为 xy 以提高可读性。

最后,您通过平均颜色将 RGB 转换为灰色的方法可行,但不是转换为灰度的最常用方法,因为人眼不会将颜色的强度感知为相同。请参阅 Wikipedia on gray scale conversion 以更好地理解正确的转换及其背后的理论。


然而,综上所述,对于存储为 YCbCr(最常见的 JPEG 存储方式)的 JPEG 图像,有一种更快、内存效率更高且更简单的方法将图像转换为灰度,那就是只需读取 JPEG 的 Y(亮度)通道并直接将其用作灰度。

使用Java和ImageIO,你可以这样做:

public class GrayJPEG {
    public static void main(String[] args) throws IOException {
        try (ImageInputStream stream = ImageIO.createImageInputStream(new File(args[0]))) {
            ImageReader reader = ImageIO.getImageReaders(stream).next(); // Will throw exception if no reader available

            try {
                reader.setInput(stream);
                ImageReadParam param = reader.getDefaultReadParam();

                // The QnD way, just specify the gray type directly
                //param.setDestinationType(ImageTypeSpecifier.createFromBufferedImageType(BufferedImage.TYPE_BYTE_GRAY));

                // The very correct way, query the reader if it supports gray, and use that
                Iterator<ImageTypeSpecifier> types = reader.getImageTypes(0);
                while (types.hasNext()) {
                    ImageTypeSpecifier type = types.next();

                    if (type.getColorModel().getColorSpace().getType() == ColorSpace.TYPE_GRAY) {
                        param.setDestinationType(type);
                        break;
                    }
                }

                BufferedImage image = reader.read(0, param);

                ImageIO.write(image, "JPEG", new File(args[0] + "_gray.jpg"));

            }
            finally {
                reader.dispose();
            }
        }
    }
}