2025/06/06日日志 Java使用OpenCV实现人脸识别与人脸比对
Java使用OpenCV实现人脸识别与人脸比对
1. OpenCV概述
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,提供了丰富的图像处理和计算机视觉算法。它支持多种编程语言,包括C++、Python和Java,并广泛应用于图像识别、目标跟踪、视频分析等领域。
2. 安装OpenCV
2.1 下载OpenCV
OpenCV的最新版本可以从其官网下载。本文使用的是4.7.0版本。下载完成后,解压到本地目录。
- 下载地址:OpenCV Releases
- 安装目录结构:
- build:基于Windows的构建文件。
- sources:源码文件。
 
进入build/java目录,可以看到以下文件:
- opencv-470.jar:Java操作OpenCV的程序包。
- x64或- x86目录:包含对应的- .dll文件(Windows系统)或- .so文件(Linux系统)。
2.2 准备文件
为了使用OpenCV进行人脸识别,需要以下文件:
- 特征分类器文件:haarcascade_frontalface_alt.xml,用于人脸检测。- Windows路径:opencv\build\etc\haarcascades
- Linux路径:/usr/local/share/opencv4/haarcascades
 
- Windows路径:
- Java库文件:opencv-470.jar。- Windows路径:{opencv安装目录}\opencv\build\java
- Linux路径:/usr/local/share/java/opencv4
 
- Windows路径:
- 动态链接库文件:
- Windows:opencv_java470.dll
- Linux:libopencv_java470.so
 
- Windows:
3. 代码实现
3.1 添加依赖
在Maven项目中,需要在pom.xml文件中添加OpenCV的依赖。以下是三种可选的依赖配置:
<!-- 方式1 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>opencv</artifactId>
    <version>4.7.0-1.5.9</version>
</dependency>
<!-- 方式2 -->
<dependency>
    <groupId>org.bytedeco</groupId>
    <artifactId>javacv-platform</artifactId>
    <version>1.5.9</version>
</dependency>
<!-- 方式3 -->
<dependency>
    <groupId>org.openpnp</groupId>
    <artifactId>opencv</artifactId>
    <version>4.7.0-0</version>
</dependency>
根据实际需求选择合适的依赖。实验表明,javacv-platform依赖的打包文件最大(约929.64MB),而org.openpnp.opencv依赖的打包文件最小(几乎为0MB)。
3.2 编写代码
以下是实现人脸识别和比对的完整代码示例:
package com.testpro.test.opencv;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import java.util.Arrays;
public class FaceCompare {
    // 初始化人脸探测器
    static CascadeClassifier faceDetector;
    private static final String PATH_PREFIX = "C:\\Users\\dev\\Desktop\\";
    static int i = 0;
    static {
        // 判断系统类型并加载动态库
        String os = System.getProperty("os.name");
        if (os != null && os.toLowerCase().startsWith("windows")) {
            // Windows系统
            System.load("D:\\opencv\\opencv\\build\\java\\x64\\opencv_java470.dll");
        } else if (os != null && os.toLowerCase().startsWith("linux")) {
            // Linux系统
            System.load("/opt/face/libopencv_java440.so");
        }
        // 加载特征分类器文件
        String property = "D:\\opencv\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_alt.xml";
        faceDetector = new CascadeClassifier(property);
    }
    public static void main(String[] args) {
        // 比较两张图片的人脸相似度
        String str1 = PATH_PREFIX + "3-1.jpg";
        String str2 = PATH_PREFIX + "3-2.jpg";
        long start = System.currentTimeMillis();
        double compareHist = compare_image(str1, str2);
        System.out.println("time:" + (System.currentTimeMillis() - start));
        System.out.println(compareHist);
        if (compareHist > 0.6) {
            System.out.println("人脸匹配");
        } else {
            System.out.println("人脸不匹配");
        }
    }
    // 灰度化人脸并提取人脸区域
    public static Mat conv_Mat(String img) {
        Mat image0 = Imgcodecs.imread(img);
        Mat image1 = new Mat();
        Imgproc.cvtColor(image0, image1, Imgproc.COLOR_BGR2GRAY);
        MatOfRect faceDetections = new MatOfRect();
        faceDetector.detectMultiScale(image1, faceDetections);
        for (Rect rect : faceDetections.toArray()) {
            Mat face = new Mat(image1, rect);
            return face;
        }
        return null;
    }
    // 比较两张图片的人脸相似度
    public static double compare_image(String img_1, String img_2) {
        Mat mat_1 = conv_Mat(img_1);
        Mat mat_2 = conv_Mat(img_2);
        Mat hist_1 = new Mat();
        Mat hist_2 = new Mat();
        MatOfFloat ranges = new MatOfFloat(0f, 256f);
        MatOfInt histSize = new MatOfInt(1000);
        Imgproc.calcHist(Arrays.asList(mat_1), new MatOfInt(0), new Mat(), hist_1, histSize, ranges);
        Imgproc.calcHist(Arrays.asList(mat_2), new MatOfInt(0), new Mat(), hist_2, histSize, ranges);
        double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);
        return res;
    }
}
4. 效果展示
运行上述代码后,程序会输出两张图片的人脸相似度。如果相似度大于0.6,则认为人脸匹配;否则不匹配。以下是运行效果的示例:

5. 扩展功能
除了人脸比对,还可以实现以下功能:
- 从摄像头实时人脸识别:通过VideoCapture类获取摄像头视频流,并实时识别人脸。
- 从本地视频文件中识别人脸:读取本地视频文件并识别人脸。
- 本地图片人脸识别:读取本地图片并识别人脸,同时保存人脸图片到本地。
以下是实现这些功能的代码片段:
// 从摄像头实时人脸识别
public static void getVideoFromCamera() {
    VideoCapture capture = new VideoCapture(0);
    Mat video = new Mat();
    while (i < 3) {
        capture.read(video);
        HighGui.imshow("实时人脸识别", getFace(video));
        if (HighGui.waitKey(100) == 27) {
            break;
        }
    }
    capture.release();
}
// 从本地视频文件中识别人脸
public static void getVideoFromFile() {
    VideoCapture capture = new VideoCapture(PATH_PREFIX + "yimi.mp4");
    Mat video = new Mat();
    while (capture.isOpened()) {
        capture.read(video);
        HighGui.imshow("本地视频识别人脸", getFace(video));
        if (HighGui.waitKey(100) == 27) {
            break;
        }
    }
    capture.release();
}
// 本地图片人脸识别
public static void face(String filename) {
    Mat image = Imgcodecs.imread(PATH_PREFIX + filename);
    MatOfRect face = new MatOfRect();
    faceDetector.detectMultiScale(image, face);
    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);
        Imgcodecs.imwrite(PATH_PREFIX + "face.png", image);
    }
    HighGui.imshow("人脸识别", image);
    HighGui.waitKey(0);
}
---整理转载,方便使用

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号