javacv工具类

发布时间:2023年12月29日

依赖

安装完opencv后在安装目录的build\java目录下有jar包,将其依赖进项目
在这里插入图片描述

<dependency>
            <groupId>org.opencv</groupId>
            <artifactId>opencv</artifactId>
            <version>4.8.0</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/src/main/resources/lib/opencv/linux/opencv-480.jar</systemPath>
</dependency>
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import java.net.URL;
import java.util.Arrays;

public class OpenCvUtil {
    static {
        // 加载OpenCV本地库
        String sys = OpenCvUtil.getOperatingSystem();
        URL url = null;
        if (sys.equals("Windows")) {
            url = ClassLoader.getSystemResource("lib/opencv/windows/opencv_java480.dll");
            System.load(url.getPath());
        } else {
            System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        }
    }

    //    该方法不能使用相对路径,只能使用系统上的绝对路径
    static CascadeClassifier faceDetector = OpenCvUtil.getOperatingSystem().equals("Windows") ?
            new CascadeClassifier("D:\\openCv\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml")
            : new CascadeClassifier("/app/haarcascade_frontalface_alt.xml");

    public static void imageFaceDetection(String imgPath) {
        // 读取测试图片
        Mat image = Imgcodecs.imread(imgPath);
        if (image.empty()) {
            throw new RuntimeException("图片内存为空");
        }

        // 检测脸部
        MatOfRect face = new MatOfRect();
        // 检测图像中的人脸
        faceDetector.detectMultiScale(image, face);
        // 匹配Rect矩阵
        Rect[] rects = face.toArray();
        System.out.println("识别人脸个数: " + rects.length);

        // 识别图片中的所以人脸并分别保存
        int i = 1;
        for (Rect rect : face.toArray()) {
            Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0), 3);
            // 进行图片裁剪
            imageCut(imgPath, "D:\\user\\" + i + ".jpg", rect.x, rect.y, rect.width, rect.height);
            i++;
        }
        // 图片中人脸画框保存到本地
        Imgcodecs.imwrite("D:\\user\\test1.png", image);
    }

    /**
     * 裁剪人脸
     *
     * @param readPath 读取文件路径
     * @param outPath  写出文件路径
     * @param x        坐标X
     * @param y        坐标Y
     * @param width    截图宽度
     * @param height   截图长度
     */
    public static void imageCut(String readPath, String outPath, int x, int y, int width, int height) {
        // 原始图像
        Mat image = Imgcodecs.imread(readPath);
        // 截取的区域
        Rect rect = new Rect(x, y, width, height);
        // Mat sub = new Mat(image,rect);
        Mat sub = image.submat(rect);
        Mat mat = new Mat();
        Size size = new Size(width, height);
        // 人脸进行截图并保存
        Imgproc.resize(sub, mat, size);
        Imgcodecs.imwrite(outPath, mat);
    }


    /**
     * 传入图片地址人脸识别比较
     *
     * @param image1
     * @param image2
     * @return
     */
    public static double faceRecognitionComparison(String image1, String image2) {
        try {
            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(2000);

            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);

            // 比较两个密集或两个稀疏直方图
            return Imgproc.compareHist(mat3, mat4, Imgproc.CV_COMP_CORREL);
        } catch (Exception e) {
            return 0;
        }
    }

    /**
     * 传入图片字节流人脸识别比较
     *
     * @param image1
     * @param image2
     * @return
     */
    public static double faceRecognitionComparison(byte[] image1, byte[] image2) {
        try {
            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(5000);

            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);

            // 比较两个密集或两个稀疏直方图
            return Imgproc.compareHist(mat3, mat4, Imgproc.CV_COMP_CORREL);
        } catch (Exception e) {
            return 0;
        }
    }


    /**
     * 传入图片地址灰度化人脸
     *
     * @param img
     * @return
     */
    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;
    }

    /**
     * 传入图片字节流灰度化人脸
     *
     * @param img
     * @return
     */
    public static Mat conv_Mat(byte[] img) {
        // 读取图像
        Mat mat1 = byteStreamToMat(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;
    }

    public static Mat byteStreamToMat(byte[] byteStream) {
        // 将字节流转换为OpenCV的Mat对象
        MatOfByte matOfByte = new MatOfByte(byteStream);
        Mat image = Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_UNCHANGED);
        matOfByte.release();
        return image;
    }


    public static String getOperatingSystem() {
        String os = System.getProperty("os.name").toLowerCase();

        if (os.contains("win")) {
            return "Windows";
        } else if (os.contains("nix") || os.contains("nux") || os.contains("mac")) {
            return "Linux";
        } else {
            return "Unknown";
        }
    }
}

ps:可直接调用faceRecognitionComparison方法进行人脸识别校验

使用docker搭建opencv的linux运行环境可以参考下面链接的Dockerfile
https://bigxiamu.blog.csdn.net/article/details/135251651

文章来源:https://blog.csdn.net/bigxiamu/article/details/135273597
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。