使用OpenCV做一个人脸识别(Java)

前言

当前很多博客实现人脸识别的大部分都是调用云厂家的接口,如百度,阿里云。以及我们乐橙开放平台也支持人脸识别等人工智能服务。这些都比较简单,会接开放平台,走接口请求基本上都掌握了。缺点就是有限制,收费。

那么有没有方法自己搭建一个呢?当然有,这里采用最常见的OpenCV来做吧

一.下载并配置OpenCV

1、opencv下载
打开opencv官网https://opencv.org/releases/。下载opencv。我使用的是4.5.4版本。本地为windows.按照自己的需求进行下载。
这里推荐使用我发现的一个网页下载https://www.raoyunsoft.com/wordpress/index.php/2020/03/09/opencvdownload/

2.安装
没什么好主意的,按照步骤就可以了

二.创建一个Maven项目

pom.xml:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>face</groupId>
  <artifactId>face</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <parent>
  	<groupId>org.springframework.boot</groupId>
  	<artifactId>spring-boot-starter-parent</artifactId>
  	<version>2.0.4.RELEASE</version>
  </parent>
  <!-- opencv + javacv + ffmpeg-->
   <dependencies>
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg</artifactId>
            <version>4.1-1.4.4</version>
        </dependency>
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv</artifactId>
            <version>1.4.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/ffmpeg-platform -->
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>ffmpeg-platform</artifactId>
            <version>4.1-1.4.4</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.4</version>
        </dependency>


        <!-- 视频摄像头 -->
        <!-- https://mvnrepository.com/artifact/org.bytedeco/javacv-platform -->
        <dependency>
            <groupId>org.bytedeco</groupId>
            <artifactId>javacv-platform</artifactId>
            <version>1.4.4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.bytedeco.javacpp-presets/opencv-platform -->
        <dependency>
            <groupId>org.bytedeco.javacpp-presets</groupId>
            <artifactId>opencv-platform</artifactId>
            <version>4.0.1-1.4.4</version>
        </dependency>
   </dependencies>
</project>

接着需要配置OpenCV
第一步:
复制\opencv\build\bin中的opencv_videoio_ffmpeg454_64.dll
到\opencv\build\java\x64中
像这样:在这里插入图片描述
第二步:
在idea中配置构建路径,jar包在\opencv\build\java中
在这里插入图片描述
注意这里需要编辑一下
一定要改此项!
在这里插入图片描述
将\opencv\build\java\x64设为本机库位置

ok,那配置现在也就完成了

三.主程序

注意记得将faceDetector设为自己opencv\sources\data\haarcascades\haarcascade_frontalface_alt.xml
的位置

package face;

import org.opencv.core.*;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;
import org.opencv.videoio.VideoCapture;
import org.opencv.videoio.VideoWriter;
import org.opencv.videoio.Videoio;

import java.util.Arrays;

/**
 *
 * @Title: Opencv 图片人脸识别、实时摄像头人脸识别、视频文件人脸识别
 * @Description: OpenCV-4.1.1 测试文件
 * @date: 2019年8月19日 17:17:48
 * @version: V-1.0.0
 *
 */
public class FaceVideo {

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

    static int i=0;

