package com.ktg.common.utils.face;


import com.ktg.common.config.RuoYiConfig;
import com.ktg.common.utils.StringUtils;
import com.ktg.common.vo.FaceMatchVO;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import java.util.Arrays;

/**
 * 面部对比工具
 *
 * @author ruoyi
 */
public class FaceImgMatchUtil {


    // 加载OpenCV本地库
    static {
        String prodApi = RuoYiConfig.getProd();
        String loadPath = "/guoruan/app/opencv/build/java/x64/opencv_java470.dll";
        if (StringUtils.isBlank(prodApi)) {
            loadPath = "C:/work/app/install/opencv/build/java/x64/opencv_java470.dll";
        }
        System.load(loadPath);
    }

    // 初始化人脸探测器
    private static CascadeClassifier faceDetector;

    static {
        String prodApi = RuoYiConfig.getProd();
        String faceDetectorPath = "/guoruan/app/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";
        if (StringUtils.isBlank(prodApi)) {
            faceDetectorPath = "C:/work/app/install/opencv/sources/data/haarcascades/haarcascade_frontalface_alt.xml";
        }
        faceDetector = new CascadeClassifier(faceDetectorPath);
    }

    public static void main(String[] args) {
        FaceMatchVO vo = faceRecognitionComparison("C:/work/file/11.jpg", "C:/work/file/13.jpg");
        System.out.println("对比结果：" + vo.getScore());
        if (vo.getScore() > 0.85) {
            System.out.println("人脸匹配成功1");
        } else {
            System.out.println("人脸不匹配识别1");
        }

        FaceMatchVO vo1 = faceRecognitionComparison("C:/work/file/12.jpg", "C:/work/file/13.jpg");
        System.out.println("对比结果：" + vo1.getScore());
        if (vo1.getScore() > 0.85) {
            System.out.println("人脸匹配成功2");
        } else {
            System.out.println("人脸不匹配识别2");
        }
        // 终止当前运行的 Java 虚拟机。
        System.exit(0);
    }


    /**
     * 人脸识别比对
     */
    public static FaceMatchVO faceRecognitionComparison(String image1, String image2) {
        Mat mat1 = conv_mat(image1);
        Mat mat2 = conv_mat(image2);
        Mat mat3 = new Mat();
        Mat mat4 = new Mat();
        // 颜色范围
        MatOfFloat ranges = new MatOfFloat(0f, 256f);
        // 直方图大小， 越大匹配越精确 (越慢)
        MatOfInt histSize = new MatOfInt(1000);

        Imgproc.calcHist(Arrays.asList(mat1), new MatOfInt(0), new Mat(), mat3, histSize, ranges);

        // 比较两个密集或两个稀疏直方图

        Imgproc.calcHist(Arrays.asList(mat2), new MatOfInt(0), new Mat(), mat4, histSize, ranges);
        double v = Imgproc.compareHist(mat3, mat4, Imgproc.CV_COMP_CORREL);
        if (v > 0.80) {
            return new FaceMatchVO().setContent(image2).setScore(v);
        }
        return null;
    }

    /**
     * 灰度化人脸
     */
    public static Mat conv_mat(String img) {
        // 读取图像
        Mat mat1 = Imgcodecs.imread(img);
        Mat mat2 = new Mat();
        // 灰度化:将图像从一种颜色空间转换为另一种颜色空间
        Imgproc.cvtColor(mat1, mat2, Imgproc.COLOR_BGR2GRAY);
        // 探测人脸:检测到的对象作为矩形列表返回
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(mat1, faceDetections);
        // rect中人脸图片的范围
        for (Rect rect : faceDetections.toArray()) {
            Mat face = new Mat(mat1, rect);
            return face;
        }
        return null;
    }


}
