第一步:在项目中pom.xml 文件配置库。
<!-- OpenCV Java绑定 -->
<dependency>
<groupId>org.openpnp</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-0</version>
</dependency>
第二步:下载人脸识别模型
-
人脸识别模型:
face_recognition_sface_2021dec.onnx -
人脸检测模型:
face_detection_yunet_2023mar.onnx -
下载地址:通过网盘分享的文件:opencvModels.rar
链接: https://pan.baidu.com/s/12gaUpC9e6zN7p2C-PpOvKg?pwd=syr6
第三步:java想关代码
package com.jeeplus.modules.sys.service; import nu.pattern.OpenCV; import org.opencv.core.Mat; import org.opencv.core.MatOfByte; import org.opencv.core.Size; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.objdetect.FaceDetectorYN; import org.opencv.objdetect.FaceRecognizerSF; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.URL; import java.util.Base64; @Service @Transactional(readOnly = true) public class FaceRecognitionService { // consine距离阈值 private static double cosine_similar_threshold = 0.7; // 人脸检测模型的本地全路径 private static String faceDetectModelPath = "C:\\zl_models\\face_detection_yunet_2023mar.onnx"; // 声明人脸检测对象 private static FaceDetectorYN faceDetector = null; // 人脸识别模型的本地全路径 private static String faceRecognizModelPath = "C:\\zl_models\\face_recognition_sface_2021dec.onnx"; // 声明人脸识别对象 private static FaceRecognizerSF faceRecognizer = null; public String faceRecognizer(String imgPathA, String imgPathB) throws IOException { // 加载opencv OpenCV.loadLocally(); // 加载人脸检测模型 loadFaceDetector(); // 加载人脸识别模型 loadFaceRecognizer(); return faceRecognizerUtil(imgPathA, imgPathB); } /** * 加载人脸检测模型 */ private static void loadFaceDetector() { if (faceDetector != null) { return; } // 你需要传入人脸检测模型的本地全路径 faceDetector = FaceDetectorYN.create(faceDetectModelPath, "", new Size()); } /** * 加载人脸识别模型 */ private static void loadFaceRecognizer() { if (faceRecognizer != null) { return; } // 你需要传入人脸识别模型的本地全路径 faceRecognizer = FaceRecognizerSF.create(faceRecognizModelPath, ""); } /** * 人脸识别. 比对两张图片的相似程度 * * @param imgPathA imgABase64 * @param imgPathB imgB路径 * @return 返回是否一致 */ public static String faceRecognizerUtil(String imgPathA, String imgPathB) { String result = ""; try { // 将网络地址转换为Mat对象 Mat imgA = base64ToMat(imgPathA.split(",")[1]); Mat imgB = urlToMat(imgPathB); // 2.检测人脸信息 Mat faceA = new Mat(); faceDetector.setInputSize(imgA.size()); faceDetector.detect(imgA, faceA); Mat faceB = new Mat(); faceDetector.setInputSize(imgB.size()); faceDetector.detect(imgB, faceB); if (faceA.rows()>0 && faceB.rows()>0) { // 人脸检测成功 // 3.对齐图像以将脸放在标准位置 Mat alignFaceA = new Mat(); faceRecognizer.alignCrop(imgA, faceA.row(0), alignFaceA); Mat alignFaceB = new Mat(); faceRecognizer.alignCrop(imgB, faceB.row(0), alignFaceB); // 4.从对齐图像中提取人脸特征 Mat featureA = new Mat(); faceRecognizer.feature(alignFaceA, featureA); featureA = featureA.clone(); Mat featureB = new Mat(); faceRecognizer.feature(alignFaceB, featureB); featureB = featureB.clone(); // 5.人脸识别。计算两个面要素之间的距离 // 获取cosine相似度 double match1 = faceRecognizer.match(featureA, featureB, FaceRecognizerSF.FR_COSINE); System.out.println("人脸数据库中数据:" + imgPathB + "与拍照人脸的相似度:" + match1); // 获取l2norm相似度 // double match2 = faceRecognizer.match(featureA, featureB, FaceRecognizerSF.FR_NORM_L2); if (match1 >= cosine_similar_threshold) { result = match1+","+true; } else { result = match1+","+false; } }else { result = 0+","+false; } return result; } catch (Exception e) { e.printStackTrace(); return 0+","+false; } } /** * 将网络地址转换为Mat对象 * @param imgUrl 网络地址 * @return Mat对象 * @throws Exception */ private static Mat urlToMat(String imgUrl) throws Exception { URL url = new URL(imgUrl); InputStream in = url.openStream(); ByteArrayOutputStream buffer = new ByteArrayOutputStream(); int nRead; byte[] data = new byte[16384]; // 16KB buffer size while ((nRead = in.read(data, 0, data.length)) != -1) { buffer.write(data, 0, nRead); } in.close(); byte[] bytes = buffer.toByteArray(); MatOfByte matOfByte = new MatOfByte(); matOfByte.fromArray(bytes); return Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_COLOR); } /** * 将base64字符串转换为Mat对象 * @param base64Str base64字符串 * @return Mat对象 * @throws Exception * 注意:这里的base64字符串是不含前缀的,即不含data:image/jpeg;base64, */ private static Mat base64ToMat(String base64Str) throws Exception { byte[] decodedBytes = Base64.getDecoder().decode(base64Str); MatOfByte matOfByte = new MatOfByte(); matOfByte.fromArray(decodedBytes); return Imgcodecs.imdecode(matOfByte, Imgcodecs.IMREAD_COLOR); } }
浙公网安备 33010602011771号