java通过接口把图片处理成透明背景,java通过接口抠图

1、图片工具类

package org.springblade.modules.api.utils;

import org.springframework.mock.web.MockMultipartFile;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Base64;

public final class FileImageUtil {
    // 自定义的背景色,可以根据红绿蓝的平均值写
    public static int color_range = 120;


    private static BufferedImage rotate(Image src, int angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size
        Rectangle rect_des = CalcRotatedSize(new Rectangle(new Dimension(
                src_width, src_height)), angel);

        BufferedImage res = null;
        res = new BufferedImage(rect_des.width, rect_des.height,
                BufferedImage.TYPE_INT_RGB);
        Graphics2D g2 = res.createGraphics();
        res = g2.getDeviceConfiguration().createCompatibleImage(rect_des.width, rect_des.height, Transparency.TRANSLUCENT);
        g2.dispose();
        g2 = res.createGraphics();
        // transform
        g2.translate((rect_des.width - src_width) / 2,
                (rect_des.height - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width / 2, src_height / 2);
        g2.setColor(new Color(255, 0, 0));
        g2.setStroke(new BasicStroke(1));
        g2.drawImage(src, null, null);
        g2.dispose();
        return res;
    }

    public static Rectangle CalcRotatedSize(Rectangle src, int angel) {
        // if angel is greater than 90 degree, we need to do some conversion
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = src.height;
                src.height = src.width;
                src.width = temp;
            }
            angel = angel % 90;
        }

        double r = Math.sqrt(src.height * src.height + src.width * src.width) / 2;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) src.height / src.width);
        double angel_dalta_height = Math.atan((double) src.width / src.height);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        int des_width = src.width + len_dalta_width * 2;
        int des_height = src.height + len_dalta_height * 2;
        return new Rectangle(new Dimension(des_width, des_height));
    }

    /**
     * 顺时针旋转
     *
     * @param base64FileStr
     * @param rotate
     * @return
     * @throws IOException
     */
    public static String rotateImage(String base64FileStr, int rotate) throws IOException {
        if (StringUtils.isEmpty(base64FileStr)) {
            return "";
        }

        Base64.Decoder decoder = Base64.getDecoder();
        // Base64解码,对字节数组字符串进行Base64解码并生成文件
        final byte[] byt = decoder.decode(base64FileStr);
        for (int i = 0, len = byt.length; i < len; ++i) {
            // 调整异常数据
            if (byt[i] < 0) {
                byt[i] += 256;
            }
        }
        InputStream input = new ByteArrayInputStream(byt);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        BufferedImage src = ImageIO.read(input);
        BufferedImage des = rotate(src, rotate);
        ImageIO.write(des, "png", out);
        final Base64.Encoder encoder = Base64.getEncoder();
        final byte[] bytes = out.toByteArray();
        return encoder.encodeToString(bytes);
    }

    public static MultipartFile koutTu(@RequestParam MultipartFile file) {
        BufferedImage image = getBufferedImage(file);
        // 高度和宽度
        int height = image.getHeight();
        int width = image.getWidth();

        // 生产背景透明和内容透明的图片
        ImageIcon imageIcon = new ImageIcon(image);
        BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
        Graphics2D g2D = (Graphics2D) bufferedImage.getGraphics(); // 获取画笔
        g2D.drawImage(imageIcon.getImage(), 0, 0, null); // 绘制Image的图片

        int alpha = 0; // 图片透明度
        // 外层遍历是Y轴的像素
        for (int y = bufferedImage.getMinY(); y < bufferedImage.getHeight(); y++) {
            // 内层遍历是X轴的像素
            for (int x = bufferedImage.getMinX(); x < bufferedImage.getWidth(); x++) {
                int rgb = bufferedImage.getRGB(x, y);
                // 对当前颜色判断是否在指定区间内
                if (colorInRange(rgb)) {
                    alpha = 0;
                } else {
                    // 设置为不透明
                    alpha = 255;
                }
                // #AARRGGBB 最前两位为透明度
                rgb = (alpha << 24) | (rgb & 0x00ffffff);
                bufferedImage.setRGB(x, y, rgb);
            }
        }
        // 绘制设置了RGB的新图片
        g2D.drawImage(bufferedImage, 0, 0, null);
        //转换类型
        MultipartFile multipartFile = fileCase(bufferedImage);
        return multipartFile;
    }

    // 判断是背景还是内容
    public static boolean colorInRange(int color) {
        int red = (color & 0xff0000) >> 16;// 获取color(RGB)中R位
        int green = (color & 0x00ff00) >> 8;// 获取color(RGB)中G位
        int blue = (color & 0x0000ff);// 获取color(RGB)中B位
        // 通过RGB三分量来判断当前颜色是否在指定的颜色区间内
        if (red >= color_range && green >= color_range && blue >= color_range) {
            return true;
        }
        return false;
    }

    public static BufferedImage getBufferedImage(@RequestParam MultipartFile file) {
        BufferedImage image = null;
        try {
            image = ImageIO.read(file.getInputStream());
        } catch (IOException e) {
            System.out.println("读取图片文件出错!" + e.getMessage());
        }
        return image;
    }

    public static MultipartFile fileCase(BufferedImage image) {
        //得到BufferedImage对象
        MultipartFile multipartFile = null;
        try {
            //创建一个ByteArrayOutputStream
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //把BufferedImage写入ByteArrayOutputStream
            ImageIO.write(image, "png", os);
            //ByteArrayOutputStream转成InputStream
            InputStream input = new ByteArrayInputStream(os.toByteArray());
            //InputStream转成MultipartFile
            multipartFile = new MockMultipartFile("file", "file.png", "text/plain", input);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return multipartFile;

    }

}

