shenghua/src/main/java/com/shenghua/utils/EliminateImageUtil.java

311 lines
11 KiB
Java
Raw Normal View History

2025-06-18 11:04:49 +08:00
package com.shenghua.utils;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.util.*;
import java.util.List;
public class EliminateImageUtil {
/**
* 坐标嘞
*/
private static class Coordinate {
private int x;
private int y;
public Coordinate(int x, int y) {
this.x = x;
this.y = y;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Coordinate that = (Coordinate) o;
return x == that.x &&
y == that.y;
}
@Override
public int hashCode() {
return Objects.hash(x, y);
}
}
private static class CoordinateWithCenter extends Coordinate implements Comparable<CoordinateWithCenter> {
private Coordinate center;
private int distance;
public int getDistance() {
return distance;
}
public void setDistance(int distance) {
this.distance = distance;
}
public CoordinateWithCenter(int x, int y) {
super(x,y);
this.center = new Coordinate(0,0);
}
public CoordinateWithCenter(int x, int y,Coordinate center) {
super(x,y);
this.center = center;
this.distance = Math.abs(this.getX()-center.getX())+Math.abs(this.getY()-center.getY());
}
@Override
public int compareTo(CoordinateWithCenter o) {
//负整数是小于
//0为等于
return Integer.compare(o.distance, this.distance); //正整数是大于
}
}
private static int RANGE = 5;
private static int WEIGHT = 1;
public static String imageEliminate(String primaryBase64,String eraseBase64){
BufferedImage bufferedImage = ImageUtil.bufferedImage(primaryBase64);
BufferedImage bufferedMask = ImageUtil.bufferedImage(eraseBase64);
/*获取涂抹中心区域*/
Coordinate wipeCenter = getWipeCenter(bufferedMask);
/* 被涂抹的坐标,需要处理 */
List<CoordinateWithCenter> coordinateWithCenters = getWipeCoordinate(bufferedMask, wipeCenter);
System.out.println("大小:"+bufferedImage.getWidth() + "x" + bufferedImage.getHeight());
//平均颜色
Color colorAvg = getBorderAvgColor(bufferedImage, bufferedMask);
//Color colorAvg = getMostColor(bufferedImage,bufferedMask);
//已处理的坐标
Set<Coordinate> hasDoneSet = new HashSet<>();
for (CoordinateWithCenter c : coordinateWithCenters) {
/* 获取像素点周围平均像素点 */
Color color = getAvgColor(bufferedImage, bufferedMask, c.getX(), c.getY(),colorAvg,hasDoneSet);
bufferedImage.setRGB(c.getX(), c.getY(), color.getRGB());
Coordinate coordinate = new Coordinate(c.getX(), c.getY());
hasDoneSet.add(coordinate);
}
return ImageUtil.imageToBase64(bufferedImage);
}
private static List<CoordinateWithCenter> getWipeCoordinate(BufferedImage bufferedMask, Coordinate wipeCenter) {
List<CoordinateWithCenter> list = new ArrayList<>();
int height = bufferedMask.getHeight();
int width = bufferedMask.getWidth();
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
if (bufferedMask.getRGB(i, j) != -1) {
list.add(new CoordinateWithCenter(i, j, wipeCenter));
}
}
}
Collections.sort(list);
return list;
}
/***
*获取周围的像素点的平均像素
* @param bufferedImage
* @param bufferedMask
* @param x 像素点坐标x
* @param y 像素点坐标y
* @param colorAvg 填充颜色
* @return
*/
private static Color getAvgColor(BufferedImage bufferedImage, BufferedImage bufferedMask, int x, int y, Color colorAvg,Set<Coordinate> hasDoneSet) {
int count = 0;
int aRed = 0, aBlue = 0, aGreen = 0;
for (int a = x - RANGE; a < x + RANGE; a++) {
for (int b = y - RANGE; b < y + RANGE; b++) {
//越界
if (a <= 0 || a > (bufferedImage.getWidth() - 1)
|| b < 0 || b > (bufferedImage.getHeight() - 1)
|| (a == x && b == y)) {
continue;
}
//没涂抹的区域,或者已经处理过
if (bufferedMask.getRGB(a, b) == -1 ||hasDoneSet.contains(new Coordinate(a, b))) {
int ragb = bufferedImage.getRGB(a, b);
Color color = new Color(ragb, true);
int blue = color.getBlue();
int red = color.getRed();
int green = color.getGreen();
aRed = aRed + red * WEIGHT;
aBlue = aBlue + blue * WEIGHT;
aGreen = aGreen + green * WEIGHT;
count = count + WEIGHT;
}
}
}
if (count == 0) {
return colorAvg;
}
return new Color(aRed / count, aGreen / count, aBlue / count);
}
/***
* 获取掩码涂抹的中心位置
* @param bufferedMask 掩码图
* @return 返回中心坐标
*/
private static Coordinate getWipeCenter(BufferedImage bufferedMask) {
int width = bufferedMask.getWidth();
int height = bufferedMask.getHeight();
int top = height - 1, bottom = 0, left = height - 1, right = 0;
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
if (bufferedMask.getRGB(i, j) != -1) {
right = Math.max(right, i);
left = Math.min(left, i);
bottom = Math.max(bottom, j);
top = Math.min(top, j);
}
}
}
return new Coordinate((left + right) / 2, (top + bottom) / 2);
}
/***
* 获取掩码未涂抹的平均颜色,如果全部涂抹返回整个图的平均颜色,用于填充涂抹区域
* @param bufferedImage 原图
* @param bufferedMask 掩码图
* @return 返回平均颜色
*/
private static Color getAllAvgColor(BufferedImage bufferedImage, BufferedImage bufferedMask) {
int aRed = 0, aBlue = 0, aGreen = 0, count = 0, bRed = 0, bBlue = 0, bGreen = 0;
int width = bufferedMask.getWidth();
int height = bufferedMask.getHeight();
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int ragb = bufferedImage.getRGB(i, j);
Color color = new Color(ragb, true);
if (bufferedMask.getRGB(i, j) == -1) {//未被涂抹区域
aRed = aRed + color.getRed();
aBlue = aBlue + color.getBlue();
aGreen = aGreen + color.getGreen();
count++;
}
bRed = bRed + color.getRed();
bBlue = bBlue + color.getBlue();
bGreen = bGreen + color.getGreen();
}
}
//全部涂抹
if (count == 0) {
count = width*height;
return new Color(bRed / count, bGreen / count, bBlue / count);
} else {
return new Color(aRed / count, aGreen / count, aBlue / count);
}
}
/***
* 获取边界平均颜色
* @param bufferedImage
* @param bufferedMask
* @return
*/
private static Color getBorderAvgColor(BufferedImage bufferedImage, BufferedImage bufferedMask) {
int aRed = 0, aBlue = 0, aGreen = 0, count = 0, bRed = 0, bBlue = 0, bGreen = 0;
Set<Coordinate> coordinates = new HashSet<>();
int width = bufferedMask.getWidth();
int height = bufferedMask.getHeight();
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
int ragb = bufferedImage.getRGB(i, j);
Color color = new Color(ragb, true);
if (bufferedMask.getRGB(i,j)==-1){//没被涂抹
for (int a = i - 1; a < i + 1; a++) {
for (int b = j - 1; b < j + 1; b++) {
//越界
if (a <= 0 || a > (bufferedImage.getWidth() - 1)
|| b < 0 || b > (bufferedImage.getHeight() - 1)
|| (a == i && b == j)) {
continue;
}
if (bufferedMask.getRGB(a,b)!=-1) {//是边界点
if (coordinates.add(new Coordinate(i,j))) {
aRed = aRed + color.getRed();
aBlue = aBlue + color.getBlue();
aGreen = aGreen + color.getGreen();
count++;
break;
}
}
}
}
}
bRed = bRed + color.getRed();
bBlue = bBlue + color.getBlue();
bGreen = bGreen + color.getGreen();
}
}
//全部涂抹
if (coordinates.size() == 0) {//全部涂抹,取平均色
count = width*height;
return new Color(bRed / count, bGreen / count, bBlue / count);
} else {
return new Color(aRed / count, aGreen / count, aBlue / count);
}
}
/***
* 获取颜色最多的
* @param bufferedImage 原图
* @param bufferedMask 掩码图
* @return 返回最多的颜色
*/
private static Color getMostColor(BufferedImage bufferedImage, BufferedImage bufferedMask) {
int countArgb = 0, retArgb = 0;
int width = bufferedMask.getWidth();
int height = bufferedMask.getHeight();
HashMap<Integer, Integer> map = new HashMap();
for (int j = 0; j < height; j++) {
for (int i = 0; i < width; i++) {
if (bufferedMask.getRGB(i, j) == -1) {//未被涂抹区域
int ragb = bufferedImage.getRGB(i, j);
map.put(ragb, map.get(ragb) == null ? 0 : map.get(ragb) + 1);
}
}
}
for (Integer key : map.keySet()) {
if (map.get(key) > countArgb) {
countArgb = map.get(key);
retArgb = key;
}
}
return new Color(retArgb);
}
}