    static {
        System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
        faceDetector = new CascadeClassifier("---\\openCV\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
    }

    public static void main(String[] args) {
    	// 1- 从摄像头实时人脸识别,识别成功保存图片到本地
        //getVideoFromCamera();
        // 2- 从本地视频文件中识别人脸
        getVideoFromFile();

        // 3- 本地图片人脸识别,识别成功并保存人脸图片到本地
        //face();

        // 4- 比对本地2张图的人脸相似度 (越接近1越相似)
        String basePicPath = "D:\\Documents\\Pictures\\";
        double compareHist = compare_image(basePicPath + "fc.jpg", basePicPath + "fc_1.jpg");
        System.out.println(compareHist);
        if (compareHist > 0.72) {
            System.out.println("人脸匹配");
        } else {
            System.out.println("人脸不匹配");
        }

    }




    /**
     * OpenCV-4.1.1 从摄像头实时读取
     * @return: void
     * @date: 2019年8月19日 17:20:13
     */
    public static void getVideoFromCamera() {
        //1 如果要从摄像头获取视频 则要在 VideoCapture 的构造方法写 0
        VideoCapture capture=new VideoCapture(0);
        Mat video=new Mat();
        int index=0;
        System.out.println("摄像头识别");
        if (capture.isOpened()) {
            while(i<3) {// 匹配成功3次退出
                capture.read(video);
                HighGui.imshow("实时人脸识别", getFace(video));
                index=HighGui.waitKey(100);
                if (index==27) {
                    capture.release();
                    break;
                }
            }
        }else{
            System.out.println("摄像头未开启");
        }
        try {
            capture.release();
            Thread.sleep(1000);
            System.exit(0);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return;
    }

    /**
     * OpenCV-4.1.1 从视频文件中读取
     * @return: void
     * @date: 2019年8月19日 17:20:20
     */
    public static void getVideoFromFile() {
        VideoCapture capture=new VideoCapture();
        capture.open("D:\\video\\素材\\bandicam 2022-04-09 21-59-55-196.mp4");//1 读取视频文件的路径

        if(!capture.isOpened()){
            System.out.println("读取视频文件失败!");
            return;
        }
        Mat video=new Mat();
        int index=0;
        while(capture.isOpened()) {
            capture.read(video);//2 视频文件的视频写入 Mat video 中
            HighGui.imshow("本地视频识别人脸", getFace(video));//3 显示图像
            index=HighGui.waitKey(100);//4 获取键盘输入
            if(index==27) {//5 如果是 Esc 则退出
                capture.release();
                return;
            }
        }
    }

    /**
     * OpenCV-4.1.1 人脸识别
     * @date: 2019年8月19日 17:19:36
     * @param image 待处理Mat图片(视频中的某一帧)
     * @return 处理后的图片

     */
    public static Mat getFace(Mat image) {
        // 1 读取OpenCV自带的人脸识别特征XML文件(faceDetector)
//        CascadeClassifier facebook=new CascadeClassifier("D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
        // 2  特征匹配类
        MatOfRect face = new MatOfRect();
        // 3 特征匹配
        faceDetector.detectMultiScale(image, face);
        Rect[] rects=face.toArray();
        System.out.println("匹配到 "+rects.length+" 个人脸");
        if(rects != null && rects.length >= 1) {

            // 4 为每张识别到的人脸画一个圈
            for (int i = 0; i < rects.length; i++) {
                Imgproc.rectangle(image, new Point(rects[i].x, rects[i].y), new Point(rects[i].x + rects[i].width, rects[i].y + rects[i].height), new Scalar(0, 255, 0));
                Imgproc.putText(image, "Human", new Point(rects[i].x, rects[i].y), Imgproc.FONT_HERSHEY_SCRIPT_SIMPLEX, 1.0, new Scalar(0, 255, 0), 1, Imgproc.LINE_AA, false);
                //Mat dst=image.clone();
                //Imgproc.resize(image, image, new Size(300,300));
            }
            i++;
            if(i==3) {// 获取匹配成功第10次的照片
                Imgcodecs.imwrite("D:\\Documents\\Pictures\\" + "face.png", image);
            }
        }
        return image;
    }



    /**
     * OpenCV-4.1.1 图片人脸识别
     * @return: void
     * @date: 2019年5月7日12:16:55
     */
    public static void face() {
        // 1 读取OpenCV自带的人脸识别特征XML文件
        //OpenCV 图像识别库一般位于 opencv\sources\data 下面
//        CascadeClassifier facebook=new CascadeClassifier("D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml");
        // 2 读取测试图片
        String imgPath = "D:\\Documents\\Pictures\\he.jpg";
        Mat image=Imgcodecs.imread(imgPath);
        if(image.empty()){
            System.out.println("image 内容不存在!");
            return;
        }
        // 3 特征匹配
        MatOfRect face = new MatOfRect();
        faceDetector.detectMultiScale(image, face);
        // 4 匹配 Rect 矩阵 数组
        Rect[] rects=face.toArray();
        System.out.println("匹配到 "+rects.length+" 个人脸");
        // 5 为每张识别到的人脸画一个圈
        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:\\Documents\\Pictures\\"+i+".jpg", rect.x, rect.y, rect.width, rect.height);// 进行图片裁剪
            i++;
        }
        // 6 展示图片
        HighGui.imshow("人脸识别", image);
        HighGui.waitKey(0);
    }

    /**
     * 裁剪人脸
     * @param imagePath
     * @param outFile
     * @param posX
     * @param posY
     * @param width
     * @param height
     */
    public static void imageCut(String imagePath, String outFile, int posX, int posY, int width, int height) {
        // 原始图像
        Mat image = Imgcodecs.imread(imagePath);
        // 截取的区域:参数,坐标X,坐标Y,截图宽度,截图长度
        Rect rect = new Rect(posX, posY, width, height);
        // 两句效果一样
        Mat sub = image.submat(rect); // Mat sub = new Mat(image,rect);
        Mat mat = new Mat();
        Size size = new Size(width, height);
        Imgproc.resize(sub, mat, size);// 将人脸进行截图并保存
        Imgcodecs.imwrite(outFile, mat);
        System.out.println(String.format("图片裁切成功,裁切后图片文件为: %s", outFile));

    }

    /**
     * 人脸比对
     * @param img_1
     * @param img_2
     * @return
     */
    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);

