一个亲戚让我帮他把照片里的红色印章抠出来,,,记录下处理过程,代码如下,可直接用:
public static void signatureProcess(String sourceImagePath, String targetImagePath) {
Graphics2D graphics2D = null;
try {
File imageFile = new File(sourceImagePath);
BufferedImage sourceBufferIamge = ImageIO.read(imageFile);
//新图大小与原图保持一致
int targetImageWidth = sourceBufferIamge.getWidth();
int targetImageHeight = sourceBufferIamge.getHeight();
BufferedImage targetBufferImage = new BufferedImage(targetImageWidth, targetImageHeight, BufferedImage.TYPE_4BYTE_ABGR);
graphics2D = targetBufferImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
int targetW = targetBufferImage.getWidth();
int targetH = targetBufferImage.getHeight();
int targetMinX = targetBufferImage.getMinX();
int targetMinY = targetBufferImage.getMinY();
for (int i = targetMinX; i < targetW; i++) {
for (int j = targetMinY; j < targetH; j++) {
// 得到原图像素(i,j)上的RGB值
int pixel = sourceBufferIamge.getRGB(i, j);
Color color = new Color(pixel);
float[] hsbvals=new float[3];
float[] floats = Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsbvals);
int red = (pixel >> 16) & 0xFF;
// 判断是否为红色印章
if (red > 200 && colorInRange(floats)) { //双重判断,精细一点 可以根据需要调整阈值
targetBufferImage.setRGB(i, j, pixel);
} else {
// 不是红色,设置为透明
targetBufferImage.setRGB(i, j, 0x00000000);
}
}
}
// 保存到新文件
FileOutputStream ops = new FileOutputStream(new File(targetImagePath));
ImageIO.write(targetBufferImage, "png", ops);
ops.flush();
ops.close();
}
catch (Exception e) {
e.printStackTrace();
}
finally {
if (graphics2D != null) {
graphics2D.dispose();
}
}
}
private static Boolean colorInRange( float[] floats){
if (0.90< floats[0]) {
return true;
}
return false;
}
运行效果(章名打了马赛克),左变为抠出的章,右边为原图,如果抠图效果不好,调整代码判断阈值,最好选清晰的色差大的抠图: