无法在 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
)。通过将 i
和 j
初始化为 0
从 0 开始迭代,您的代码将按预期工作。
为了获得更好的性能,您还想更改循环的顺序。由于 BufferedImage
逐行存储为连续数组,如果在内循环中遍历 x 轴(行),您将更好地利用 CPU 缓存。
旁注:我还建议将 i
和 j
重命名为 x
和 y
以提高可读性。
最后,您通过平均颜色将 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();
}
}
}
}
我在获取 .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
)。通过将 i
和 j
初始化为 0
从 0 开始迭代,您的代码将按预期工作。
为了获得更好的性能,您还想更改循环的顺序。由于 BufferedImage
逐行存储为连续数组,如果在内循环中遍历 x 轴(行),您将更好地利用 CPU 缓存。
旁注:我还建议将 i
和 j
重命名为 x
和 y
以提高可读性。
最后,您通过平均颜色将 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();
}
}
}
}