我正在尝试编写一个程序,将bufferedImage作为输入,并将所有黑色关闭颜色(R <32,G <32,B <32)映射为黑色,将其他颜色映射为白色以用于OCR(OCR引擎需要BufferedImage作为输入)。有没有办法在不迭代像素的情况下做到这一点?即,我试过了
public static BufferedImage BlackAndWhite(BufferedImage image) {
ColorModel model = new BlackWhiteColorModel(DataBuffer.TYPE_INT);
WritableRaster raster = image.getRaster();
BufferedImage newImage = new BufferedImage(model, raster, false, null);
return newImage;
}
其中BlackWhiteColorModel定义为
public class BlackWhiteColorModel extends ColorModel {
public BlackWhiteColorModel(int bits) {
super(bits);
}
@Override
public int getRed(int pixel) {
int[] rgb = getRgb(pixel);
if (rgb[0] < 32 && rgb[1] < 32 && rgb[2] < 32) {
return 0;
} else {
return 255;
}
}
@Override
public int getGreen(int pixel) {
int[] rgb = getRgb(pixel);
if (rgb[0] < 32 && rgb[1] < 32 && rgb[2] < 32) {
return 0;
} else {
return 255;
}
}
@Override
public int getBlue(int pixel) {
int[] rgb = getRgb(pixel);
if (rgb[0] < 32 && rgb[1] < 32 && rgb[2] < 32) {
return 0;
} else {
return 255;
}
}
@Override
public int getAlpha(int pixel) {
return pixel;
}
private int[] getRgb(int pixel) {
int r = (pixel) & 0xFF;
int g = (pixel >> 8) & 0xFF;
int b = (pixel >> 16) & 0xFF;
int a = (pixel >> 24) & 0xFF;
return new int[]{r, g, b, a};
}
}
但是,我最终得到了isCompatibleRasterException。有人能给我一些建议吗?
(1)您没有实施合同中的一种方法:isCompatibleRaster
。这是一个过于乐观的实现,在您的问题陈述中运行良好:
@Override
public boolean isCompatibleRaster(Raster raster) {
return true;
}
(2)getRed
,getGreen
和getBlue
具有相同的代码。这是一个完整的程序,它将公共代码分解为一个名为getColor
的新方法。该程序运行没有错误:
import java.awt.*;
import java.awt.image.*;
public class BlackWhiteColorModel extends ColorModel {
public static void main(String[] args) {
BufferedImage bufferedImage = new BufferedImage(200,200,BufferedImage.TYPE_INT_RGB);
Graphics g = bufferedImage.getGraphics();
g.drawString("Hello, World", 20,20);
blackAndWhite(bufferedImage);
}
public static BufferedImage blackAndWhite(BufferedImage image) {
ColorModel model = new BlackWhiteColorModel(DataBuffer.TYPE_INT);
WritableRaster raster = image.getRaster();
BufferedImage newImage = new BufferedImage(model, raster, false, null);
return newImage;
}
public BlackWhiteColorModel(int bits) {
super(bits);
}
private int getColor(int pixel) {
int[] rgb = getRgb(pixel);
if (rgb[0] < 32 && rgb[1] < 32 && rgb[2] < 32) {
return 0;
} else {
return 255;
}
}
@Override
public int getRed(int pixel) {
return getColor(pixel);
}
@Override
public int getGreen(int pixel) {
return getColor(pixel);
}
@Override
public int getBlue(int pixel) {
return getColor(pixel);
}
@Override
public int getAlpha(int pixel) {
return pixel;
}
@Override
public boolean isCompatibleRaster(Raster raster) {
return true;
}
private int[] getRgb(int pixel) {
int r = (pixel) & 0xFF;
int g = (pixel >> 8) & 0xFF;
int b = (pixel >> 16) & 0xFF;
int a = (pixel >> 24) & 0xFF;
return new int[]{r, g, b, a};
}
}
我想你不想因为性能问题而迭代像素。如果这是真的,我强烈建议你像这样使用OpenCV:
BufferedImage image = null; //use your image here
//Convert image to OpenCv Mat
byte[] pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
Mat mat = new Mat(image.getHeight(), image.getWidth(), CvType.CV_8UC3);
mat.put(0, 0, pixels);
//do something with the Mat e.g:
Imgproc.threshold(...);
//Convert back
mat.get(0, 0, pixels);
特别是如果您进行更多图像处理,性能至少要快10倍