Java analiza la imagen para obtener el mapa de contorno de la imagen

efecto:

Necesito hacer una foto para reemplazar el color de fondo, por lo que la primera parte averigua primero las coordenadas del contorno, primero mira el efecto: uso líneas verdes para describir el borde:

El siguiente paso es sacar el retrato, el contenido del código es el siguiente:

package com.zjxf.test;

import com.google.common.collect.Lists;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.IntStream;

/**
 * created with IntelliJ IDEA
 *
 * @author: create by limu
 * Date: 2020/11/19
 * Time:14:20
 */
public class PictureHandleUtils {

    public static final Integer intensityValue = 30;    //处理图片的阀值

    public static final Map<Integer, List<Integer>> xLineMap = new HashMap<>();  //轮廓线坐标
    public static final Map<Integer, List<Integer>> yLineMap = new HashMap<>();  //轮廓线坐标

    private static int width = 0;
    private static int height = 0;
    private static int minX = 0;
    private static int minY = 0;

    public static void main(String[] args) throws Exception {

        drawOutlinePic(calculationPic("C:\\Users\\18701\\Desktop\\img\\2.jpg"));
    }

    /**
     * 计算图片轮廓
     *
     * @param filePath 文件地址
     * @throws IOException 文件流操作异常
     */
    public static BufferedImage calculationPic(String filePath) throws IOException {
        File imageFile = new File(filePath);
        BufferedImage bufferedImage = ImageIO.read(imageFile);

        width = bufferedImage.getWidth();
        height = bufferedImage.getHeight();
        minX = bufferedImage.getMinX();
        minY = bufferedImage.getMinY();

        IntStream.range(minX, width).boxed().forEach(item -> IntStream.range(minY, height).boxed().forEach(itemJ -> {
            int rgb = bufferedImage.getRGB(item, itemJ);

            if (item != minX && itemJ != minY && item != width - 1 && itemJ != height - 1) {
                int rgb1 = bufferedImage.getRGB(item + 1, itemJ);
                int rgb2 = bufferedImage.getRGB(item - 1, itemJ);
                int rgb3 = bufferedImage.getRGB(item, itemJ + 1);
                int rgb4 = bufferedImage.getRGB(item, itemJ - 1);

                if (comparePixel(rgb, rgb1, rgb2, rgb3, rgb4)) {
                    addXLineMap(item, itemJ);
                    addYLineMap(itemJ, item);
                }
            } else {
                int rgb1 = 0;
                int rgb2 = 0;
                int rgb3 = 0;

                if (item == 0 && itemJ != 0 && itemJ != height - 1) {
                    rgb1 = bufferedImage.getRGB(item + 1, itemJ);
                    rgb2 = bufferedImage.getRGB(item, itemJ + 1);
                    rgb3 = bufferedImage.getRGB(item, itemJ - 1);
                }

                if (item == width - 1 && itemJ != 0 && itemJ != height - 1) {
                    rgb1 = bufferedImage.getRGB(item - 1, itemJ);
                    rgb2 = bufferedImage.getRGB(item, itemJ + 1);
                    rgb3 = bufferedImage.getRGB(item, itemJ - 1);
                }

                if (itemJ == 0 && item != 0 && item != width - 1) {
                    rgb1 = bufferedImage.getRGB(item + 1, itemJ);
                    rgb2 = bufferedImage.getRGB(item - 1, itemJ);
                    rgb3 = bufferedImage.getRGB(item, itemJ + 1);
                }

                if (itemJ == height - 1 && item != 0 && item != width - 1) {
                    rgb1 = bufferedImage.getRGB(item + 1, itemJ);
                    rgb2 = bufferedImage.getRGB(item - 1, itemJ);
                    rgb3 = bufferedImage.getRGB(item, itemJ - 1);
                }

                if (rgb1 != 0 && rgb2 != 0 && rgb3 != 0) {
                    if (comparePixel(rgb, rgb1, rgb2, rgb3)) {
                        addXLineMap(item, itemJ);
                        addYLineMap(itemJ, item);
                    }
                }

            }
        }));
        List<Integer> lineList = xLineMap.getOrDefault(0, Lists.newArrayList());

        List<Integer> yList = xLineMap.getOrDefault(width - 1, Lists.newArrayList());
        IntStream.range(Collections.min(yList), height - 1).boxed().forEach(item -> addXLineMap(width - 1, item));

        if (lineList.size() != 0) {
            IntStream.range(Collections.min(lineList), height - 1).boxed().forEach(itemJ -> addYLineMap(0, itemJ));
            lineList.forEach(item -> addYLineMap(item, 0));
        }

        return bufferedImage;
    }

