Java + opencv 实现人脸识别,图片人脸识别、视频人脸识别、摄像头实时人脸识别

Java + opencv 实现人脸识别,图片人脸识别、视频人脸识别、摄像头实时人脸识别opencv人脸识别

大家好,又见面了,我是你们的朋友全栈君。

搭建环境

opencv官网下载windows安装包 https://opencv.org/releases/
选择最新版4.1.1 下载完成后是一个opencv-4.1.1-vc14_vc15.exe,双击安装。
在这里插入图片描述
重要: 把安装路径D:\Sofeware\opencv\build\bin下面的两个文件复制到 D:\Sofeware\opencv\build\java\x64 (为了支持读取视频流)
在这里插入图片描述

集成到IDEA中

打开project structure –> modules –>dependencies 引入D:\Sofeware\opencv\build\java 下的opencv-411.jar包,然后编辑这个包加入D:\Sofeware\opencv\build\x64 路径里的资源

在这里插入图片描述
在这里插入图片描述

pom.xml 相关依赖包

<!-- opencv + javacv + ffmpeg-->
        <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>

创建FaceVideo.class 主方法类 来进行人脸识别测试

注意修改下面 faceDetector = new CascadeClassifier( 中.xml路径改成你的路径。

package com.jack.demo.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("D:\\Sofeware\\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;
        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("C:\\Users\\Administrator\\Desktop\\1.avi");//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.png";
        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;
            }
        }
    }

}

开始测试>>>

右键执行FaceVideo.Class Main()方法

如果出现运行Main方法时报错:java.lang.UnsatisfiedLinkError: no opencv_java411 in java.library.path(需要加一个运行参数)
在这里插入图片描述

编辑启动类:Edit Configuration VM options:-Djava.library.path=D:\Sofeware\opencv\build\java\x64;
在这里插入图片描述

1- 测试摄像头实时识别人脸:

在这里插入图片描述

2- 测试本地视频识别人脸

在这里插入图片描述

3- 测试本地图片人脸识别

在这里插入图片描述

4- 测试本地2张图片人脸的相似度

在这里插入图片描述

完结。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/144970.html原文链接:https://javaforall.net

(1)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • ctf-web:关于文件上传漏洞的深入研究[通俗易懂]

    ctf-web:关于文件上传漏洞的深入研究[通俗易懂]上次我们研究了关于文件上传的漏洞,这次我们研究的内容属于上节课的补充内容,关于文件上传的绕过与防御.怎么说呢,算是一种锻炼吧.因为下个月有个awd的比赛,因此最近会经常发一些关于web的内容.其实我还是挺慌的,因为以前参加的都是ctf线上赛,而且我做的都是逆向这个方面的,然而这次突然来了个web,搞得我有点懵.web也是最近才开始研究的,所以写的可能不尽人意,希望各位大佬看看就好,不喜勿喷.一.实验环境我们这次的实验依然用的是上次的网站和phpstudy.我发在了下面.1.upload-f.

    2022年7月15日
    15
  • sonar.exclusions 配置如何生效

    sonar.exclusions 配置如何生效1、sonar.exclusions后配置一定要用**/*Criss*.java格式完成配置2、多个类需要用英文逗号分隔

    2025年5月26日
    3
  • fluent用法总结_28个英语语法速记图解

    fluent用法总结_28个英语语法速记图解最近开始转行做大数据,大数据中很重要的一部分是数据的收集,我们公司主要用的数据收集工具是Fluentd,由于Fluentd的配置比较多,有可能配置过一次后就会忘了。我这边在学习Fluentd配置的同时也对这些配置进行一些记录,方便后面再用到时可以快速的查找。Fluentd简介Fluentd是一款完全免费且完全开源的日志收集器,拥有“LogEverything”的体系结构,能够与125种以…

    2025年7月14日
    5
  • [译文]三重缓冲:为什么我们爱它

    [译文]三重缓冲:为什么我们爱它
    文章来源:http://www.anandtech.com/video/showdoc.aspx?i=3591&p=1
    文章标题:TripleBuffering:WhyWeLoveIt
    文章作者:DerekWilson
    文章时间:2009年6月26日

    引子

    我们往往不愿过多讨论哪些选项在游戏中应该开启。相反,我们往往把重点放在我们的评测内容上。老实说,我们对玩游戏的建议设置与我们的评测设置非常相似,除

    2022年5月21日
    51
  • Linux磁盘阵列

    Linux磁盘阵列一、磁盘阵列1基础知识磁盘阵列(RedundantArraysofIndependentDisks,RAID),有“独立磁盘构成的具有冗余能力的阵列”之意。磁盘阵列是由很多价格较便宜的磁盘,以硬件(RAID卡)或软件(MDADM)形式组合成一个容量巨大的磁盘组,利用多个磁盘组合在一起,提升整个磁盘系统效能。利用这项技术,将数据切割成许多区段,分别存放在各个硬盘上。磁盘阵列还能利用同位检查(ParityCheck)的观念,在数组中任意一个硬盘故障时,仍可读出数据,在数据重构时,将数据经计算

    2022年5月25日
    38
  • goland 2021激活码(破解版激活)

    goland 2021激活码(破解版激活),https://javaforall.net/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

    2022年3月17日
    304

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号