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
由于没有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