    /**
     * 绘制轮廓
     */
    public static void drawOutlinePic(BufferedImage bufferedImage) throws Exception {
        //预处理图片边框
        xLineMap.forEach((key, value) -> value.forEach(itemJ -> {
            List<Integer> defaultList = yLineMap.getOrDefault(itemJ, Lists.newArrayList());
            if (defaultList.size() != 0) {
                Integer max = Collections.max(defaultList);
                Integer min = Collections.min(defaultList);
                    bufferedImage.setRGB(key, itemJ, 65281);
            }
        }));

        calculationContinuousPoint(bufferedImage);
        buildFile(bufferedImage, "zh.jpg");
    }


    /**
     * 添加到间隔线map里面
     *
     * @param item  x
     * @param itemJ y
     */
    public static void addXLineMap(int item, int itemJ) {
        List<Integer> itemJList = xLineMap.getOrDefault(item, Lists.newArrayList());
        itemJList.add(itemJ);
        xLineMap.put(item, itemJList);
    }

    /**
     * 添加到间隔线map里面
     *
     * @param item  x
     * @param itemJ y
     */
    public static void addYLineMap(int itemJ, int item) {
        List<Integer> itemList = yLineMap.getOrDefault(itemJ, Lists.newArrayList());
        itemList.add(item);
        yLineMap.put(itemJ, itemList);
    }

    /**
     * 构建生成文件
     *
     * @param bufferedImage 文件包装信息
     * @param fileName      文件名称
     * @throws IOException 文件流处理异常信息
     */
    public static void buildFile(BufferedImage bufferedImage, String fileName) throws IOException {
        FileOutputStream ops = new FileOutputStream(new File("C:\\Users\\18701\\Desktop\\img\\new_1_" + fileName));
        ImageIO.write(bufferedImage, "jpg", ops);
        ops.flush();
        ops.close();
    }

    /**
     * 计算阻像素点连续性
     * 解释:
     * 1:假设 如果像素坐标出现无法连续的情况,自动补全轮廓的连续点坐标;
     *
     * @param bufferedImage 像素点连续
     * @throws Exception 流信息异常
     */
    public static void calculationContinuousPoint(BufferedImage bufferedImage) throws Exception {
        //从坐标x为0开始
        Integer integer = xLineMap.getOrDefault(0, Lists.newArrayList()).stream().findFirst().orElse(0);
        IntStream.range(minX, width).boxed().forEach(item -> IntStream.range(minY, height).boxed().forEach(itemJ -> {
            Boolean aBoolean = CoordinateUtils.upperPixed(xLineMap, item, itemJ);
            if (!aBoolean){
                System.out.println("有节点");
            }else{
                System.out.println("无节点");
            }
        }));
    }


    /**
     * 判断色值是否超过设定的阀值
     *
     * @param rgb    目标色值
     * @param rgbArr 相邻色值数组
     * @return boolean
     */
    public static boolean comparePixel(int rgb, int... rgbArr) {
        int[] rgbArray = handleColorValue(rgb);
        return Arrays.stream(rgbArr).mapToObj(PictureHandleUtils::handleColorValue).anyMatch(item -> compareArr(rgbArray, item));
    }

    /**
     * 比较rgb的值得大小
     *
     * @param aArr 目标色值a
     * @param bArr 目标色值b
     * @return boolean
     */
    public static boolean compareArr(int[] aArr, int[] bArr) {
        int i1 = aArr[0];
        int i2 = aArr[1];
        int i3 = aArr[2];

        int j1 = bArr[0];
        int j2 = bArr[1];
        int j3 = bArr[2];

        return i1 - j1 >= intensityValue || i2 - j2 >= intensityValue || i3 - j3 >= intensityValue;
    }


    /**
     * 处理颜色色值
     *
     * @param rgb 颜色十进制
     * @return int[]
     */
    public static int[] handleColorValue(int rgb) {
        int[] rgbValue = new int[3];
        rgbValue[0] = (rgb & 0xff0000) >> 16;
        rgbValue[1] = (rgb & 0xff00) >> 8;
        rgbValue[2] = (rgb & 0xff);
        return rgbValue;
    }

}

El siguiente paso es extraer la cabeza de la persona, y mañana se escribirá el siguiente.

Supongo que te gusta

Origin blog.csdn.net/qq_38821574/article/details/109784883
Recomendado
Clasificación