2、接口

/**
	 * 抠图
	 *
	 * @param file 抠图
	 * @return LocalFile
	 */
	@PostMapping("kouTu")
	public R<Kv> kouTu(@RequestParam MultipartFile file) {
		//调用抠图方法,然后自己再进行别的操作
		MultipartFile multipartFile = FileImageUtil.koutTu(file);
		//下面的方法,是框架里上传文件的方法,没有该框架可以自己写,返回的是图片路径
		/**LocalFile localFile = getFile(multipartFile);
		localFile.transfer();
		localFile.setUploadVirtualPath(localFile.getUploadVirtualPath().replace("//", "/"));
		//拼接url
		String url = localFile.getDomain() + localFile.getUploadVirtualPath();
		Kv kv = Kv.create().set("url", url);*/
		return R.data(kv);
	}
  • 8
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 本身并没有提供图像抠图的相关功能,需要借助第三方库或者自己实现算法来实现图像抠图。 一种常见的图像抠图方法是基于 ACRush 的 GrabCut 算法,通过手动标记前景和背景区域,算法能够根据这些标记自动分割图像。 Java 中可以使用 OpenCV 提供的 Java 接口来实现 GrabCut 算法。具体步骤如下: 1. 加载需要抠图图片。 2. 创建一个和图片大小相同的掩码,用来标记前景和背景区域(0 表示背景,1 表示前景,2 表示未确定区域)。 3. 手动使用鼠标在图片上标记前景和背景区域,将标记信息保存到掩码中。 4. 调用 OpenCV 提供的 GrabCut 方法,输入原始图片和掩码,得到分割结果。 5. 根据分割结果,将前景区域保留,其他区域设置为透明,输出抠图结果。 以下是示例代码: ``` import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.highgui.HighGui; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.photo.Photo; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; public class ImageCut { static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); } private static final Scalar RECT_COLOR = new Scalar(0, 255, 0); private static final Scalar BG_COLOR = new Scalar(0, 0, 255); private static final Scalar FG_COLOR = new Scalar(255, 0, 0); private static Point startPoint = new Point(0, 0); private static Point endPoint = new Point(0, 0); private static boolean isDrawing = false; public static void main(String[] args) { Mat img = Imgcodecs.imread("input.jpg"); Mat mask = new Mat(); Mat bgdModel = new Mat(); Mat fgdModel = new Mat(); Mat result = new Mat(); Imgproc.cvtColor(img, img, Imgproc.COLOR_BGR2RGB); grabCut(img, mask, bgdModel, fgdModel, result, 5); showResult(img, result); Imgcodecs.imwrite("output.png", result); } private static void grabCut(Mat img, Mat mask, Mat bgdModel, Mat fgdModel, Mat result, int iterCount) { Mat bgd = new Mat(); Mat fgd = new Mat(); Imgproc.cvtColor(img, img, Imgproc.COLOR_RGB2BGR); Rect rect = newRect(img.width(), img.height()); Imgproc.grabCut(img, mask, rect, bgdModel, fgdModel, iterCount, Imgproc.GC_INIT_WITH_RECT); Core.compare(mask, new Scalar(Imgproc.GC_PR_FGD), bgd, Core.CMP_EQ); Core.compare(mask, new Scalar(Imgproc.GC_FGD), fgd, Core.CMP_EQ); Mat bgModel = new Mat(), fgModel = new Mat(); Photo.estimateNewBackgroundModel(img, bgd, mask, bgModel); Imgproc.grabCut(img, mask, rect, bgModel, fgModel, iterCount, Imgproc.GC_INIT_WITH_MASK); Core.compare(mask, new Scalar(Imgproc.GC_PR_FGD), bgd, Core.CMP_EQ); Core.compare(mask, new Scalar(Imgproc.GC_FGD), fgd, Core.CMP_EQ); result.setTo(new Scalar(0, 0, 0, 0)); img.copyTo(result, fgd); } private static Rect newRect(int w, int h) { int x = w * 2 / 5; int y = h * 2 / 5; int w1 = w * 4 / 5; int h1 = h * 4 / 5; return new Rect(x, y, w1, h1); } private static void showResult(Mat img, Mat result) { HighGui.imshow("Input Image", img); HighGui.setMouseCallback("Input Image", new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { switch (e.getButton()) { case MouseEvent.BUTTON1: if (!isDrawing) { startPoint = getPoint(e); } else { endPoint = getPoint(e); drawRect(img, result); } isDrawing = !isDrawing; break; case MouseEvent.BUTTON3: splitImage(img, result); break; default: break; } } }); HighGui.imshow("GrabCut", result); HighGui.waitKey(); } private static Point getPoint(MouseEvent e) { return new Point(e.getX(), e.getY()); } private static void drawRect(Mat img, Mat result) { Rect rect = new Rect(startPoint, endPoint); Imgproc.rectangle(img, rect.tl(), rect.br(), RECT_COLOR, 2, Imgproc.LINE_AA, 0); Rect sub = new Rect(rect.x, rect.y, rect.width, rect.height); Core.subtract(new Scalar(1.0), new Mat(result, sub), new Mat(result, sub)); result.setTo(FG_COLOR, new Mat(result, sub)); HighGui.imshow("Input Image", img); } private static void splitImage(Mat img, Mat result) { for (int i = 0; i < result.rows(); i++) { for (int j = 0; j < result.cols(); j++) { if (result.get(i, j)[0] == Imgproc.GC_BGD || result.get(i, j)[0] == Imgproc.GC_PR_BGD) { result.put(i, j, new double[]{0, 0, 0, 0}); } } } Imgproc.cvtColor(result, result, Imgproc.COLOR_RGBA2RGB); HighGui.imshow("Input Image", img); HighGui.imshow("GrabCut", result); } } ``` 运行结果如下: ![](https://img-blog.csdnimg.cn/2021100601182538.png)

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值