先一步一步来,中间会讲解会踩到的坑。
作者环境:java11(最好用java8)
1.正常用maven导入坐标:
<dependency> <groupId>org.openpnp</groupId> <artifactId>opencv</artifactId> <version>4.5.3-1</version> </dependency>
依赖下载完别急着写代码
你急着把测试代码写了会遇到:
库文件找不到异常
2.下载库文件:
下载对应版本
下载好运行解压到指定目录后一路打开找到这个opencv_java453.dll
3.下载模型文件:
这个是用于人脸识别的模型
4.把库文件粘贴到你的jdk的bin目录下
因为你在javase的测试main方法调用opencv的api,该api底层是会依赖opencv_java453.dll这个库的,jvm首先就在bin目录下查找该库,所以需要把库文件放bin下。
5.把模型文件放到你的项目目录
可以是根目录也可以像作者一样放src下:
6.编写你的javase测试代码
注意图片文件路径、模型文件路径,不要无脑copy过来直接运行,你只需要修改成你自己项目里面的路径就可以了
import org.opencv.core.*; import org.opencv.imgcodecs.Imgcodecs; import org.opencv.imgproc.Imgproc; import org.opencv.objdetect.CascadeClassifier; import java.util.Arrays; import java.util.Base64; /** * @author mijiupro */ public class FaceDetection { //人脸检测器 private static final CascadeClassifier FACE_DETECTOR; //人脸模型xml文件路径 private static final String FACE_MODEL_PATH = "src/main/java/com/mi9688/common/opencv/model/haarcascade_frontalface_alt.xml"; //测试图片文件夹路径 private static final String TRAINING_DATA_DIR = "src/main/java/com/mi9688/common/opencv/sample"; //检测并处理后保存图片路径 private static final String DETECTION_RESULT ="src/main/java/com/mi9688/common/opencv/result/result.jpg"; static { System.loadLibrary(Core.NATIVE_LIBRARY_NAME);//加载库文件 FACE_DETECTOR = new CascadeClassifier(FACE_MODEL_PATH);//创建级联分类器加载人脸模型xml文件 } /** * 测试模型 */ public static void testModel() { // 加载样本图片 Mat image = Imgcodecs.imread(TRAINING_DATA_DIR+"/1.jpg"); // 检测人脸 MatOfRect faceDetections = new MatOfRect(); FACE_DETECTOR.detectMultiScale(image, faceDetections); int numFaces = faceDetections.toArray().length; System.out.println("人脸数量: " + numFaces); // 绘制标人脸识框并打印人脸位置坐标 Arrays.stream(faceDetections.toArray()).forEach( (rect) -> { Imgproc.rectangle(image, new Point(rect.x, rect.y), new Point(rect.x + rect.width, rect.y + rect.height), new Scalar(0, 255, 0)); System.out.println("坐标: (" + rect.x + ", " + rect.y + ")"); }); // 保存处理后的图片 Imgcodecs.imwrite(DETECTION_RESULT, image); } public static void main(String[] args) { testModel(); } }
运行后你会得到:
恭喜你完成了第一步,当你把人脸识别封装成接口时,又会遇到惊喜,下面说一下这个惊喜。
7.编写前端提交人脸图片的后端人脸校验接口
继续在该测试类写个人脸校验静态方法
public static Boolean hasOneFace(String base64Image) { try { Mat imageMat = Imgcodecs.imdecode(new MatOfByte(Base64.getDecoder().decode(base64Image)), Imgcodecs.IMREAD_UNCHANGED); // 转换为灰度图像 Mat grayImageMat = new Mat(); Imgproc.cvtColor(imageMat, grayImageMat, Imgproc.COLOR_BGR2GRAY); // 检测人脸 MatOfRect faceDetections = new MatOfRect(); FACE_DETECTOR.detectMultiScale(grayImageMat, faceDetections, 1.1, 2, 0, new Size(30, 30)); int numFaces = faceDetections.toArray().length; log.info("人脸数量: " + numFaces); if (numFaces != 1) { log.info("请确保人脸数量为1,且人脸位于图片正中央"); return false; } Arrays.stream(faceDetections.toArray()).forEach(rect -> log.info("坐标: (" + rect.x + ", " + rect.y + ")")); } catch (Exception e) { log.info(e.getMessage()); } return true; }
controller:
@PostMapping("/staff-is-face1") public Result<?> isFaceByOpencv(@RequestBody String faceBase64) { if(FaceDetection.hasOneFace(faceBase64)){ return Result.success(); } return Result.error(ResultCode.FAIL); }
8惊喜:这时前端调用你的接口就会:
又出现库找不到异常了:
这时候你大概率引入了热部署依赖大部分都是这个原因:
这时你需要注释掉热部署导入,然后maven刷新依赖,重启就解决了。
如果还没有解决
那就在你的C:\Windows\System32目录也复制一份库文件opencv_java453.dll
ok到这里你99%已经可以愉快使用你的opencv了
9.注意:该依赖目前不支持java自训练模型,自训练接口仅对c++语言提供,社区补充版本的依赖可以支持模型自训练
地址如下:https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_alt.xml
maven坐标:
<dependency> <groupId>org.bytedeco</groupId> <artifactId>javacv-platform</artifactId> <version>1.5.9</version> </dependency>
具体看github官方文档