【解决opencv dll引入错误大坑】SpringBoot与OpenCV整合进行人脸特征识别

出现问题

使用SpringBoot整合OpenCV,初始化class/调用

java.lang.UnsatisfiedLinkError: org.opencv.objdetect.CascadeClassifier.CascadeClassifier_0(Ljava/lang/String;)J

快速解决

  1. 如果你使用了SpringBoot,请去掉spring-boot-devtools这个依赖项

  2. 如果你没有引入dll文件。请采用如下三种方式之一引入dll

dll引入的方式

这里的dll是opencv的动态链接库,下载地址

方法一:动态引入(推荐)

  1. 在resource下新建lib/opencv

  2. 放入opencv_javaxxx.dll,xxx取决于你的jar版本,如opencv_java455.dll

  3. 静态初始化区使用如下代码

          URL url = ClassLoader.getSystemResource("lib/opencv/opencv_java455.dll");
          System.load(url.getPath());

方法二:放入system32或者jre/bin目录

  1. 将dll放入system32或者jre/bin目录

  2. 静态初始化区使用如下代码加载,其中Core是org.opencv.core.Core

    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

方法三:指定 java.library.path

  1. 将dll放入任意位置,如文件夹F:\opencv_java\x64

  2. 使用-Djava.library.path参数启动SpringBoot(jar)项目

    java -Djava.library.path=F:\opencv_java\x64 -jar xxx
  3. (或者)如果你使用IDEA,请点如下图标注1的位置,点击【Edit Configurations..】,再在标注2处加入参数

  4. 静态初始化区使用如下代码加载,其中Core是org.opencv.core.Core

    System.loadLibrary(Core.NATIVE_LIBRARY_NAME);

System.load(param)和System.loadLibrary(param)的区别

  1. load传入dll文件的绝对路径,可以是任意路径,表示加载路径为这个参数的dll

  2. loadLibrary,传入这个dll文件的名字(不含路径和后缀),表示从环境变量中读取改名字的dll文件。

  3. System.loadLibrary(Core.NATIVE_LIBRARY_NAME);中的Core.NATIVE_LIBRARY_NAME实际上是随着这个jar包写死的,如opencv-455.jar就是会返回opencv_455这个名字。

IDEA:SpringBoot与OpenCV整合完整过程

完成一次人脸特征识别的过程

导入jar包

  1. 下载jar包,下载地址

  2. 依次点击File->Project Struture->Libraries->加号->Java,选择你的jar包路径,导入成功后可以看到最下方已经有了jar包

加载动态链接库(dll)

使用的是上方方法一,这里演示了,你可以选择任意方式

创建人脸识别器

  1. 存放级联分类器xml文件,文件在OpenCV/data/haarcascades

不同的级联分类器的区别可以参考:OpenCV中4个人脸级联分类器_LinJM-机器视觉的博客-CSDN博客

  1. 加载xml文件

    CascadeClassifier faceDetector = new CascadeClassifier("F:\\Project\\examDemo\\examDemo\\src\\main\\resources\\lib\\opencv\\haarcascade_frontalface_alt.xml");

    此处必须使用绝对路径,不能存放在jar包内,并且动态获取Jar包内的Resource下的的路径。猜测是JNI调用时需要一个能访问的xml文件路径,而不是Jar包内的文件。

识别

Mat faceImag = imread("F:\\Project\\examDemo\\examDemo\\src\\main\\resources\\images\\image.png");
MatOfRect faceDetections = new MatOfRect();
faceDetector.detectMultiScale(faceImag,faceDetections);
Rect[] rects = faceDetections.toArray();

全部代码

        // 解决awt报错问题
        System.setProperty("java.awt.headless", "false");
        System.out.println(System.getProperty("java.library.path"));
        // 加载动态库
        URL url = ClassLoader.getSystemResource("lib/opencv/opencv_java455.dll");
        System.load(url.getPath());
        Mat faceImag = imread("F:\\Project\\examDemo\\examDemo\\src\\main\\resources\\images\\image.png");
        // 人脸识别器
        CascadeClassifier faceDetector = new CascadeClassifier("F:\\Project\\examDemo\\examDemo\\src\\main\\resources\\lib\\opencv\\haarcascade_frontalface_alt.xml");
        // 在图片中检测人脸
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(faceImag,faceDetections);
        Rect[] rects = faceDetections.toArray();
        if(rects != null && rects.length >= 1){
            for (Rect rect : rects) {

                Imgproc.rectangle(faceImag,rect,Scalar.all(1));
            }
        }
        imshow("人脸检测图片",faceImag);
        waitKey();

效果

会全出人脸的位置。如下图:

参考

  1. Java调用OpenCV(含简单人脸识别和图像灰度处理的示例)_adventure.Li的博客-CSDN博客_java opencv

  2. OpenCV中4个人脸级联分类器_LinJM-机器视觉的博客-CSDN博客

  3. OpenCV学习---级联分类器(人脸检测等)_人间凑数的博客-CSDN博客

点赞

发表评论

电子邮件地址不会被公开。必填项已用 * 标注