        // CORREL 相关系数
        double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);
        return res;
    }

    /**
     * 灰度化人脸
     * @param img
     * @return
     */
    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);
        // rect中人脸图片的范围
        for (Rect rect : faceDetections.toArray()) {
            Mat face = new Mat(image1, rect);
            return face;
        }
        return null;
    }

    /**
     * OpenCV-4.1.1 将摄像头拍摄的视频写入本地
     * @return: void
     * @date: 2019年8月19日 17:20:48
     */
    public static void writeVideo() {
        //1 如果要从摄像头获取视频 则要在 VideoCapture 的构造方法写 0
        VideoCapture capture=new VideoCapture(0);
        Mat video=new Mat();
        int index=0;
        Size size=new Size(capture.get(Videoio.CAP_PROP_FRAME_WIDTH),capture.get(Videoio.CAP_PROP_FRAME_HEIGHT));
        VideoWriter writer=new VideoWriter("D:/a.mp4",VideoWriter.fourcc('D', 'I', 'V', 'X'), 15.0,size, true);
        while(capture.isOpened()) {
            capture.read(video);//2 将摄像头的视频写入 Mat video 中
            writer.write(video);
            HighGui.imshow("像头获取视频", video);//3 显示图像
            index=HighGui.waitKey(100);//4 获取键盘输入
            if(index==27) {//5 如果是 Esc 则退出
                capture.release();
                writer.release();
                return;
            }
        }
    }

}

效果图:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
若是觉得这篇文章还不错的话,点一个免费的赞吧~

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
要在Java使用OpenCV实现人脸识别,需要以下几个步骤: 1.下载安装OpenCV库 首先需要下载并安装OpenCV库,可以到官方网站https://opencv.org/releases/下载适合自己环境的版本,然后按照安装指南进行安装。 2.导入OpenCV库 在Java项目中,需要使用OpenCV库的功能,需要将OpenCV库导入到项目中。具体导入方式可以查看OpenCV官方文档https://docs.opencv.org/3.4/d9/df8/tutorial_root.html。 3.载入训练好的人脸分类器 OpenCV提供了一些训练好的人脸分类器,可以用来检测人脸。可以在OpenCV库中找到这些分类器文件,然后使用Java代码将其载入。 4.读取图片或视频流 使用Java代码读取图片或视频流,可以使用OpenCV中提供的Imgcodecs类进行图片读取,也可以使用VideoCapture类进行视频流读取。 5.使用人脸分类器检测人脸 使用OpenCV中提供的CascadeClassifier类,将训练好的人脸分类器载入,并使用detectMultiScale方法在图片或视频流中检测人脸。 6.标记人脸并显示 使用Java代码标记出检测到的人脸位置,并将结果显示在图片或视频流中。 下面是一个简单的Java代码示例: ``` import org.opencv.core.Core; import org.opencv.core.Mat; import org.opencv.core.MatOfRect; import org.opencv.core.Rect; import org.opencv.core.Scalar; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.objdetect.CascadeClassifier; public class FaceDetection { public static void main(String[] args) { System.loadLibrary(Core.NATIVE_LIBRARY_NAME); // 载入人脸分类器 CascadeClassifier faceDetector = new CascadeClassifier("haarcascade_frontalface_alt.xml"); // 读取图片 Mat image = Imgcodecs.imread("test.jpg"); // 检测人脸 MatOfRect faceDetections = new MatOfRect(); faceDetector.detectMultiScale(image, faceDetections); // 标记人脸并显示 for (Rect rect : faceDetections.toArray()) { Imgproc.rectangle(image, rect.tl(), rect.br(), new Scalar(0, 255, 0), 3); } Imgcodecs.imwrite("result.jpg", image); } } ``` 在这个示例中,我们载入了一个人脸分类器文件"haarcascade_frontalface_alt.xml",然后读取了一张图片"test.jpg",使用人脸分类器检测人脸,并标记人脸位置,并将结果保存在"result.jpg"中。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Spasol

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值