Java AWT/ImageIO 提供開箱即用的圖像處理能力,無需引入 OpenCV 等重型庫。本文演示如何用 BufferedImage 實現灰度化(TYPE_BYTE_GRAY)與二值化(TYPE_BYTE_BINARY),附完整代碼與效果對比圖。
ImageIO.read(File)BufferedImage.TYPE_BYTE_GRAY 或 TYPE_BYTE_BINARYImageIO.write(image, "jpg", File)
package image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
public class ImageDemo {
// 二值化:非黑即白,適合文字識別預處理
public void binaryImage() throws IOException {
File src = new File(System.getProperty("user.dir") + "/src/2722425974762424026.jpg");
BufferedImage image = ImageIO.read(src);
int w = image.getWidth(), h = image.getHeight();
BufferedImage binary = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int rgb = image.getRGB(x, y);
binary.setRGB(x, y, rgb); // 自動按閾值二值化
}
}
ImageIO.write(binary, "jpg", new File(System.getProperty("user.dir") + "/src/2722425974762424028.jpg"));
}
// 灰度化:256 級灰階,保留細節層次
public void grayImage() throws IOException {
File src = new File(System.getProperty("user.dir") + "/src/2722425974762424026.jpg");
BufferedImage image = ImageIO.read(src);
int w = image.getWidth(), h = image.getHeight();
BufferedImage gray = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_GRAY);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int rgb = image.getRGB(x, y);
gray.setRGB(x, y, rgb); // 自動按亮度公式灰度化
}
}
ImageIO.write(gray, "jpg", new File(System.getProperty("user.dir") + "/src/2722425974762424027.jpg"));
}
public static void main(String[] args) throws IOException {
new ImageDemo().binaryImage();
new ImageDemo().grayImage();
}
}
| 常量 | 含義 | 適用場景 |
|---|---|---|
BufferedImage.TYPE_BYTE_GRAY | 8位灰度圖 (0-255) | 圖像增強、特徵提取、打印預覽 |
BufferedImage.TYPE_BYTE_BINARY | 1位二值圖 (黑/白) | OCR 預處理、條碼識別、文檔歸檔 |
BufferedImage.TYPE_INT_RGB | 標準 24 位彩色 | 通用圖像處理基礎類型 |
原圖:
灰度化:
二值化:
默認 TYPE_BYTE_BINARY 使用中值閾值(128),若需自定義閾值(如自適應 Otsu 算法),需手動像素運算:
public static BufferedImage customBinary(BufferedImage src, int threshold) {
int w = src.getWidth(), h = src.getHeight();
BufferedImage dest = new BufferedImage(w, h, BufferedImage.TYPE_BYTE_BINARY);
for (int x = 0; x < w; x++) {
for (int y = 0; y < h; y++) {
int rgb = src.getRGB(x, y);
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
int gray = (r + g + b) / 3; // 或 0.299*r + 0.587*g + 0.114*b
int binary = (gray >= threshold) ? 0xFFFFFF : 0x000000;
dest.setRGB(x, y, binary);
}
}
return dest;
}
getRGB/setRGB 速度一般,大圖建議用 getRaster()/getDataBuffer() 直接操作像素數組。BufferedImage 對象,減少 GC 壓力。Java 標準庫就能搞定基礎灰度/二值化,幾行代碼即可上手。理解
BufferedImage類型機制,是輕量級圖像處理的關鍵。