【人脸识别】 新增多种人脸识别模型

【底层优化】 支持自由选择 OpenCV 或 BufferedImage 作为图像引擎

【通用图像】 全部模型启用 Image 输入,支持各类图片格式与 Image 的互转

【模型管理】 优化模型生命周期,关闭后可重新创建

【人脸识别】 支持在人脸查询结果中绘制姓名标注

【人脸检测】 新增人脸裁剪功能

【修复】 修复若干已知问题,提升系统稳定性
This commit is contained in:
dengwenjie
2025-10-02 16:26:42 +08:00
parent 1b50e2b943
commit dfa8cf9bb4
133 changed files with 6635 additions and 3532 deletions

View File

@@ -12,7 +12,7 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<smartjavaai.version>1.0.24</smartjavaai.version>
<smartjavaai.version>1.0.25</smartjavaai.version>
<!--如果打包运行,需要替换成你的main-->
<exec.mainClass>smartai.examples.face.facedet.FaceDetDemo</exec.mainClass>
@@ -220,35 +220,6 @@
<!-- linux aarch64 平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
</dependencies>
@@ -278,7 +249,21 @@
</plugins>
</build>
<repositories>
<!-- <repository>-->
<!-- <id>aliyunmaven</id>-->
<!-- <name>阿里云公共仓库</name>-->
<!-- <url>https://maven.aliyun.com/repository/public</url>-->
<!-- <releases>-->
<!-- <enabled>true</enabled>-->
<!-- </releases>-->
<!-- <snapshots>-->
<!-- <enabled>false</enabled>-->
<!-- </snapshots>-->
<!-- </repository>-->
<repository>
<id>central</id>
<url>https://repo1.maven.org/maven2/</url>

View File

