package com.ktg.common.utils.face;


import com.ktg.common.config.RuoYiConfig;
import com.ktg.common.utils.StringUtils;
import com.ktg.common.vo.FaceCutVO;
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 org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Collections;
import java.util.List;

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


    // 加载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 FaceMatchVO faceRecognitionComparison(MultipartFile mfile, List<FaceCutVO> list) throws IOException {
        Mat mat1 = conv_mat(mfile); // 转换为灰度图像的Mat对象
        Mat hist1 = computeHistogram(mat1); // 计算第一个图像的直方图

        // ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // 创建线程池
        // List<Future<FaceMatchVO>> futures = new ArrayList<>(); // 存储Future对象的列表

        for (FaceCutVO vo : list) { // 遍历第二个图像集合
            // futures.add(executorService.submit(() -> {
                Mat hist2 = MatChangeUtil.strToMat(vo.getMatData(), vo.getMatRows(), vo.getMatCols(), vo.getMatType());
            System.out.println("hist2--------/n" + hist2.dump());
                // Mat hist2 = computeHistogram(mat2); // 计算第二个图像的直方图
                double v = Imgproc.compareHist(hist1, hist2, Imgproc.CV_COMP_CORREL); // 比较两个直方图的相似度
                if (v > 0.80) { // 如果相似度大于0.80，认为匹配成功
                    return new FaceMatchVO().setContent(vo.getContent()).setScore(v); // 返回匹配结果
                } /*else {
                    return null; // 否则返回null
                }*/
            // }));
        }

        /*try {
            for (Future<FaceMatchVO> future : futures) { // 遍历所有Future对象
                FaceMatchVO result = future.get(); // 获取执行结果
                if (result != null) { // 如果结果不为空，说明找到了匹配的图像
                    executorService.shutdownNow(); // 立即关闭线程池
                    return result; // 返回匹配结果
                }
            }
        } catch (InterruptedException | ExecutionException e) { // 捕获异常
            e.printStackTrace(); // 打印异常信息
        } finally {
            executorService.shutdown(); // 确保线程池最终被关闭
        }*/
        return null; // 如果没有找到匹配的图像，返回null
    }

    /**
     * 灰度化人脸并返回Mat对象
     */
    public static Mat conv_mat(MultipartFile mfile) throws IOException {
        byte[] bytes = mfile.getBytes(); // 获取文件字节数组
        Mat mat1 = Imgcodecs.imdecode(new MatOfByte(bytes), Imgcodecs.IMREAD_COLOR); // 解码为彩色图像的Mat对象
        Mat mat2 = new Mat(); // 创建一个新的Mat对象用于存储灰度图像
        Imgproc.cvtColor(mat1, mat2, Imgcodecs.IMREAD_COLOR); // 将彩色图像转换为灰度图像
        MatOfRect faceDetections = new MatOfRect(); // 创建用于存储检测到的人脸区域的MatOfRect对象
        faceDetector.detectMultiScale(mat1, faceDetections); // 检测人脸区域
        for (Rect rect : faceDetections.toArray()) { // 遍历检测到的人脸区域
            return new Mat(mat1, rect); // 返回包含人脸区域的子Mat对象
        }
        return null; // 如果没有检测到人脸，返回null
    }


    /**
     * 计算直方图
     */
    private static Mat computeHistogram(Mat mat) {
        Mat hist = new Mat(); // 创建用于存储直方图的Mat对象
        MatOfFloat ranges = new MatOfFloat(0f, 256f); // 定义直方图的范围
        MatOfInt histSize = new MatOfInt(100); // 定义直方图的大小（越大越精确，但计算速度越慢）
        Imgproc.calcHist(Collections.singletonList(mat), new MatOfInt(0), new Mat(), hist, histSize, ranges); // 计算直方图
        Core.normalize(hist, hist, 0, 1, Core.NORM_MINMAX); // 归一化直方图，使其值在0到1之间
        return hist; // 返回计算好的直方图
    }
}
