package cn.js.ccit.opencv.reco;

import org.opencv.core.Mat; import org.opencv.highgui.HighGui; import org.opencv.videoio.VideoCapture; import java.net.URL; /**  * @Description 读取摄像头  * @Author CodeHaywire  * @Created at 2022-02-06 10:16  */ public class ReadVideoData {     static void showCamera() {         // 加载动态库         URL url = ClassLoader.getSystemResource("lib/opencv_java411.dll");         System.load(url.getPath());         //打开相机         VideoCapture videoCapture = new VideoCapture();         //判断相机是否打开 0:表示打开默认摄像头         if (!videoCapture.open(0)) {             System.out.println("相机打开失败");             return;         }         //循环获取画面         while (true) { //新建关键帧(图片数据每一张都存在里面)             Mat img = new Mat(); //读取并判断 是否读取到             if (!videoCapture.read(img)) {                 return;             } //展示图片 HighGui:opencv自带的窗口             HighGui.imshow("my camera video", img); //延迟10ms展示图片             HighGui.waitKey(10);         }     } }

package cn.js.ccit.opencv.reco;

import org.junit.jupiter.api.Test;

/**
 * @Description 测试
 * @Author CodeHaywire
 * @Created at 2022-02-06 10:17
 */
public class ReadVideoDataTest {
    @Test
    public void testReadVideoData() {
        ReadVideoData.showCamera();
    }
}

每秒钟播放24帧,人眼能看到连续的画面,所以获取的关键帧连续展示在窗口就会看起来像视频

 文件结构  opencv:下载 咔咔咔 下一步 从安装目录拿出这两文件 opencv-xxx.jar  opencv_javaxxx.dll   最后将架(jar)包 add library 即可

接着写  人脸检测和获取人脸训练数据存放到本地

MatOfRect  矩形区域的像素点的集合 (个人理解) 
for (Rect rect : matOfRect.toArray()) {
      System.out.println(rect);
   }
// 输出: 起始点 矩形大小 rect.with rect.height 可以取出矩形的长宽
{258, 198, 149x149}
{264, 195, 149x149}
CascadeClassifier 加载检测文件的对象
Imgproc 处理图片的类
Imgcodecs 保存图片的类
package cn.js.ccit.opencv.reco;

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 java.net.URL;

/**
 * @Description 读取摄像头
 * @Author CodeHaywire
 * @Created at 2022-02-06 10:16
 */
public class ReadVideoData {
    static void showCamera() {
        // 加载动态库
        URL url = ClassLoader.getSystemResource("lib/opencv_java411.dll");
        System.load(url.getPath());
        //添加人脸检测
        CascadeClassifier detector = new CascadeClassifier("src/main/resources/DetectData/haarcascade_frontalface_default.xml");
        //打开相机
        VideoCapture videoCapture = new VideoCapture();
        int count = 1;
        //判断相机是否打开
        if (!videoCapture.open(0)) {
            System.out.println("相机打开失败");
            return;
        }
        //循环获取画面
        while (true) {
            //存放关键帧对象
            Mat img = new Mat();
            if (!videoCapture.read(img)) {
                return;
            }
            Mat gray = new Mat();
            //将彩色画面转成灰度   检测:通常都是用灰度,检测更精确
            Imgproc.cvtColor(img, gray, Imgproc.COLOR_RGB2GRAY);
            MatOfRect matOfRect = new MatOfRect();
                       //将符合的数据区域框选
            detector.detectMultiScale(gray, matOfRect);
            for (Rect rect : matOfRect.toArray()) {
                //System.out.println(rect);
                Imgproc.putText(gray, "YouName", new Point(rect.x + 5, rect.y - 8), 1, 1.0, new Scalar(255, 255, 255));
                Imgproc.rectangle(
                        gray,
                        new Point(rect.x, rect.y),
                        new Point(rect.x + rect.width, rect.y + rect.height),
                        new Scalar(255, 255, 255), 1, 4);
                                //保存人脸区域图片到本地
                Imgcodecs.imwrite("src/main/resources/img/" + count + ".jpg", gray.submat(new Rect(rect.x, rect.y, rect.width, rect.height)));
                count++;
            }
            HighGui.imshow("my camera video", img);
            HighGui.waitKey(10);
        }
    }


}

接着干 训练数据,提高验证正确率,但100%还是不可能的

Python 的face相关模块可以用,但是java版的该模块因不稳定在主项目中移除了,需要自己重新编译运行生成完整jar

可以参照官或者这个博主的文章 https://www.icode9.com/content-1-298318.html

由于没有face相关识别就先不实现训练数据人脸对比了,等我编译出来了完整jar包再说

转成图片相似度对比

package cn.js.ccit.opencv.comp;

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 java.net.URL;
import java.util.ArrayList;
import java.util.List;

/**
 * @Description 比较两张图片人脸的匹配度
 * 原理 :
 * 1. 灰度化(减小图片大小)
 * 2. 人脸识别
 * 3. 人脸切割
 * 4. 直方图相似度匹配  CV_COMP_CORREL 相关性比较算法
 * @Author CodeHaywire
 * @Created at 2022-02-07 11:51
 */
public class FaceCompare {

    static {
        // 加载动态库
        URL url = ClassLoader.getSystemResource("lib/opencv_java455.dll");
        System.load(url.getPath());
    }

    /**
     * 彩色图片转灰度
     */
    static Mat cvtImgToGray(Mat face) {
        Mat grayFace = new Mat();
        Imgproc.cvtColor(face, grayFace, Imgproc.COLOR_RGB2GRAY);
        return grayFace;
    }

    /**
     * 图片对比
     */
    static double compareImg(Mat grayFace, String sqlFace) {
        List gfList = new ArrayList<>();
        List sfList = new ArrayList<>();
        Mat sFace = Imgcodecs.imread(sqlFace);
        Mat cFace = cvtImgToGray(sFace);
        gfList.add(grayFace);
        sfList.add(cFace);
        //存放直方值
        Mat hist_1 = new Mat();
        Mat hist_2 = new Mat();
        //颜色范围
        MatOfFloat ranges = new MatOfFloat(0f, 256f);
        //直方图大小,越大匹配越慢 结果越精确
        MatOfInt histSize = new MatOfInt(1000);
                //计算直方值
        Imgproc.calcHist(gfList, new MatOfInt(0), new Mat(), hist_1, histSize, ranges);
        Imgproc.calcHist(sfList, new MatOfInt(0), new Mat(), hist_2, histSize, ranges);
        // res 相关系数   对比直方值
        double res = Imgproc.compareHist(hist_1, hist_2, Imgproc.CV_COMP_CORREL);
        return res;
    }

    static void showCamera() {
        //添加人脸检测
        CascadeClassifier detector = new CascadeClassifier("src/main/resources/DetectData/haarcascade_frontalface_default.xml");
        //打开相机
        VideoCapture videoCapture = new VideoCapture();
        //判断相机是否打开
        if (!videoCapture.open(0)) {
            System.out.println("相机打开失败");
            return;
        }
        //循环获取画面
        while (true) {
            //存放关键帧对象
            Mat img = new Mat();
            if (!videoCapture.read(img)) {
                return;
            }
            //将彩色画面转成灰度
            Mat gray = cvtImgToGray(img);
            MatOfRect matOfRect = new MatOfRect();
            //检测灰度图,将符合区域存在MatOfRect
            detector.detectMultiScale(gray, matOfRect);
            for (Rect rect : matOfRect.toArray()) {
                //在彩图中框选框选人脸
                Imgproc.rectangle(
                        img,
                        new Point(rect.x, rect.y),
                        new Point(rect.x + rect.width, rect.y + rect.height),
                        new Scalar(255, 255, 255), 1, 4);
                //获取的人脸部分存放在Mat里
                Mat face = new Mat(gray, rect);
                //与数据库的人脸进行对比
                double v = compareImg(face, "src/main/resources/img/1.jpg");
                System.out.println(v);
            }
            HighGui.imshow("my camera video", img);
            HighGui.waitKey(10);
        }
    }
}
package cn.js.ccit.opencv.comp;

import org.junit.jupiter.api.Test;

/**
 * @Description TODO
 * @Author CodeHaywire
 * @Created at 2022-02-07 11:51
 */
public class FaceCompareTest {
    @Test
    public void faceCompare() {
        FaceCompare.showCamera();
    }
}
结果: 是使用的匹配的人脸(我)
0.9125234821221283
0.8965588269011584
0.8786549462021448
0.8786549462021448
0.8387727275205578
0.8315250148777042
使用: 麦麦(赵今麦)
0.07287158869172858
0.0797435690147237
0.024495920668897244
0.024495920668897244
0.010139715957173966
-0.01785953384059259
0.03628837760179462