@@ -1,11 +1,14 @@
package smartai.examples.face.attribute;
import ai.djl.modality.cv.Image;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.entity.R;
import cn.smartjavaai.common.entity.face.FaceAttribute;
import cn.smartjavaai.common.entity.face.FaceInfo;
import cn.smartjavaai.common.utils.ImageUtils;
import cn.smartjavaai.face.config.FaceAttributeConfig;
import cn.smartjavaai.face.config.FaceDetConfig;
import cn.smartjavaai.face.enums.FaceAttributeModelEnum;
@@ -38,6 +41,8 @@ public class FaceAttributeDetDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -47,13 +52,13 @@ public class FaceAttributeDetDemo {
FaceAttributeConfig config = new FaceAttributeConfig();
config.setModelEnum(FaceAttributeModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
config.setModelPath("C:/Users/DengWenJie/Downloads/sf3.0_models/sf3.0_models");
return FaceAttributeModelFactory.getInstance().getModel(config);
}
public FaceDetModel getFaceDetModel() {
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
String modelPath = "C:/Users/DengWenJie/Downloads/sf3.0_models/sf3.0_models";
FaceDetConfig faceDetectModelConfig = new FaceDetConfig();
faceDetectModelConfig.setModelEnum(FaceDetModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
@@ -68,10 +73,12 @@ public class FaceAttributeDetDemo {
public void testFaceAttributeDetect(){
try {
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
DetectionResponse detectionResponse = faceAttributeModel.detect("src/main/resources/iu_1.jpg");
////创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
DetectionResponse detectionResponse = faceAttributeModel.detect(image);
//绘制并导出人脸属性图片,小人脸仅有人脸框
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
FaceUtils.drawBoxesWithFaceAttribute(image, detectionResponse,"C:/Users/Administrator/Downloads/double_person_.png");
BufferedImage bufferedImage = ImageUtils.toBufferedImage(image);
FaceUtils.drawBoxesWithFaceAttribute(bufferedImage, detectionResponse,"C:/Users/Administrator/Downloads/double_person_.png");
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(detectionResponse));
} catch (Exception e) {
e.printStackTrace();
@@ -85,7 +92,9 @@ public class FaceAttributeDetDemo {
public void testFaceAttributeDetect2(){
try {
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
FaceAttribute faceAttribute = faceAttributeModel.detectTopFace("src/main/resources/iu_1.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
FaceAttribute faceAttribute = faceAttributeModel.detectTopFace(image);
log.info("人脸属性检测结果:{}", JSONObject.toJSONString(faceAttribute));
} catch (Exception e) {
e.printStackTrace();
@@ -101,8 +110,8 @@ public class FaceAttributeDetDemo {
try {
FaceDetModel faceDetModel = getFaceDetModel();
FaceAttributeModel faceAttributeModel = getFaceAttributeModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));

View File

@@ -3,6 +3,7 @@ package smartai.examples.face.expression;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionRectangle;
import cn.smartjavaai.common.entity.DetectionResponse;
@@ -11,6 +12,7 @@ import cn.smartjavaai.common.entity.face.ExpressionResult;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.enums.face.FacialExpression;
import cn.smartjavaai.common.enums.face.LivenessStatus;
import cn.smartjavaai.common.utils.BufferedImageUtils;
import cn.smartjavaai.common.utils.ImageUtils;
import cn.smartjavaai.common.utils.OpenCVUtils;
import cn.smartjavaai.face.config.FaceDetConfig;
@@ -60,6 +62,8 @@ public class ExpressionRecDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -75,7 +79,7 @@ public class ExpressionRecDemo {
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(FaceDetModelEnum.MTCNN);
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/face_model");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/mtcnn");
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
config.setConfidenceThreshold(0.5f);
//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
@@ -106,7 +110,9 @@ public class ExpressionRecDemo {
public void testExpressionDetect() {
try {
ExpressionModel model = getExpressionModel();
R<ExpressionResult> result = model.detectTopFace("src/main/resources/emotion/happy.png");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/emotion/happy.png");
R<ExpressionResult> result = model.detectTopFace(image);
if(result.isSuccess()){
log.info("识别结果:{}", JSONObject.toJSONString(result.getData().getExpression().getDescription()));
}else{
@@ -125,7 +131,9 @@ public class ExpressionRecDemo {
public void testExpressionDetect2() {
try {
ExpressionModel model = getExpressionModel();
R<DetectionResponse> result = model.detect("src/main/resources/emotion/happy.png");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/emotion/happy.png");
R<DetectionResponse> result = model.detect(image);
if(result.isSuccess()){
//log.info("识别结果:{}", JSONObject.toJSONString(result.getData()));
for (DetectionInfo detectionInfo : result.getData().getDetectionInfoList()) {
@@ -149,7 +157,8 @@ public class ExpressionRecDemo {
try {
FaceDetModel faceDetModel = getFaceDetModel();
ExpressionModel model = getExpressionModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/emotion/happy.png").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/emotion/happy.png");
R<DetectionResponse> detResult = faceDetModel.detect(image);
if(detResult.isSuccess()){
R<List<ExpressionResult>> result = model.detect(image, detResult.getData());
@@ -178,7 +187,8 @@ public class ExpressionRecDemo {
try {
FaceDetModel faceDetModel = getFaceDetModel();
ExpressionModel model = getExpressionModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/emotion/happy.png").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/emotion/happy.png");
R<DetectionResponse> detResult = faceDetModel.detect(image);
if(detResult.isSuccess()){
for (DetectionInfo detectionInfo : detResult.getData().getDetectionInfoList()) {
@@ -204,15 +214,16 @@ public class ExpressionRecDemo {
public void testExpressionDetectAndDraw(){
try {
ExpressionModel model = getExpressionModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/emotion/surprise.png").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/emotion/surprise.png");
R<DetectionResponse> result = model.detect(image);
if(result.isSuccess()){
//log.info("识别结果:{}", JSONObject.toJSONString(result.getData()));
for (DetectionInfo detectionInfo : result.getData().getDetectionInfoList()) {
log.info("识别结果:{}", JSONObject.toJSONString(detectionInfo.getFaceInfo().getExpressionResult().getExpression().getDescription()));
ImageUtils.drawImageRectWithText(image, detectionInfo.getDetectionRectangle(), detectionInfo.getFaceInfo().getExpressionResult().getExpression().getDescription(), Color.red);
ImageUtils.drawRectAndText(image, detectionInfo.getDetectionRectangle(), detectionInfo.getFaceInfo().getExpressionResult().getExpression().getDescription());
}
ImageUtils.saveImage(image, "output/detect.jpg");
ImageUtils.save(image, "output/detect.jpg");
}else{
log.info("识别失败:{}", result.getMessage());
}
@@ -225,7 +236,7 @@ public class ExpressionRecDemo {
* 摄像头表情识别
* 注意事项:如果视频比较卡,可以使用轻量的人脸检测模型
*/
@Test
// @Test
public void testExpressionDetectCamera(){
try {
ExpressionModel expressionModel = getExpressionModel();
@@ -264,7 +275,7 @@ public class ExpressionRecDemo {
JOptionPane.showConfirmDialog(null, "Failed to capture image from WebCam.");
}
ViewerFrame frame = new ViewerFrame(width, height);
ImageFactory factory = ImageFactory.getInstance();
SmartImageFactory factory = SmartImageFactory.getInstance();
Size size = new Size(width, height);
while (capture.isOpened()) {
@@ -273,19 +284,18 @@ public class ExpressionRecDemo {
}
Mat resizeImage = new Mat();
Imgproc.resize(image, resizeImage, size);
Image img = factory.fromImage(resizeImage);
BufferedImage bufferedImage = OpenCVUtils.mat2Image(resizeImage);
R<DetectionResponse> detectedResult = expressionModel.detect(bufferedImage);
Image img = factory.fromMat(resizeImage);
R<DetectionResponse> detectedResult = expressionModel.detect(img);
if(!detectedResult.isSuccess()){
log.debug("识别失败:{}", detectedResult.getMessage());
continue;
}
for(DetectionInfo detectionInfo : detectedResult.getData().getDetectionInfoList()){
DetectionRectangle detectionRectangle = detectionInfo.getDetectionRectangle();
String text = detectionInfo.getFaceInfo().getExpressionResult().getExpression().getDescription() + ":" + detectionInfo.getFaceInfo().getExpressionResult().getScore();
ImageUtils.drawImageRectWithText(bufferedImage, detectionRectangle, text, Color.red);
String text = detectionInfo.getFaceInfo().getExpressionResult().getExpression().getLabel() + ":" + detectionInfo.getFaceInfo().getExpressionResult().getScore();
ImageUtils.drawRectAndText(img, detectionRectangle, text);
}
frame.showImage(bufferedImage);
frame.showImage(ImageUtils.toBufferedImage(img));
}
capture.release();

View File

@@ -2,7 +2,9 @@ package smartai.examples.face.facedet;
import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import ai.djl.util.JsonUtils;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionRectangle;
import cn.smartjavaai.common.entity.DetectionResponse;
@@ -17,6 +19,7 @@ import cn.smartjavaai.face.enums.FaceDetModelEnum;
import cn.smartjavaai.face.factory.FaceDetModelFactory;
import cn.smartjavaai.face.model.facedect.FaceDetModel;
import cn.smartjavaai.face.model.liveness.LivenessDetModel;
import cn.smartjavaai.face.utils.FaceUtils;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import nu.pattern.OpenCV;
@@ -51,6 +54,8 @@ public class FaceDetDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -67,7 +72,7 @@ public class FaceDetDemo {
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(FaceDetModelEnum.MTCNN);
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/face_model");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/mtcnn");
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
config.setConfidenceThreshold(0.5f);
//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
@@ -104,7 +109,7 @@ public class FaceDetDemo {
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(FaceDetModelEnum.YOLOV5_FACE_320);
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/face_model/yolo-face/yolov5face-n-0.5-320x320.onnx");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/yolo-face/yolov5face-n-0.5-320x320.onnx");
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
config.setConfidenceThreshold(0.5f);
//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
@@ -137,9 +142,16 @@ public class FaceDetDemo {
public void testFaceDetect(){
try {
FaceDetModel faceModel = getFaceDetModel();
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(imgPath);
R<DetectionResponse> detectedResult = faceModel.detect(image);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
//裁剪人脸保存
for (DetectionInfo detectionInfo : detectedResult.getData().getDetectionInfoList()) {
Image faceImage = FaceUtils.cropFace(image, detectionInfo.getDetectionRectangle());
ImageUtils.save(faceImage, "output/face_" + detectionInfo.getDetectionRectangle().getX() + "_" + detectionInfo.getDetectionRectangle().getY() + ".jpg");
}
}else{
log.info("人脸检测失败:{}", detectedResult.getMessage());
}
@@ -156,7 +168,12 @@ public class FaceDetDemo {
public void testFaceDetectAndDraw(){
try {
FaceDetModel faceModel = getFaceDetModel();
faceModel.detectAndDraw("src/main/resources/largest_selfie.jpg","output/largest_selfie_detected.png");
R<DetectionResponse> detectedResult = faceModel.detectAndDraw("src/main/resources/largest_selfie.jpg","output/largest_selfie_detected.png");
if(detectedResult.isSuccess()){
log.info("人脸检测成功:{}", JsonUtils.toJson(detectedResult.getData()));
}else{
log.info("人脸检测失败:{}", detectedResult.getMessage());
}
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -170,15 +187,14 @@ public class FaceDetDemo {
public void testFaceDetectAndDraw2(){
try {
FaceDetModel faceModel = getFaceDetModel();
BufferedImage image = null;
String imagePath = "src/main/resources/largest_selfie.jpg";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//可以根据后续业务场景使用detectedImage
R<BufferedImage> detectedImage = faceModel.detectAndDraw(image);
if(detectedImage.isSuccess()){
log.info("人脸检测成功");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(imgPath);
R<DetectionResponse> detectionResponseR = faceModel.detectAndDraw(image);
if(detectionResponseR.isSuccess()){
log.info("人脸检测成功:{}", JsonUtils.toJson(detectionResponseR.getData()));
ImageUtils.save(detectionResponseR.getData().getDrawnImage(), "output/iu_1_detect.png");
}else{
log.info("人脸检测失败:{}", detectedImage.getMessage());
log.info("人脸检测失败:{}", detectionResponseR.getMessage());
}
} catch (Exception e) {
throw new RuntimeException(e);
@@ -187,31 +203,6 @@ public class FaceDetDemo {
}
/**
* 人脸检测(GPU模式)
*/
@Test
public void testDetectFaceGPU(){
try {
FaceDetConfig config = new FaceDetConfig();
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(FaceDetModelEnum.MTCNN);
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/face_model");
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
config.setConfidenceThreshold(0.5f);
config.setDevice(DeviceEnum.GPU);
FaceDetModel faceModel = FaceDetModelFactory.getInstance().getModel(config);
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
}else{
log.info("人脸检测失败:{}", detectedResult.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 人脸检测(Seetaface6)
@@ -221,7 +212,9 @@ public class FaceDetDemo {
public void testFaceDetectSeetaface6(){
try {
FaceDetModel faceModel = getSeetaface6DetModel();
R<DetectionResponse> detectedResult = faceModel.detect(imgPath);
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(imgPath);
R<DetectionResponse> detectedResult = faceModel.detect(image);
if(detectedResult.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
}else{
@@ -276,7 +269,7 @@ public class FaceDetDemo {
JOptionPane.showConfirmDialog(null, "Failed to capture image from WebCam.");
}
ViewerFrame frame = new ViewerFrame(width, height);
ImageFactory factory = ImageFactory.getInstance();
SmartImageFactory factory = SmartImageFactory.getInstance();
Size size = new Size(width, height);
while (capture.isOpened()) {
@@ -285,9 +278,8 @@ public class FaceDetDemo {
}
Mat resizeImage = new Mat();
Imgproc.resize(image, resizeImage, size);
Image img = factory.fromImage(resizeImage);
BufferedImage bufferedImage = OpenCVUtils.mat2Image(resizeImage);
R<DetectionResponse> detectedResult = faceModel.detect(bufferedImage);
Image img = factory.fromMat(resizeImage);
R<DetectionResponse> detectedResult = faceModel.detect(img);
if(!detectedResult.isSuccess()){
log.debug("识别失败:{}", detectedResult.getMessage());
continue;
@@ -298,11 +290,10 @@ public class FaceDetDemo {
if(detectionInfo.getScore() > 0){
text = detectionInfo.getScore() + "";
}
ImageUtils.drawImageRectWithText(bufferedImage, detectionRectangle, text, Color.red);
ImageUtils.drawRectAndText(img, detectionRectangle, text);
}
frame.showImage(bufferedImage);
frame.showImage(ImageUtils.toBufferedImage(img));
}
capture.release();
System.exit(0);
} catch (Exception e) {

View File

@@ -1,10 +1,13 @@
package smartai.examples.face.facerec;
import cn.smartjavaai.common.config.Config;
import ai.djl.modality.cv.Image;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.entity.R;
import cn.smartjavaai.common.entity.face.FaceSearchResult;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.utils.BufferedImageUtils;
import cn.smartjavaai.common.utils.ImageUtils;
import cn.smartjavaai.face.config.FaceDetConfig;
import cn.smartjavaai.face.config.FaceRecConfig;
import cn.smartjavaai.face.constant.FaceDetectConstant;
@@ -18,7 +21,6 @@ import cn.smartjavaai.face.factory.FaceDetModelFactory;
import cn.smartjavaai.face.factory.FaceRecModelFactory;
import cn.smartjavaai.face.model.facedect.FaceDetModel;
import cn.smartjavaai.face.model.facerec.FaceRecModel;
import cn.smartjavaai.face.utils.SimilarityUtil;
import cn.smartjavaai.face.vector.config.MilvusConfig;
import cn.smartjavaai.face.vector.config.SQLiteConfig;
import cn.smartjavaai.face.vector.entity.FaceVector;
@@ -28,6 +30,7 @@ import lombok.extern.slf4j.Slf4j;
import org.junit.BeforeClass;
import org.junit.Test;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;
@@ -45,6 +48,8 @@ public class FaceRecDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -61,7 +66,7 @@ public class FaceRecDemo {
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(FaceDetModelEnum.MTCNN);
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/face_model");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/mtcnn");
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
config.setConfidenceThreshold(0.5f);
//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
@@ -116,19 +121,19 @@ public class FaceRecDemo {
* 也可以使用其他模型,具体其他模型参数可以查看文档:http://doc.smartjavaai.cn/face.html
* @return
*/
public FaceRecModel getHighAccuracyFaceRecModel(){
public FaceRecModel getFaceRecModel(){
FaceRecConfig config = new FaceRecConfig();
//高精度模型,速度慢
config.setModelEnum(FaceRecModelEnum.ELASTIC_FACE_MODEL);
config.setModelEnum(FaceRecModelEnum.INSIGHT_FACE_IRSE50_MODEL);
//模型路径,请下载模型并替换为本地路径:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/model/elasticface.pt");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/recognition/InsightFace/model_ir_se50.pt");
//裁剪人脸:如果图片已经是裁剪过的,则请将此参数设置为false
config.setCropFace(true);
//开启人脸对齐:适用于人脸不正的场景,开启将提升人脸特征准确度,关闭可以提升性能
config.setAlign(true);
config.setDevice(device);
//指定人脸检测模型
config.setDetectModel(getProFaceDetModel());
config.setDetectModel(getFaceDetModel());
return FaceRecModelFactory.getInstance().getModel(config);
}
@@ -141,9 +146,9 @@ public class FaceRecDemo {
public FaceRecModel getHighSpeedFaceRecModel(){
FaceRecConfig config = new FaceRecConfig();
//模型枚举
config.setModelEnum(FaceRecModelEnum.SEETA_FACE6_LIGHT_MODEL);
config.setModelEnum(FaceRecModelEnum.INSIGHT_FACE_MOBILE_FACENET_MODEL);
//模型路径,请下载模型并替换为本地路径:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/xxx/Documents/develop/model/sf3.0_models");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/recognition/InsightFace/model_mobilefacenet.pt");
//裁剪人脸:如果图片已经是裁剪过的,则请将此参数设置为false
config.setCropFace(true);
//开启人脸对齐:适用于人脸不正的场景,开启将提升人脸特征准确度,关闭可以提升性能
@@ -161,8 +166,9 @@ public class FaceRecDemo {
public FaceRecModel getFaceRecModelWithDbConfig(){
FaceRecConfig config = new FaceRecConfig();
//高精度模型,速度慢,追求速度请更换高速模型,具体其他模型参数可以查看文档:http://doc.smartjavaai.cn/face.html
config.setModelEnum(FaceRecModelEnum.ELASTIC_FACE_MODEL);//人脸识别模型
config.setModelPath("/Users/xxx/Documents/develop/model/elasticface.pt");
config.setModelEnum(FaceRecModelEnum.INSIGHT_FACE_IRSE50_MODEL);
//模型路径,请下载模型并替换为本地路径:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/recognition/InsightFace/model_ir_se50.pt");
//裁剪人脸:如果图片已经是裁剪过的,则请将此参数设置为false
config.setCropFace(true);
//开启人脸对齐:适用于人脸不正的场景,开启将提升人脸特征准确度,关闭可以提升性能
@@ -175,9 +181,9 @@ public class FaceRecDemo {
MilvusConfig vectorDBConfig = new MilvusConfig();
vectorDBConfig.setHost("127.0.0.1");
vectorDBConfig.setPort(19530);
//vectorDBConfig.setUsername("root");
//vectorDBConfig.setPassword("Milvus");
//vectorDBConfig.setCollectionName("face5");
// vectorDBConfig.setUsername("root");
// vectorDBConfig.setPassword("Milvus");
// vectorDBConfig.setCollectionName("face6");
//ID策略:自动生成
vectorDBConfig.setIdStrategy(IdStrategy.AUTO);
//索引类型:内积 (Inner Product) 不建议修改
@@ -193,8 +199,9 @@ public class FaceRecDemo {
public FaceRecModel getFaceRecModelWithSQLiteConfig(){
FaceRecConfig config = new FaceRecConfig();
//高精度模型,速度慢, 追求速度请更换高速模型,具体其他模型参数可以查看文档:http://doc.smartjavaai.cn/face.html
config.setModelEnum(FaceRecModelEnum.ELASTIC_FACE_MODEL);//人脸检测模型
config.setModelPath("/Users/wenjie/Documents/develop/model/elasticface.pt");
config.setModelEnum(FaceRecModelEnum.INSIGHT_FACE_IRSE50_MODEL);
//模型路径,请下载模型并替换为本地路径:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/recognition/InsightFace/model_ir_se50.pt");
//裁剪人脸:如果图片已经是裁剪过的,则请将此参数设置为false
config.setCropFace(true);
//开启人脸对齐:适用于人脸不正的场景,开启将提升人脸特征准确度,关闭可以提升性能
@@ -221,9 +228,11 @@ public class FaceRecDemo {
public void testExtractFeatures(){
try {
//高精度模型,速度慢, 追求速度请更换高速模型: getHighSpeedFaceRecModel
FaceRecModel faceRecModel = getHighAccuracyFaceRecModel();
FaceRecModel faceRecModel = getFaceRecModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//提取图片中所有人脸特征
R<DetectionResponse> faceResult = faceRecModel.extractFeatures("src/main/resources/iu_1.jpg");
R<DetectionResponse> faceResult = faceRecModel.extractFeatures(image);
if(faceResult.isSuccess()){
log.info("人脸特征提取成功:{}", JSONObject.toJSONString(faceResult.getData()));
}else{
@@ -246,15 +255,59 @@ public class FaceRecDemo {
public void featureComparison(){
try {
//高精度模型,速度慢, 追求速度请更换高速模型: getHighSpeedFaceRecModel
FaceRecModel faceRecModel = getHighAccuracyFaceRecModel();
FaceRecModel faceRecModel = getFaceRecModel();
//基于图像直接比对人脸特征
R<Float> similarResult = faceRecModel.featureComparison("src/main/resources/iu_1.jpg","src/main/resources/iu_2.jpg");
if(similarResult.isSuccess()){
//相似度阈值不同模型不同,具体参看文档
log.info("人脸比对相似度:{}", JSONObject.toJSONString(similarResult.getData()));
//不同模型的相似度标准不同。当前阈值仅适用于 insight_face 模型,切换模型时请相应调整阈值,详情请参考文档。
if(similarResult.getData() >= 0.62f){
log.info("识别为同一人");
}else{
log.info("识别为不同人");
}
}else{
log.info("人脸比对失败:{}", similarResult.getMessage());
}
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 人脸比对1:1(基于图像直接比对)
* 流程:从输入图像中裁剪分数最高的人脸 → 提取其人脸特征 → 比对两张图片中提取的人脸特征。(接口内自动完成)
* 注意事项:
* 1、首次调用接口,可能会较慢。只要不关闭程序,后续调用会明显加快。若每次重启程序,则每次首次调用都将重新加载,仍会较慢。
* 2、若人脸朝向不正,可开启人脸对齐以提升特征提取准确度。(方法参考自定义配置人脸特征提取)
* @throws Exception
*/
@Test
public void featureComparison3(){
try {
//高精度模型,速度慢, 追求速度请更换高速模型: getHighSpeedFaceRecModel
FaceRecModel faceRecModel = getFaceRecModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image1 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
Image image2 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_2.jpg");
//基于图像直接比对人脸特征
R<Float> similarResult = faceRecModel.featureComparison(image1, image2);
if(similarResult.isSuccess()){
//相似度阈值不同模型不同,具体参看文档
log.info("人脸比对相似度:{}", JSONObject.toJSONString(similarResult.getData()));
//不同模型的相似度标准不同。当前阈值仅适用于 insight_face 模型,切换模型时请相应调整阈值,详情请参考文档。
if(similarResult.getData() >= 0.62f){
log.info("识别为同一人");
}else{
log.info("识别为不同人");
}
}else{
log.info("人脸比对失败:{}", similarResult.getMessage());
}
}
catch (Exception e){
e.printStackTrace();
@@ -273,9 +326,11 @@ public class FaceRecDemo {
public void featureComparison2(){
try {
//高精度模型,速度慢, 追求速度请更换高速模型: getHighSpeedFaceRecModel
FaceRecModel faceRecModel = getHighAccuracyFaceRecModel();
FaceRecModel faceRecModel = getFaceRecModel();
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult1 = faceRecModel.extractTopFaceFeature("src/main/resources/iu_1.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image1 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
R<float[]> featureResult1 = faceRecModel.extractTopFaceFeature(image1);
if(featureResult1.isSuccess()){
log.info("图片1人脸特征提取成功:{}", JSONObject.toJSONString(featureResult1.getData()));
}else{
@@ -283,7 +338,8 @@ public class FaceRecDemo {
return;
}
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult2 = faceRecModel.extractTopFaceFeature("src/main/resources/iu_2.jpg");
Image image2 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_2.jpg");
R<float[]> featureResult2 = faceRecModel.extractTopFaceFeature(image2);
if(featureResult2.isSuccess()){
log.info("图片2人脸特征提取成功:{}", JSONObject.toJSONString(featureResult2.getData()));
}else{
@@ -293,6 +349,12 @@ public class FaceRecDemo {
//计算相似度
float similar = faceRecModel.calculSimilar(featureResult1.getData(), featureResult2.getData());
log.info("相似度:{}", similar);
//不同模型的相似度标准不同。当前阈值仅适用于 insight_face 模型,切换模型时请相应调整阈值,详情请参考文档。
if(similar >= 0.62f){
log.info("识别为同一人");
}else{
log.info("识别为不同人");
}
}
catch (Exception e){
e.printStackTrace();
@@ -318,8 +380,10 @@ public class FaceRecDemo {
Thread.sleep(100);
}
log.info("====================人脸注册==========================");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult = faceRecModel.extractTopFaceFeature("src/main/resources/iu_1.jpg");
R<float[]> featureResult = faceRecModel.extractTopFaceFeature(image);
if(featureResult.isSuccess()){
log.info("人脸特征提取成功:{}", JSONObject.toJSONString(featureResult.getData()));
}else{
@@ -341,21 +405,23 @@ public class FaceRecDemo {
}else{
log.info("注册失败:{}", registerResult.getMessage());
}
/*log.info("====================人脸更新==========================");
log.info("====================人脸更新==========================");
//更新人脸 只支持自定义ID:vectorDBConfig.setIdStrategy(IdStrategy.CUSTOM);
FaceRegisterInfo updateInfo = new FaceRegisterInfo();
//设置人脸注册的自定义元数据,本例中使用 JSON 格式存储用户信息
JSONObject metadataJsonUpdate = new JSONObject();
metadataJsonUpdate.put("name", "iu_update");
metadataJsonUpdate.put("age", "25");
updateInfo.setMetadata(metadataJsonUpdate.toJSONString());
//更新必须设置ID,只有
updateInfo.setId(registerResult.getData());
faceRecModel.upsertFace(updateInfo, "src/main/resources/iu_2.jpg");
log.info("更新人脸成功");*/
// FaceRegisterInfo updateInfo = new FaceRegisterInfo();
// //设置人脸注册的自定义元数据,本例中使用 JSON 格式存储用户信息
// JSONObject metadataJsonUpdate = new JSONObject();
// metadataJsonUpdate.put("name", "iu_update");
// metadataJsonUpdate.put("age", "25");
// updateInfo.setMetadata(metadataJsonUpdate.toJSONString());
// //更新必须设置ID,只有
// updateInfo.setId(registerResult.getData());
// Image image2 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_2.jpg");
// faceRecModel.upsertFace(updateInfo, image2);
// log.info("更新人脸成功");
log.info("====================人脸查询==========================");
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult2 = faceRecModel.extractTopFaceFeature("src/main/resources/iu_3.jpg");
Image image3 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_3.jpg");
R<float[]> featureResult2 = faceRecModel.extractTopFaceFeature(image3);
if(featureResult2.isSuccess()){
log.info("人脸特征提取成功:{}", JSONObject.toJSONString(featureResult2.getData()));
}else{
@@ -364,8 +430,7 @@ public class FaceRecDemo {
}
FaceSearchParams faceSearchParams = new FaceSearchParams();
faceSearchParams.setTopK(1);
faceSearchParams.setThreshold(0.8f);
// faceSearchParams.setThreshold(0.62f);
List<FaceSearchResult> faceSearchResults = faceRecModel.search(featureResult2.getData(), faceSearchParams);
// R<DetectionResponse> faceSearchResults = faceModel.search("src/main/resources/face/iu_3.jpg", faceSearchParams);
log.info("人脸查询结果:{}", JSONArray.toJSONString(faceSearchResults));
@@ -397,7 +462,9 @@ public class FaceRecDemo {
}
log.info("====================人脸注册==========================");
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult = faceRecModel.extractTopFaceFeature("src/main/resources/iu_1.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
R<float[]> featureResult = faceRecModel.extractTopFaceFeature(image);
if(featureResult.isSuccess()){
log.info("人脸特征提取成功:{}", JSONObject.toJSONString(featureResult.getData()));
}else{
@@ -429,11 +496,13 @@ public class FaceRecDemo {
updateInfo.setMetadata(metadataJsonUpdate.toJSONString());
//更新必须设置ID,只有
updateInfo.setId(registerResult.getData());
faceRecModel.upsertFace(updateInfo, "src/main/resources/iu_2.jpg");
Image image2 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_2.jpg");
faceRecModel.upsertFace(updateInfo, image2);
log.info("更新人脸成功");
log.info("====================人脸查询==========================");
//特征提取(提取分数最高人脸特征),适用于单人脸场景
R<float[]> featureResult2 = faceRecModel.extractTopFaceFeature("src/main/resources/iu_3.jpg");
Image image3 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_3.jpg");
R<float[]> featureResult2 = faceRecModel.extractTopFaceFeature(image3);
if(featureResult2.isSuccess()){
log.info("人脸特征提取成功:{}", JSONObject.toJSONString(featureResult2.getData()));
}else{
@@ -442,7 +511,7 @@ public class FaceRecDemo {
}
FaceSearchParams faceSearchParams = new FaceSearchParams();
faceSearchParams.setTopK(1);
faceSearchParams.setThreshold(0.8f);
//faceSearchParams.setThreshold(0.62f);
List<FaceSearchResult> faceSearchResults = faceRecModel.search(featureResult2.getData(), faceSearchParams);
log.info("人脸查询结果:{}", JSONArray.toJSONString(faceSearchResults));
log.info("====================人脸删除==========================");
@@ -454,6 +523,57 @@ public class FaceRecDemo {
}
}
/**
* 人脸查询及绘制
*
* @throws Exception
*/
@Test
public void searchFace3(){
try {
//高精度模型,速度慢, 追求速度请更换高速模型
FaceRecModel faceRecModel = getFaceRecModelWithSQLiteConfig();
//等待加载人脸库结束
while (!faceRecModel.isLoadFaceCompleted()){
Thread.sleep(100);
}
log.info("====================人脸注册==========================");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//人脸注册信息
FaceRegisterInfo faceRegisterInfo = new FaceRegisterInfo();
//设置人脸注册的自定义元数据,本例中使用 JSON 格式存储用户信息
JSONObject metadataJson = new JSONObject();
metadataJson.put("name", "iu");
metadataJson.put("age", "25");
faceRegisterInfo.setMetadata(metadataJson.toJSONString());
//可自定义 ID,若未设置则自动生成。
//faceRegisterInfo.setId("00001");
//人脸注册,返回人脸库ID
R<String> registerResult = faceRecModel.register(faceRegisterInfo, image);
if(registerResult.isSuccess()){
log.info("注册成功:ID-{}", registerResult.getData());
}else{
log.info("注册失败:{}", registerResult.getMessage());
}
log.info("====================人脸查询==========================");
//特征提取(提取分数最高人脸特征),适用于单人脸场景
Image image3 = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_3.jpg");
FaceSearchParams faceSearchParams = new FaceSearchParams();
faceSearchParams.setTopK(1);
//faceSearchParams.setThreshold(0.62f);
//图片中只会显示Metadata信息中name的字段
Image drawSearchResult = faceRecModel.drawSearchResult(image3, faceSearchParams, "name");
ImageUtils.save(drawSearchResult, "output/search_result.jpg");
log.info("====================人脸删除==========================");
faceRecModel.removeRegister(registerResult.getData());
log.info("人脸删除成功");
}
catch (Exception e){
e.printStackTrace();
}
}
/**
* 获取人脸信息
@@ -486,7 +606,7 @@ public class FaceRecDemo {
public void listFaces(){
//使用ID获取人脸信息
try {
FaceRecModel faceRecModel = getFaceRecModelWithDbConfig();
FaceRecModel faceRecModel = getFaceRecModelWithSQLiteConfig();
//等待加载人脸库结束
while (!faceRecModel.isLoadFaceCompleted()){
Thread.sleep(100);

View File

@@ -4,6 +4,7 @@ import ai.djl.modality.cv.Image;
import ai.djl.modality.cv.ImageFactory;
import cn.hutool.core.lang.UUID;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionRectangle;
import cn.smartjavaai.common.entity.DetectionResponse;
@@ -65,6 +66,8 @@ public class LivenessDetDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -104,9 +107,9 @@ public class LivenessDetDemo {
config.setModelEnum(LivenessModelEnum.MINI_VISION_MODEL);
config.setDevice(device);
//模型1路径:需替换为实际模型存储路径
config.setModelPath("/Users/xxx/Documents/develop/model/live/2.7_80x80_MiniFASNetV2.onnx");
config.setModelPath("/Users/wenjie/Documents/develop/model/live/2.7_80x80_MiniFASNetV2.onnx");
//SE模型路径:需替换为实际模型存储路径
config.putCustomParam("seModelPath", "/Users/xxx/Documents/develop/model/live/4_0_0_80x80_MiniFASNetV1SE.onnx");
config.putCustomParam("seModelPath", "/Users/wenjie/Documents/develop/model/live/4_0_0_80x80_MiniFASNetV1SE.onnx");
//人脸活体阈值,可选,超过阈值则认为是真人,低于阈值是非活体
config.setRealityThreshold(0.5f);
/*视频检测帧数,可选,默认10,输出帧数超过这个number之后,就可以输出识别结果。
@@ -132,7 +135,7 @@ public class LivenessDetDemo {
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(FaceDetModelEnum.MTCNN);
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
config.setModelPath("/Users/wenjie/Documents/develop/face_model");
config.setModelPath("/Users/wenjie/Documents/develop/model/face_model/mtcnn");
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
config.setConfidenceThreshold(0.5f);
//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
@@ -149,10 +152,12 @@ public class LivenessDetDemo {
public void testLivenessDetect(){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
R<DetectionResponse> response = livenessDetModel.detect("src/main/resources/liveness/1.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/liveness/1.jpg");
R<DetectionResponse> response = livenessDetModel.detect(image);
if(response.isSuccess()){
for (DetectionInfo detectionInfo : response.getData().getDetectionInfoList()){
log.info("活体检测结果:{}", JSONObject.toJSONString(detectionInfo.getFaceInfo().getLivenessStatus().getStatus().getDescription()));
log.info("活体检测结果:{}", JSONObject.toJSONString(detectionInfo));
}
}else{
log.info("活体检测失败:{}", response.getMessage());
@@ -169,18 +174,18 @@ public class LivenessDetDemo {
public void testLivenessDetectAndDraw(){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/liveness/1.jpg").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/liveness/1.jpg");
R<DetectionResponse> response = livenessDetModel.detect(image);
if(response.isSuccess()){
for (DetectionInfo detectionInfo : response.getData().getDetectionInfoList()){
log.info("活体检测结果:{}", JSONObject.toJSONString(detectionInfo.getFaceInfo().getLivenessStatus().getStatus().getDescription()));
Color color = detectionInfo.getFaceInfo().getLivenessStatus().getStatus() == LivenessStatus.LIVE ? Color.GREEN : Color.RED;
ImageUtils.drawImageRectWithText(image, detectionInfo.getDetectionRectangle(), detectionInfo.getFaceInfo().getLivenessStatus().getStatus().getDescription(), color);
ImageUtils.drawRectAndText(image, detectionInfo.getDetectionRectangle(), detectionInfo.getFaceInfo().getLivenessStatus().getStatus().toString());
ImageUtils.save(image, "output/detect.jpg");
}
}else{
log.info("活体检测失败:{}", response.getMessage());
}
ImageUtils.saveImage(image, "output/detect.jpg");
} catch (Exception e) {
throw new RuntimeException(e);
}
@@ -194,10 +199,12 @@ public class LivenessDetDemo {
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
//指定文件夹路径
File dir = new File("face-example/src/main/resources/liveness");
File dir = new File("src/main/resources/liveness");
File[] files = dir.listFiles();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
SmartImageFactory imageFactory = SmartImageFactory.getInstance();
for (File file : files) {
R<LivenessResult> response = livenessDetModel.detectTopFace(ImageIO.read(file));
R<LivenessResult> response = livenessDetModel.detectTopFace(imageFactory.fromFile(file));
if(response.isSuccess()){
log.info("{}活体检测结果:{},分数:{}", file.getName(), response.getData().getStatus().getDescription(), response.getData().getScore());
}else{
@@ -218,8 +225,8 @@ public class LivenessDetDemo {
try {
FaceDetModel faceDetectModel = getFaceDetModel();
LivenessDetModel livenessDetModel = getLivenessDetModel();
// 将图片路径转换为 BufferedImage
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/liveness/1.jpg").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/liveness/1.jpg");
//人脸检测
R<DetectionResponse> detectionResponse = faceDetectModel.detect(image);
if(detectionResponse.isSuccess()){
@@ -251,8 +258,8 @@ public class LivenessDetDemo {
try {
FaceDetModel faceDetModel = getFaceDetModel();
LivenessDetModel livenessDetModel = getMiniVisionLivenessDetModel();
// 将图片路径转换为 BufferedImage
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/liveness/1.jpg").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/liveness/1.jpg");
R<DetectionResponse> detResult = faceDetModel.detect(image);
if(detResult.isSuccess()){
for (DetectionInfo detectionInfo : detResult.getData().getDetectionInfoList()) {
@@ -281,7 +288,7 @@ public class LivenessDetDemo {
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
//视频路径
R<LivenessResult> livenessStatus = livenessDetModel.detectVideo("video.mp4");
R<LivenessResult> livenessStatus = livenessDetModel.detectVideo("/Users/wenjie/Documents/idea_workplace/SmartJavaAI-Demo/src/main/resources/girl.mp4");
if (livenessStatus.isSuccess()){
log.info("识别结果:{}", JSONObject.toJSONString(livenessStatus.getData()));
}else{
@@ -296,7 +303,7 @@ public class LivenessDetDemo {
* 摄像头活体检测
* 注意事项:如果视频比较卡,可以使用轻量的人脸检测模型
*/
@Test
// @Test
public void testLivenessDetectCamera(){
try {
LivenessDetModel livenessDetModel = getLivenessDetModel();
@@ -335,7 +342,7 @@ public class LivenessDetDemo {
JOptionPane.showConfirmDialog(null, "Failed to capture image from WebCam.");
}
ViewerFrame frame = new ViewerFrame(width, height);
ImageFactory factory = ImageFactory.getInstance();
SmartImageFactory factory = SmartImageFactory.getInstance();
Size size = new Size(width, height);
while (capture.isOpened()) {
@@ -344,9 +351,8 @@ public class LivenessDetDemo {
}
Mat resizeImage = new Mat();
Imgproc.resize(image, resizeImage, size);
Image img = factory.fromImage(resizeImage);
BufferedImage bufferedImage = OpenCVUtils.mat2Image(resizeImage);
R<DetectionResponse> detectedResult = livenessDetModel.detect(bufferedImage);
Image img = factory.fromMat(resizeImage);
R<DetectionResponse> detectedResult = livenessDetModel.detect(img);
if(!detectedResult.isSuccess()){
log.debug("识别失败:{}", detectedResult.getMessage());
continue;
@@ -355,11 +361,10 @@ public class LivenessDetDemo {
DetectionRectangle detectionRectangle = detectionInfo.getDetectionRectangle();
Color color = detectionInfo.getFaceInfo().getLivenessStatus().getStatus() == LivenessStatus.LIVE ? Color.GREEN : Color.RED;
String text = detectionInfo.getFaceInfo().getLivenessStatus().getStatus().getDescription() + ":" + detectionInfo.getFaceInfo().getLivenessStatus().getScore();
ImageUtils.drawImageRectWithText(bufferedImage, detectionRectangle, text, color);
ImageUtils.drawRectAndText(img, detectionRectangle, text);
}
frame.showImage(bufferedImage);
frame.showImage(ImageUtils.toBufferedImage(img));
}
capture.release();
System.exit(0);
} catch (Exception e) {

View File

@@ -1,6 +1,8 @@
package smartai.examples.face.quality;
import ai.djl.modality.cv.Image;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.entity.R;
@@ -47,6 +49,8 @@ public class FaceQualityDetDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -62,7 +66,7 @@ public class FaceQualityDetDemo {
QualityConfig config = new QualityConfig();
config.setModelEnum(QualityModelEnum.SEETA_FACE6_MODEL);
//需替换为实际模型存储路径
config.setModelPath("C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models");
config.setModelPath("C:/Users/DengWenJie/Downloads/sf3.0_models/sf3.0_models");
config.setDevice(device);
return FaceQualityModelFactory.getInstance().getModel(config);
}
@@ -74,7 +78,7 @@ public class FaceQualityDetDemo {
*/
public FaceDetModel getFaceDetModel() {
//需替换为实际模型存储路径
String modelPath = "C:/Users/Administrator/Downloads/sf3.0_models/sf3.0_models";
String modelPath = "C:/Users/DengWenJie/Downloads/sf3.0_models/sf3.0_models";
FaceDetConfig faceDetectModelConfig = new FaceDetConfig();
faceDetectModelConfig.setModelEnum(FaceDetModelEnum.SEETA_FACE6_MODEL);
faceDetectModelConfig.setModelPath(modelPath);
@@ -91,8 +95,9 @@ public class FaceQualityDetDemo {
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));
@@ -124,8 +129,9 @@ public class FaceQualityDetDemo {
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));
@@ -157,8 +163,8 @@ public class FaceQualityDetDemo {
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));
@@ -190,8 +196,9 @@ public class FaceQualityDetDemo {
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));
@@ -224,8 +231,9 @@ public class FaceQualityDetDemo {
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));
@@ -258,8 +266,9 @@ public class FaceQualityDetDemo {
try {
FaceQualityModel faceQualityModel = getFaceQualityModel();
FaceDetModel faceDetModel = getFaceDetModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/iu_1.jpg");
//人脸检测
BufferedImage image = ImageIO.read(new File(Paths.get("src/main/resources/iu_1.jpg").toAbsolutePath().toString()));
R<DetectionResponse> detectionResponse = faceDetModel.detect(image);
if(detectionResponse.isSuccess()){
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectionResponse.getData()));

Binary file not shown.

Before

Width:  |  Height:  |  Size: 682 KiB

After

Width:  |  Height:  |  Size: 674 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

After

Width:  |  Height:  |  Size: 273 KiB

View File

@@ -12,7 +12,7 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<smartjavaai.version>1.0.24</smartjavaai.version>
<smartjavaai.version>1.0.25</smartjavaai.version>
<!--如果打包运行,需要替换成你的main-->
<exec.mainClass>smartai.examples.ocr.common.OcrRecognizeDemo</exec.mainClass>
@@ -219,39 +219,6 @@
</dependency>
<!-- linux aarch64 平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
</dependencies>
<build>

View File

@@ -2,6 +2,7 @@ package smartai.examples.ocr.common;
import ai.djl.modality.cv.Image;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionResponse;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.utils.ImageUtils;
@@ -43,6 +44,7 @@ public class OcrDetectionDemo {
@BeforeClass
public static void beforeAll() throws IOException {
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -56,7 +58,7 @@ public class OcrDetectionDemo {
//指定检测模型,切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_MOBILE_DET_MODEL);
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
config.setDetModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
config.setDevice(device);
return OcrModelFactory.getInstance().getDetModel(config);
}
@@ -73,7 +75,9 @@ public class OcrDetectionDemo {
public void detect(){
try {
OcrCommonDetModel model = getDetectionModel();
List<OcrBox> boxes = model.detect("src/main/resources/ocr_1.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/ocr_1.jpg");
List<OcrBox> boxes = model.detect(image);
log.info("OCR检测结果:{}", JSONObject.toJSONString(boxes));
} catch (Exception e) {
e.printStackTrace();
@@ -97,6 +101,26 @@ public class OcrDetectionDemo {
}
}
/**
* 文本检测并绘制结果
* 检测图像中的文本区域,仅检测文本框位置,不识别文字内容
* 注意事项:
* 1、批量检测时,模型应统一放在外层 try 中使用,避免重复加载,自动释放资源更安全。
* 2、模型文件需要放在单独文件夹
*/
@Test
public void detectAndDraw2(){
try {
OcrCommonDetModel model = getDetectionModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/ocr_1.jpg");
Image resultImage = model.detectAndDraw(image);
ImageUtils.save(resultImage, "output/ocr_1_detected2.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 批量文本检测:批量检测要求图片宽高一致
@@ -110,7 +134,7 @@ public class OcrDetectionDemo {
try {
OcrCommonDetModel model = getDetectionModel();
//批量检测要求图片宽高一致
String folderPath = "/Users/xxx/Downloads/testing33";
String folderPath = "/Users/wenjie/Downloads/testing33";
//读取文件夹中所有图片
List<Image> images = ImageUtils.readImagesFromFolder(folderPath);
List<List<OcrBox>> ocrResult = model.batchDetectDJLImage(images);

View File

@@ -1,7 +1,10 @@
package smartai.examples.ocr.common;
import ai.djl.modality.cv.Image;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.utils.ImageUtils;
import cn.smartjavaai.ocr.config.DirectionModelConfig;
import cn.smartjavaai.ocr.config.OcrDetModelConfig;
import cn.smartjavaai.ocr.entity.OcrBox;
@@ -46,7 +49,7 @@ public class OcrDirectionDetDemo {
//指定行文本方向检测模型,切换模型需要同时修改modelEnum及modelPath
directionModelConfig.setModelEnum(DirectionModelEnum.PP_LCNET_X0_25);
//指定行文本方向检测模型路径,需要更改为自己的模型路径(下载地址请查看文档)
directionModelConfig.setModelPath("/Users/xxx/Documents/develop/model/ocr/PP-LCNet_x0_25_textline_ori_infer/PP-LCNet_x0_25_textline_ori_infer.onnx");
directionModelConfig.setModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-LCNet_x0_25_textline_ori_infer/PP-LCNet_x0_25_textline_ori_infer.onnx");
directionModelConfig.setDevice(device);
directionModelConfig.setTextDetModel(getDetectionModel());
return OcrModelFactory.getInstance().getDirectionModel(directionModelConfig);
@@ -61,7 +64,7 @@ public class OcrDirectionDetDemo {
//指定检测模型,切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_MOBILE_DET_MODEL);
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
config.setDetModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
config.setDevice(device);
return OcrModelFactory.getInstance().getDetModel(config);
}
@@ -78,7 +81,9 @@ public class OcrDirectionDetDemo {
public void detect(){
try {
OcrDirectionModel directionModel = getDirectionModel();
List<OcrItem> itemList = directionModel.detect("src/main/resources/ocr_1.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/ocr_1.jpg");
List<OcrItem> itemList = directionModel.detect(image);
log.info("OCR方向检测结果1:{}", JSONObject.toJSONString(itemList));
} catch (Exception e) {
e.printStackTrace();
@@ -102,6 +107,25 @@ public class OcrDirectionDetDemo {
}
}
/**
* 文本检测并绘制结果
* 流程:文本检测 -> 方向分类
* 检测图像中的文本区域,仅检测文本框位置,不识别文字内容
* 模型需要放在单独文件夹
*/
@Test
public void detectAndDraw2(){
try {
OcrDirectionModel directionModel = getDirectionModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/ocr_1.jpg");
Image resultImage = directionModel.detectAndDraw(image);
ImageUtils.save(resultImage, "output/ocr_1_detected4.jpg");
} catch (Exception e) {
e.printStackTrace();
}
}
}

View File

@@ -5,7 +5,9 @@ import ai.djl.util.JsonUtils;
import cn.hutool.core.img.ImgUtil;
import cn.hutool.core.io.FileUtil;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.utils.BufferedImageUtils;
import cn.smartjavaai.common.utils.ImageUtils;
import cn.smartjavaai.ocr.config.DirectionModelConfig;
import cn.smartjavaai.ocr.config.OcrDetModelConfig;
@@ -48,34 +50,70 @@ public class OcrRecognizeDemo {
@BeforeClass
public static void beforeAll() throws IOException {
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
//Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
/**
* 获取通用识别模型(不带方向矫正)
* 获取通用识别模型(高精确度模型)
* 注意事项:高精度模型,识别准确度高,速度慢
* @return
*/
public OcrCommonRecModel getRecModel(){
public OcrCommonRecModel getProRecModel(){
OcrRecModelConfig recModelConfig = new OcrRecModelConfig();
//指定文本识别模型,切换模型需要同时修改modelEnum及modelPath
recModelConfig.setRecModelEnum(CommonRecModelEnum.PP_OCR_V5_MOBILE_REC_MODEL);
recModelConfig.setRecModelEnum(CommonRecModelEnum.PP_OCR_V5_SERVER_REC_MODEL);
//指定识别模型位置,需要更改为自己的模型路径(下载地址请查看文档)
recModelConfig.setRecModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_server_rec_infer/PP-OCRv5_server_rec.onnx");
recModelConfig.setDevice(device);
recModelConfig.setTextDetModel(getDetectionModel());
recModelConfig.setTextDetModel(getProDetectionModel());
recModelConfig.setDirectionModel(getDirectionModel());
return OcrModelFactory.getInstance().getRecModel(recModelConfig);
}
/**
* 获取文本检测模型
* 获取通用识别模型(极速模型)
* 注意事项:极速模型,识别准确度低,速度快
* @return
*/
public OcrCommonDetModel getDetectionModel() {
public OcrCommonRecModel getFastRecModel(){
OcrRecModelConfig recModelConfig = new OcrRecModelConfig();
//指定文本识别模型,切换模型需要同时修改modelEnum及modelPath
recModelConfig.setRecModelEnum(CommonRecModelEnum.PP_OCR_V5_MOBILE_REC_MODEL);
//指定识别模型位置,需要更改为自己的模型路径(下载地址请查看文档)
recModelConfig.setRecModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_rec_infer/PP-OCRv5_mobile_rec_infer.onnx");
recModelConfig.setDevice(device);
recModelConfig.setTextDetModel(getFastDetectionModel());
return OcrModelFactory.getInstance().getRecModel(recModelConfig);
}
/**
* 获取文本检测模型(极速模型)
* 注意事项:极速模型,识别准确度低,速度快
* @return
*/
public OcrCommonDetModel getFastDetectionModel() {
OcrDetModelConfig config = new OcrDetModelConfig();
//指定检测模型,切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_MOBILE_DET_MODEL);
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
config.setDevice(device);
return OcrModelFactory.getInstance().getDetModel(config);
}
/**
* 获取文本检测模型(高精确度模型)
* 注意事项:高精度模型,识别准确度高,速度慢
* @return
*/
public OcrCommonDetModel getProDetectionModel() {
OcrDetModelConfig config = new OcrDetModelConfig();
//指定检测模型,切换模型需要同时修改modelEnum及modelPath
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_SERVER_DET_MODEL);
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_server_det_infer/PP-OCRv5_server_det.onnx");
config.setDevice(device);
return OcrModelFactory.getInstance().getDetModel(config);
@@ -90,28 +128,12 @@ public class OcrRecognizeDemo {
//指定行文本方向检测模型,切换模型需要同时修改modelEnum及modelPath
directionModelConfig.setModelEnum(DirectionModelEnum.PP_LCNET_X0_25);
//指定行文本方向检测模型路径,需要更改为自己的模型路径(下载地址请查看文档)
directionModelConfig.setModelPath("/Users/xxx/Documents/develop/model/ocr/PP-LCNet_x0_25_textline_ori_infer/PP-LCNet_x0_25_textline_ori_infer.onnx");
directionModelConfig.setModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-LCNet_x0_25_textline_ori_infer/PP-LCNet_x0_25_textline_ori_infer.onnx");
directionModelConfig.setDevice(device);
return OcrModelFactory.getInstance().getDirectionModel(directionModelConfig);
}
/**
* 获取通用识别模型(带方向矫正)
* @return
*/
public OcrCommonRecModel getRecModelWithDirection() {
OcrRecModelConfig recModelConfig = new OcrRecModelConfig();
//指定文本识别模型,切换模型需要同时修改modelEnum及modelPath
recModelConfig.setRecModelEnum(CommonRecModelEnum.PP_OCR_V5_MOBILE_REC_MODEL);
//指定识别模型位置,需要更改为自己的模型路径(下载地址请查看文档)
recModelConfig.setRecModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_mobile_rec_infer/PP-OCRv5_mobile_rec_infer.onnx");
recModelConfig.setDevice(device);
recModelConfig.setTextDetModel(getDetectionModel());
recModelConfig.setDirectionModel(getDirectionModel());
return OcrModelFactory.getInstance().getRecModel(recModelConfig);
}
/**
* 文本识别
@@ -124,10 +146,12 @@ public class OcrRecognizeDemo {
@Test
public void recognize(){
try {
OcrCommonRecModel recModel = getRecModel();
OcrCommonRecModel recModel = getFastRecModel();
//不带方向矫正,分行返回文本
OcrRecOptions options = new OcrRecOptions(false, true);
OcrInfo ocrInfo = recModel.recognize("/Users/wenjie/Downloads/49421755855753_.pic_hd.jpg",options);
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/ocr_1.jpg");
OcrInfo ocrInfo = recModel.recognize(image, options);
log.info("OCR识别结果:{}", JSONObject.toJSONString(ocrInfo));
} catch (Exception e) {
e.printStackTrace();
@@ -146,8 +170,10 @@ public class OcrRecognizeDemo {
@Test
public void recognizeHandWriting(){
try {
OcrCommonRecModel recModel = getRecModel();
OcrInfo ocrInfo = recModel.recognize("src/main/resources/handwriting_1.jpg",new OcrRecOptions());
OcrCommonRecModel recModel = getFastRecModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/handwriting_1.jpg");
OcrInfo ocrInfo = recModel.recognize(image, new OcrRecOptions());
log.info("OCR识别结果:{}", JSONObject.toJSONString(ocrInfo));
} catch (Exception e) {
e.printStackTrace();
@@ -166,10 +192,12 @@ public class OcrRecognizeDemo {
@Test
public void recognize2(){
try {
OcrCommonRecModel recModel = getRecModelWithDirection();
OcrCommonRecModel recModel = getFastRecModel();
//带方向矫正,分行返回文本
OcrRecOptions options = new OcrRecOptions(true, true);
OcrInfo ocrInfo = recModel.recognize("src/main/resources/ocr_3.jpg",options);
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/ocr_3.jpg");
OcrInfo ocrInfo = recModel.recognize(image, options);
log.info("OCR识别结果:{}", JSONObject.toJSONString(ocrInfo));
} catch (Exception e) {
e.printStackTrace();
@@ -189,7 +217,7 @@ public class OcrRecognizeDemo {
@Test
public void recognizeAndDraw(){
try {
OcrCommonRecModel recModel = getRecModelWithDirection();
OcrCommonRecModel recModel = getFastRecModel();
int fontSize = 18;
recModel.recognizeAndDraw("src/main/resources/general_ocr_002.png", "output/ocr_4_recognized.jpg", fontSize, new OcrRecOptions());
} catch (Exception e) {
@@ -200,55 +228,24 @@ public class OcrRecognizeDemo {
@Test
public void recognizeAndDraw2(){
try {
OcrCommonRecModel recModel = getRecModel();
OcrCommonRecModel recModel = getFastRecModel();
int fontSize = 18;
//创建保存路径
Path inputImagePath = Paths.get("src/main/resources/general_ocr_002.png");
Path imageOutputPath = Paths.get("output/ocr_4_recognized.jpg");
BufferedImage image = null;
image = ImageIO.read(new File(inputImagePath.toAbsolutePath().toString()));
BufferedImage resultImage = recModel.recognizeAndDraw(image, fontSize, new OcrRecOptions());
ImageUtils.saveImage(resultImage, imageOutputPath.toAbsolutePath().toString());
Path imageOutputPath = Paths.get("output/ocr_5_recognized.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(inputImagePath);
OcrInfo ocrInfo = recModel.recognizeAndDraw(image, fontSize, new OcrRecOptions());
log.info("OCR识别结果:{}", JSONObject.toJSONString(ocrInfo));
//保存绘制结果
if(ocrInfo != null && ocrInfo.getDrawnImage() != null){
ImageUtils.save(ocrInfo.getDrawnImage(), imageOutputPath.toAbsolutePath().toString());
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文本识别并绘制结果(返回base64)
*/
@Test
public void recognizeAndDrawToBase64(){
try {
OcrCommonRecModel recModel = getRecModel();
int fontSize = 18;
//创建保存路径
Path inputImagePath = Paths.get("src/main/resources/general_ocr_002.png");
byte[] imageBytes = FileUtil.readBytes(inputImagePath);
String base64 = recModel.recognizeAndDrawToBase64(imageBytes, fontSize, new OcrRecOptions());
log.info("base64:{}", base64);
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 文本识别并绘制结果(返回OcrInfo,OcrInfo中包含base64)
*/
@Test
public void recognizeAndDraw3(){
try {
OcrCommonRecModel recModel = getRecModel();
int fontSize = 18;
//创建保存路径
Path inputImagePath = Paths.get("src/main/resources/general_ocr_002.png");
byte[] imageBytes = FileUtil.readBytes(inputImagePath);
OcrInfo ocrInfo = recModel.recognizeAndDraw(imageBytes, fontSize, new OcrRecOptions());
log.info("ocrInfo:{}", JsonUtils.toJson(ocrInfo));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 批量识别
@@ -259,7 +256,7 @@ public class OcrRecognizeDemo {
@Test
public void batchRecognize(){
try {
OcrCommonRecModel recModel = getRecModelWithDirection();
OcrCommonRecModel recModel = getFastRecModel();
//批量检测要求图片宽高一致
String folderPath = "/Users/xxx/Downloads/testing33";
//读取文件夹中所有图片

View File

@@ -1,7 +1,9 @@
package smartai.examples.ocr.plate;
import ai.djl.modality.cv.Image;
import ai.djl.util.JsonUtils;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.R;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.utils.ImageUtils;
@@ -38,6 +40,7 @@ public class PlateRecDemo {
@BeforeClass
public static void beforeAll() throws IOException {
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -68,6 +71,7 @@ public class PlateRecDemo {
recModelConfig.setModelPath("/Users/wenjie/Documents/develop/model/plate/plate_rec_color.onnx");
//指定车牌检测模型
recModelConfig.setPlateDetModel(getPlateDetModel());
recModelConfig.setDevice(device);
return PlateModelFactory.getInstance().getRecModel(recModelConfig);
}
@@ -75,10 +79,12 @@ public class PlateRecDemo {
* 车牌识别
*/
@Test
public void testDetect() {
public void testDetect() throws IOException {
PlateRecModel plateRecModel = getPlateRecModel();
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/plate/Quicker_20220930_180856.png");
//识别车号
R<List<PlateInfo>> result = plateRecModel.recognize("src/main/resources/plate/Quicker_20220930_180856.png");
R<List<PlateInfo>> result = plateRecModel.recognize(image);
if(result.isSuccess()){
log.info("车牌识别结果:{}", JsonUtils.toJson(result.getData()));
}else{
@@ -109,14 +115,14 @@ public class PlateRecDemo {
public void recognizeAndDraw2() {
try {
PlateRecModel plateRecModel = getPlateRecModel();
BufferedImage image = null;
String imagePath = "src/main/resources/plate/Quicker_20220930_180856.png";
image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(imagePath);
//可以根据后续业务场景使用detectedImage
R<BufferedImage> detectedImage = plateRecModel.recognizeAndDraw(image);
R<Image> detectedImage = plateRecModel.recognizeAndDraw(image);
if(detectedImage.isSuccess()){
log.info("车牌识别成功");
ImageUtils.saveImage(detectedImage.getData(), "output/plate_recognized2.jpg");
ImageUtils.save(detectedImage.getData(), "output/plate_recognized3.jpg");
}else{
log.error("车牌识别失败:{}", detectedImage.getMessage());
}

View File

@@ -3,6 +3,7 @@ package smartai.examples.ocr.table;
import ai.djl.modality.cv.Image;
import cn.hutool.core.io.FileUtil;
import cn.smartjavaai.common.config.Config;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.R;
import cn.smartjavaai.common.enums.DeviceEnum;
import cn.smartjavaai.common.utils.ImageUtils;
@@ -47,6 +48,7 @@ public class TableRecDemo {
@BeforeClass
public static void beforeAll() throws IOException {
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -79,7 +81,6 @@ public class TableRecDemo {
config.setModelEnum(CommonDetModelEnum.PP_OCR_V5_MOBILE_DET_MODEL);
//指定模型位置,需要更改为自己的模型路径(下载地址请查看文档)
config.setDetModelPath("/Users/wenjie/Documents/develop/model/ocr/PP-OCRv5_mobile_det_infer/PP-OCRv5_mobile_det_infer.onnx");
// config.setDetModelPath("/Users/xxx/Documents/develop/model/ocr/PP-OCRv5_server_det_infer/PP-OCRv5_server_det.onnx");
config.setDevice(device);
return OcrModelFactory.getInstance().getDetModel(config);
}
@@ -115,45 +116,6 @@ public class TableRecDemo {
/**
* 表格识别
* 仅支持简单表格
* 流程:表格结构识别 -> 文本检测 -> 文本识别 -> 合成html table
* 注意事项:
* 1、批量检测时,模型应统一放在外层 try 中使用,避免重复加载,自动释放资源更安全。
* 2、模型文件需要放在单独文件夹
*/
@Test
public void recognize(){
try {
TableStructureModel tableStructureModel = getTableStructureModel();
OcrCommonDetModel detModel = getDetectionModel();
OcrCommonRecModel recModel = getRecModel();
OcrDirectionModel directionModel = getDirectionModel();
//创建表格识别器
TableRecognizer tableRecognizer = TableRecognizer.builder()
.withStructureModel(tableStructureModel)
.withTextDetModel(detModel)
// .withDirectionModel(getDirectionModel()) //如果表格中存在旋转的文字,可以使用方向分类模型
.withTextRecModel(recModel).build();
String imagePath = "src/main/resources/table/table_ch1.png";
BufferedImage image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
R<TableStructureResult> result = tableRecognizer.recognize(image);
if(result.isSuccess()){
log.info("result: {}", result.getData().getHtml());
//导出html内容到文件
Path outputPath = Paths.get("output/table_ch2_result.html");
FileUtil.writeUtf8String(result.getData().getHtml(), outputPath.toAbsolutePath().toString());
//绘制表格结构
tableRecognizer.drawTable(result.getData(), image, "output/table_ch2_result.jpg");
//导出excel,如果导出失败,可能是因为表格结果识别的结果是错乱的
tableRecognizer.exportExcel(result.getData().getHtml(), "output/table_ch2_result.xls");
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 表格识别
@@ -177,7 +139,8 @@ public class TableRecDemo {
// .withDirectionModel(getDirectionModel()) //如果表格中存在旋转的文字,可以使用方向分类模型
.withTextRecModel(recModel).build();
String imagePath = "src/main/resources/table/table_ch1.png";
BufferedImage image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(imagePath);
R<TableStructureResult> result = tableRecognizer.recognize(image);
if(result.isSuccess()){
log.info("result: {}", result.getData().getHtml());
@@ -185,8 +148,8 @@ public class TableRecDemo {
Path outputPath = Paths.get("output/table_ch2_result.html");
FileUtil.writeUtf8String(result.getData().getHtml(), outputPath.toAbsolutePath().toString());
//绘制表格结构
BufferedImage resultImage = tableRecognizer.drawTable(result.getData(), image);
ImageUtils.saveImage(resultImage, "output/table_ch2_result.jpg");
Image resultImage = tableRecognizer.drawTable(result.getData(), image);
ImageUtils.save(resultImage, "output/table_ch2_result.jpg");
//导出excel,如果导出失败,可能是因为表格结果识别的结果是错乱的
try (OutputStream out = Files.newOutputStream(Paths.get("output/table_ch2_result2.xls"))) {
tableRecognizer.exportExcel(result.getData().getHtml(), out);

View File

@@ -12,7 +12,7 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<smartjavaai.version>1.0.24</smartjavaai.version>
<smartjavaai.version>1.0.25</smartjavaai.version>
<!--如果打包运行,需要替换成你的main-->
<exec.mainClass>smartai.examples.speech.asr.common.OcrRecognizeDemo</exec.mainClass>

View File

@@ -12,7 +12,7 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<smartjavaai.version>1.0.24</smartjavaai.version>
<smartjavaai.version>1.0.25</smartjavaai.version>
<!--如果打包运行,需要替换成你的main-->
<exec.mainClass>smartai.examples.nlp.translation.TranslationDemo</exec.mainClass>

View File

@@ -12,7 +12,7 @@
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<smartjavaai.version>1.0.24</smartjavaai.version>
<smartjavaai.version>1.0.25</smartjavaai.version>
<!--如果打包运行,需要替换成你的main-->
<exec.mainClass>smartai.examples.vision.ObjectDetectionDemo</exec.mainClass>
@@ -272,36 +272,6 @@
</dependency>
<!-- linux aarch64 平台 (保留对应平台的配置,可以减小包大小)-->
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>javacpp</artifactId>
<version>${javacv.version}</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>ffmpeg</artifactId>
<version>6.1.1-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>openblas</artifactId>
<version>0.3.26-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
<dependency>
<groupId>org.bytedeco</groupId>
<artifactId>opencv</artifactId>
<version>4.9.0-1.5.10</version>
<classifier>${javacv.platform.linux-arm64}</classifier>
</dependency>
</dependencies>

View File

@@ -32,6 +32,8 @@ public class ActionRecognizeDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}

View File

@@ -41,6 +41,8 @@ public class InstanceSegDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -119,7 +121,7 @@ public class InstanceSegDemo {
if(result.isSuccess()){
log.info("实例分割结果:{}", JSONObject.toJSONString(result.getData()));
//保存图片
ImageUtils.saveImage(result.getData().getDrawnImage(), "dog_bike_car_detected.png", "output");
ImageUtils.save(result.getData().getDrawnImage(), "dog_bike_car_detected2.png", "output");
}else{
log.info("实例分割失败:{}", result.getMessage());
}

View File

@@ -36,6 +36,8 @@ public class ObbDetDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -115,7 +117,7 @@ public class ObbDetDemo {
if(result.isSuccess()){
log.info("旋转框检测结果:{}", JSONObject.toJSONString(result.getData()));
//保存图片
ImageUtils.saveImage(result.getData().getDrawnImage(), "boats_obb_detected.png", "output");
ImageUtils.save(result.getData().getDrawnImage(), "output/boats_obb_detected2.png");
}else{
log.info("旋转框检测失败:{}", result.getMessage());
}

View File

@@ -5,6 +5,7 @@ import ai.djl.modality.cv.ImageFactory;
import ai.djl.util.JsonUtils;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.UUID;
import cn.smartjavaai.common.cv.SmartImageFactory;
import cn.smartjavaai.common.entity.DetectionInfo;
import cn.smartjavaai.common.entity.DetectionRectangle;
import cn.smartjavaai.common.entity.DetectionResponse;
@@ -56,6 +57,8 @@ public class ObjectDetectionDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -90,7 +93,9 @@ public class ObjectDetectionDemo {
public void objectDetection(){
try {
DetectorModel detectorModel = getModel();
DetectionResponse detectionResponse = detectorModel.detect("src/main/resources/object_detection.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/object_detection.jpg");
DetectionResponse detectionResponse = detectorModel.detect(image);
log.info("目标检测结果:{}", JSONObject.toJSONString(detectionResponse));
} catch (Exception e) {
e.printStackTrace();
@@ -118,10 +123,14 @@ public class ObjectDetectionDemo {
try {
DetectorModel detectorModel = getModel();
String imagePath = "src/main/resources/object_detection.jpg";
BufferedImage image = ImageIO.read(new File(Paths.get(imagePath).toAbsolutePath().toString()));
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile(imagePath);
//可以根据后续业务场景使用detectedImage
BufferedImage detectedImage = detectorModel.detectAndDraw(image);
Assert.assertNotNull("detectedImage null", detectedImage);
DetectionResponse detectionResponse = detectorModel.detectAndDraw(image);
log.info("目标检测结果:{}", JSONObject.toJSONString(detectionResponse));
if(detectionResponse != null && detectionResponse.getDrawnImage() != null){
ImageUtils.save(detectionResponse.getDrawnImage(), "output/object_detection_detected2.png");
}
} catch (Exception e) {
e.printStackTrace();
}
@@ -181,9 +190,9 @@ public class ObjectDetectionDemo {
config.setTopK(100);
config.setDevice(device);
DetectorModel detectorModel = ObjectDetectionModelFactory.getInstance().getModel(config);
DetectionResponse detectionResponse = detectorModel.detect("src/main/resources/dog_bike_car.jpg");
//检测并保存绘制结果
detectorModel.detectAndDraw("src/main/resources/dog_bike_car.jpg", "output/dog_bike_car_detect.jpg");
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
Image image = SmartImageFactory.getInstance().fromFile("src/main/resources/dog_bike_car.jpg");
DetectionResponse detectionResponse = detectorModel.detect(image);
log.info("目标检测结果:{}", JSONObject.toJSONString(detectionResponse));
} catch (Exception e) {
e.printStackTrace();
@@ -218,11 +227,11 @@ public class ObjectDetectionDemo {
log.info("时间:" + LocalDateTimeUtil.now().toString());
log.info("检测结果:{}", JsonUtils.toJson(detectionInfoList));
//绘制检测结果
OpenCVUtils.drawRectAndText(image, detectionInfoList);
ImageUtils.drawRectAndText(image, detectionInfoList);
//保存图片
ImageUtils.saveImage(image, "test"+ UUID.fastUUID().toString() +".png","/Users/wenjie/Downloads");
ImageUtils.save(image, "test"+ UUID.fastUUID().toString() +".png","/Users/wenjie/Downloads");
if (image != null){
((Mat)image.getWrappedImage()).release();
ImageUtils.releaseOpenCVMat(image);
}
}
@@ -268,9 +277,12 @@ public class ObjectDetectionDemo {
log.info("时间:" + LocalDateTimeUtil.now().toString());
log.info("检测结果:{}", JsonUtils.toJson(detectionInfoList));
//绘制检测结果
OpenCVUtils.drawRectAndText(image, detectionInfoList);
ImageUtils.drawRectAndText(image, detectionInfoList);
//保存图片
ImageUtils.saveImage(image, "test"+ UUID.fastUUID().toString() +".png","/Users/wenjie/Downloads");
ImageUtils.save(image, "test"+ UUID.fastUUID().toString() +".png","/Users/wenjie/Downloads");
if (image != null){
ImageUtils.releaseOpenCVMat(image);
}
}
@Override
@@ -316,9 +328,12 @@ public class ObjectDetectionDemo {
log.info("时间:" + LocalDateTimeUtil.now().toString());
log.info("检测结果:{}", JsonUtils.toJson(detectionInfoList));
//绘制检测结果
OpenCVUtils.drawRectAndText(image, detectionInfoList);
ImageUtils.drawRectAndText(image, detectionInfoList);
//保存图片
ImageUtils.saveImage(image, "test"+ UUID.fastUUID().toString() +".png","/Users/wenjie/Downloads");
ImageUtils.save(image, "test"+ UUID.fastUUID().toString() +".png","/Users/wenjie/Downloads");
if (image != null){
ImageUtils.releaseOpenCVMat(image);
}
}
@Override
@@ -385,7 +400,7 @@ public class ObjectDetectionDemo {
JOptionPane.showConfirmDialog(null, "Failed to capture image from WebCam.");
}
ViewerFrame frame = new ViewerFrame(width, height);
ImageFactory factory = ImageFactory.getInstance();
SmartImageFactory factory = SmartImageFactory.getInstance();
Size size = new Size(width, height);
while (capture.isOpened()) {
@@ -394,9 +409,8 @@ public class ObjectDetectionDemo {
}
Mat resizeImage = new Mat();
Imgproc.resize(image, resizeImage, size);
Image img = factory.fromImage(resizeImage);
BufferedImage bufferedImage = OpenCVUtils.mat2Image(resizeImage);
DetectionResponse detectedResult = detectorModel.detect(bufferedImage);
Image img = factory.fromMat(resizeImage);
DetectionResponse detectedResult = detectorModel.detect(img);
if (Objects.isNull(detectedResult) || Objects.isNull(detectedResult.getDetectionInfoList()) || detectedResult.getDetectionInfoList().size() == 0){
log.debug("未检测到物体");
continue;
@@ -404,11 +418,10 @@ public class ObjectDetectionDemo {
for(DetectionInfo detectionInfo : detectedResult.getDetectionInfoList()){
DetectionRectangle detectionRectangle = detectionInfo.getDetectionRectangle();
String text = detectionInfo.getObjectDetInfo().getClassName();
ImageUtils.drawImageRectWithText(bufferedImage, detectionRectangle, text, Color.RED);
ImageUtils.drawRectAndText(img, detectionRectangle, text);
}
frame.showImage(bufferedImage);
frame.showImage(ImageUtils.toBufferedImage(img));
}
capture.release();
System.exit(0);
} catch (Exception e) {

View File

@@ -32,6 +32,8 @@ public class PersonDetectDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -108,7 +110,7 @@ public class PersonDetectDemo {
if(result.isSuccess()){
log.info("行人检测结果:{}", JSONObject.toJSONString(result.getData()));
//保存图片
ImageUtils.saveImage(result.getData().getDrawnImage(), "person_result.png", "output");
ImageUtils.save(result.getData().getDrawnImage(), "person_result.png", "output");
}else{
log.info("行人检测失败:{}", result.getMessage());
}

View File

@@ -33,6 +33,8 @@ public class PoseDetDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -105,7 +107,7 @@ public class PoseDetDemo {
//可以根据后续业务场景使用detectedImage
Image drawImage = detectorModel.detectAndDraw(image);
//保存图片
ImageUtils.saveImage(drawImage, "pose_detected.png", "output");
ImageUtils.save(drawImage, "pose_detected2.png", "output");
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -36,6 +36,8 @@ public class SemSegDemo {
@BeforeClass
public static void beforeAll() throws IOException {
//将图片处理的底层引擎切换为 OpenCV
SmartImageFactory.setEngine(SmartImageFactory.Engine.OPENCV);
//修改缓存路径
// Config.setCachePath("/Users/xxx/smartjavaai_cache");
}
@@ -109,7 +111,7 @@ public class SemSegDemo {
//可以根据后续业务场景使用detectedImage
Image dretectedImage = detectorModel.detectAndDraw(image);
//保存
ImageUtils.saveImage(dretectedImage, "dog_bike_car_detected.png", "output");
ImageUtils.save(dretectedImage, "dog_bike_car_detected2.png", "output");
} catch (Exception e) {
e.printStackTrace();
}