赞
踩
OpenCV是一个开源的计算机视觉库,它提供了一系列丰富的图像处理和计算机视觉算法,包括图像读取、显示、滤波、特征检测、目标跟踪等功能。
opencv官网:https://opencv.org/
opencv官网文档:https://docs.opencv.org/4.7.0/index.html
参考教程1:https://www.w3cschool.cn/opencv/
参考教程2:https://www.yiibai.com/opencv/opencv_adding_text.html
opencv下载:https://opencv.org/releases/
这里我们使用4.7.0版本,下载到本地后,双击进行安装即可。
进入到opencv的安装目录:
build :基于window构建
sources:开源,提供源码
进入到build\java 目录
x64与x86目录下是对应的.dll文件:代表给不同的系统使用,下面的代码会使用到.dll文件
opencv-460.jar给java操作openvc的程序包
# 1. 特征分类器:windows 和 linux 中的配置文件都一样,随便用哪个都行
haarcascade_frontalface_alt.xml
# windows 路径 : opencv\build\etc\haarcascades
# linux 路径 : /usr/local/share/opencv4/haarcascades
# 2. jar 包 - 也可以直接使用 javacv 中的 opencv 包
opencv-470.jar
# windows 路径 : {opencv安装目录}\opencv\build\java
# linux 路径 : /usr/local/share/java/opencv4
# 3. 动态库
opencv_java470.dll (windows系统使用此文件)
# windows 路径 : {opencv安装目录}\opencv\build\java\{x64}/{x86} 跟据系统选择
libopencv_java470.so (linux系统使用此文件)
# linux 路径 : /usr/local/share/java/opencv4
<!-- 版本的依赖与下载的opencv版本一致-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.7.0-1.5.9</version>
</dependency>
或:
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacv-platform</artifactId>
<version>1.5.9</version>
</dependency>
或:
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.7.0-0</version>
</dependency>
以上三个依赖任选其一即可,项目打包后观察一下使用哪个依赖打包后的jar文件更小
实验证明:
javacv-platform依赖的jar最大,达到929.64M
org.openpnp.opencv依赖最小,几乎为0M
org.bytedeco.opencv依赖居中,大小为2M
ps:依赖包太大,优化参考:https://blog.csdn.net/u014644574/article/details/122067708
ps:代码中存在加载.dll、haarcascade_frontalface_alt.xml文件,请确保文件地址正确
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操作系统 // todo windows 系统部署加载 .dll 文件 - 路径跟据自己存放位置更改【这里需要使用绝对路径】 System.load("D:\\opencv\\opencv\\build\\java\\x64\\opencv_java470.dll"); } else if (os != null && os.toLowerCase().startsWith("linux")) { // Linux操作系统 // todo Linux 服务器部署加载 .so 文件 - 路径跟据自己存放位置更改【是否需要绝对路径有待验证,目前只在windows 系统实践过】 System.load("/opt/face/libopencv_java440.so"); } // 引入 特征分类器配置 文件:haarcascade_frontalface_alt.xml 文件路径 // 此文件在opencv的安装目录build\etc\haarcascades下可以找到 String property = "D:\\opencv\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_alt.xml"; System.out.println(property); 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); // rect中人脸图片的范围 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(10000000); 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; } }
上述代码加载.dll文件也可使用以下方式:
ps:【不过以下方式需要将opencv安装目录下的build\java\x64\opencv_java470.dll文件复制到C:\Windows\System32目录下才可使用否则会报错】
// 使用此方法需将D:\opencv\opencv\build\java\x64\opencv_java470.dll文件复制到C:\Windows\System32目录下
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
如下:
包括:
从摄像头实时人脸识别,识别成功保存图片到本地
从本地视频文件中识别人脸
本地图片人脸识别,识别成功并保存人脸图片到本地
package com.testpro.test.opencv; 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; /** * Opencv 图片人脸识别、实时摄像头人脸识别、视频文件人脸识别 */ public class FaceVideo { // 初始化人脸探测器 static CascadeClassifier faceDetector; static int i = 0; static { // 判断系统 String os = System.getProperty("os.name"); // 加载动态库 if (os != null && os.toLowerCase().startsWith("windows")) { // Windows操作系统 // todo windows 系统部署加载 .dll 文件 - 路径跟据自己存放位置更改 System.load("D:\\opencv\\opencv\\build\\java\\x64\\opencv_java470.dll"); // ClassLoader.getSystemResource("dlls/opencv_java470.dll"); } else if (os != null && os.toLowerCase().startsWith("linux")) { // Linux操作系统 // todo Linux 服务器部署加载 .so 文件 - 路径跟据自己存放位置更改 System.load("/opt/face/libopencv_java440.so"); } // 引入 特征分类器配置 文件:haarcascade_frontalface_alt.xml 文件路径 String property = "D:\\opencv\\opencv\\build\\etc\\haarcascades\\haarcascade_frontalface_alt.xml"; System.out.println(property); faceDetector = new CascadeClassifier(property); } private static final String PATH_PREFIX = "C:\\Users\\dev\\Desktop\\"; public static void main(String[] args) { // 1- 从摄像头实时人脸识别,识别成功保存图片到本地 // getVideoFromCamera(); // 2- 从本地视频文件中识别人脸 // getVideoFromFile(); // 3- 本地图片人脸识别,识别成功并保存人脸图片到本地 // face("5-1.jpg"); // 4- 比对本地2张图的人脸相似度 (越接近1越相似) double compareHist = compare_image(PATH_PREFIX + "5-1.jpg", PATH_PREFIX + "6-1.jpg"); System.out.println(compareHist); if (compareHist > 0.72) { System.out.println("人脸匹配"); } else { System.out.println("人脸不匹配"); } } /** * OpenCV-4.7.0 从摄像头实时读取 */ 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.7.0 从视频文件中读取 */ public static void getVideoFromFile() { VideoCapture capture = new VideoCapture(); capture.open(PATH_PREFIX + "yimi.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.7.0 人脸识别 * * @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(PATH_PREFIX + "face.png", image); } } return image; } /** * OpenCV-4.7.0 图片人脸识别 */ public static void face(String filename) { // 1 读取OpenCV自带的人脸识别特征XML文件 // OpenCV 图像识别库一般位于 opencv\sources\data 下面 // CascadeClassifier facebook=new CascadeClassifier("D:\\Sofeware\\opencv\\sources\\data\\haarcascades\\haarcascade_frontalface_alt.xml"); // 2 读取测试图片 String imgPath = PATH_PREFIX + filename; 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, PATH_PREFIX + 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.7.0 将摄像头拍摄的视频写入本地 */ 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; } } } }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。