mirror of
https://github.com/geekwenjie/SmartJavaAI.git
synced 2026-09-09 19:18:52 +00:00
18
README.md
18
README.md
@@ -39,6 +39,22 @@
|
||||
|
||||
SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的 JAVA AI算法工具包,致力于帮助JAVA开发者零门槛使用各种AI算法模型,开发者无需深入了解底层实现,即可轻松在 Java 代码中调用人脸识别、目标检测、OCR 等功能。底层支持包括基于 DJL (Deep Java Library) 封装的深度学习模型,以及通过 JNI 接入的 C++/Python 算法,兼容多种主流深度学习框架如 PyTorch、TensorFlow、ONNX、Paddle 等,屏蔽复杂的模型部署与调用细节,开发者无需了解 AI 底层实现即可直接在 Java 项目中集成使用,后续将持续扩展更多算法,目标是构建一个“像 Hutool 一样简单易用”的 JAVA AI 通用工具箱
|
||||
|
||||
|
||||
## 📱 SmartJavaAI Android 商业版
|
||||
|
||||
**SmartJavaAI 现已支持 Android 移动端!**
|
||||
|
||||
如果您有移动端离线人脸识别的需求,我们推出了基于 SmartJavaAI 的 Android SDK 及演示 APP。
|
||||
|
||||
* 🚀 **核心能力**:毫秒级离线人脸检测、比对、注册与 1:N 搜索。
|
||||
* 📦 **开箱即用**:提供标准 SDK 接口与完整 Demo APK。
|
||||
* 💼 **商业授权**:Android 版本为商业授权版本。
|
||||
|
||||
👉 **[点击查看 Android 版演示截图、APK 下载及获取方式](./android.md)**
|
||||
|
||||
|
||||
|
||||
|
||||
## 🚀 能力展示
|
||||
|
||||
<div align="center">
|
||||
@@ -498,7 +514,7 @@ SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的
|
||||
<dependency>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>all</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
```
|
||||
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>all</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<name>${project.artifactId}</name>
|
||||
<description>SmartJavaAI</description>
|
||||
<url>https://github.com/geekwenjie/SmartJavaAI</url>
|
||||
|
||||
68
android.md
Normal file
68
android.md
Normal file
@@ -0,0 +1,68 @@
|
||||
# SmartJavaAI Android 商业版 (SDK & App)
|
||||
|
||||
欢迎关注 SmartJavaAI Android 版本。这是专为移动设备打造的高性能、离线人脸识别解决方案。
|
||||
|
||||
## ✨ 核心功能
|
||||
|
||||
Android 版本包含以下四大核心模块,支持完全**离线运行**,无需联网:
|
||||
|
||||
1. **人脸检测 (Face Detection)**
|
||||
2. **人脸注册 (Face Registration)**
|
||||
3. **人脸比对 (Face Comparison 1:1)**
|
||||
4. **人脸查询 (Face Search 1:N)**
|
||||
|
||||
---
|
||||
|
||||
## 📸 效果演示
|
||||
|
||||
所见即所得,以下是 Demo App 在真机上的运行实拍:
|
||||
|
||||
| **人脸检测** | **人脸比对** |
|
||||
|:----------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------:|
|
||||
| <img src="https://cdn.jsdelivr.net/gh/geekwenjie/SmartJavaAI-Site/images/android/android1.jpg"/> | <img src="https://cdn.jsdelivr.net/gh/geekwenjie/SmartJavaAI-Site/images/android/android2.jpg"/> |
|
||||
|
||||
---
|
||||
|
||||
## 🚀 免费试用申请 (Free Trial)
|
||||
|
||||
我们为开发者提供 **3天全功能免费试用 License**,以便您充分评估 SDK 的性能与效果。请按照以下步骤获取试用:
|
||||
|
||||
### 第一步:下载演示 APK
|
||||
* **文件名**:SmartJavaAI_Face_Demo_v1.0.apk
|
||||
* **下载地址**:[点击这里下载 APK](https://pan.baidu.com/s/1cJhY9q6HcRiLX7orv6CoXQ?pwd=1234)
|
||||
|
||||
### 第二步:邮件申请 License
|
||||
请发送邮件至 **775747758@qq.com** 申请试用授权License。
|
||||
|
||||
* **邮件标题**:SmartJavaAI Android 试用申请
|
||||
* **邮件内容**:
|
||||
* **申请类型**:企业 / 个人
|
||||
* **公司名称/个人姓名**:
|
||||
* **联系电话**:(选填)
|
||||
* **用途简述**:(例如:门禁项目测试)
|
||||
|
||||
> 💡 **小贴士**:您可以直接复制上方内容。收到邮件后,我们通常会在 24 小时内将 License 文件回复给您。
|
||||
|
||||
### 第三步:激活使用
|
||||
下载 APK 并安装后,将邮件附件中的 `秘钥` 粘贴到 App中,即可开启 3 天免费试用。
|
||||
|
||||
---
|
||||
|
||||
## 🤝 正式商业授权与咨询
|
||||
|
||||
试用满意后,如需购买正式商业授权,请联系我们:
|
||||
|
||||
* **SDK 形式**:提供标准 AAR/Jar 包,方便集成。
|
||||
* **源码支持**:提供完整的 Demo 工程源码。
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
**咨询微信 (WeChat):[deng775747758]**
|
||||
|
||||
*(添加时请备注:android)*
|
||||
|
||||
---
|
||||
|
||||
[🔙 返回项目主页](./README.md)
|
||||
@@ -6,10 +6,10 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<artifactId>bom</artifactId>
|
||||
<name>bom</name>
|
||||
<description>统一版本管理的 BOM 包,同时支持 import 和全量依赖</description>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<name>common</name>
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.nio.file.Path;
|
||||
@@ -147,6 +148,19 @@ public class SmartImageFactory {
|
||||
return ImageFactory.getInstance().fromInputStream(inputStream);
|
||||
}
|
||||
|
||||
public Image fromUrl(URL url) throws IOException {
|
||||
if (url == null) {
|
||||
throw new IllegalArgumentException("URL 不能为空");
|
||||
}
|
||||
try (InputStream inputStream = url.openStream()) {
|
||||
return ImageFactory.getInstance().fromInputStream(inputStream);
|
||||
}
|
||||
}
|
||||
|
||||
public Image fromUrl(String urlString) throws IOException {
|
||||
return this.fromUrl(new URL(urlString));
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
35
examples/face-example/Dockerfile
Normal file
35
examples/face-example/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# 使用官方 Ubuntu 22.04 作为基础
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# 设置工作目录(可选,但推荐)
|
||||
WORKDIR /app
|
||||
|
||||
# 更新 apt 仓库并安装 OpenJDK 11
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends openjdk-11-jdk && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# (可选) 验证 Java 安装 (可以选择添加你的应用程序,并编译运行,或者只是执行 java -version)
|
||||
RUN java -version
|
||||
|
||||
# 设置默认的模型路径环境变量
|
||||
ENV SMART_MODEL_PATH=/app/models
|
||||
|
||||
# 创建该目录
|
||||
RUN mkdir -p /app/models
|
||||
|
||||
# 挂载
|
||||
VOLUME ["/app/models"]
|
||||
|
||||
# UTF-8
|
||||
ENV LANG=zh_CN.UTF-8
|
||||
ENV LC_ALL=zh_CN.UTF-8
|
||||
|
||||
|
||||
# 声明服务运行在8080端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 指定docker容器启动时运行jar包
|
||||
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
|
||||
@@ -12,9 +12,9 @@
|
||||
<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.1.0</smartjavaai.version>
|
||||
<smartjavaai.version>1.1.1</smartjavaai.version>
|
||||
<!--如果打包运行,需要替换成你的main-->
|
||||
<exec.mainClass>smartai.examples.face.facedet.FaceDetDemo</exec.mainClass>
|
||||
<exec.mainClass>smartai.examples.face.FaceDemo</exec.mainClass>
|
||||
|
||||
<javacv.version>1.5.10</javacv.version>
|
||||
|
||||
@@ -86,8 +86,22 @@
|
||||
<dependency>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>face</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.microsoft.onnxruntime</groupId>
|
||||
<artifactId>onnxruntime</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.onnxruntime</groupId>
|
||||
<artifactId>onnxruntime</artifactId>
|
||||
<version>1.20.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>ai.djl.pytorch</groupId>
|
||||
<artifactId>pytorch-jni</artifactId>
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package smartai.examples.face;
|
||||
|
||||
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.utils.ImageUtils;
|
||||
import cn.smartjavaai.face.config.FaceDetConfig;
|
||||
import cn.smartjavaai.face.constant.FaceDetectConstant;
|
||||
import cn.smartjavaai.face.enums.FaceDetModelEnum;
|
||||
import cn.smartjavaai.face.factory.FaceDetModelFactory;
|
||||
import cn.smartjavaai.face.model.facedect.FaceDetModel;
|
||||
import cn.smartjavaai.face.utils.FaceUtils;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @author dwj
|
||||
* @date 2025/12/23
|
||||
*/
|
||||
@Slf4j
|
||||
public class FaceDemo {
|
||||
|
||||
public static String MODEL_PATH = "";
|
||||
|
||||
/**
|
||||
* 获取人脸检测模型
|
||||
* 注意事项:极速模型,识别准确度低,速度快
|
||||
* @return
|
||||
*/
|
||||
public static FaceDetModel getFaceDetModel(){
|
||||
FaceDetConfig config = new FaceDetConfig();
|
||||
//人脸检测模型,SmartJavaAI提供了多种模型选择(更多模型,请查看文档),切换模型需要同时修改modelEnum及modelPath
|
||||
config.setModelEnum(FaceDetModelEnum.YOLOV5_FACE_320);
|
||||
//下载模型并替换本地路径,下载地址:https://pan.baidu.com/s/10l22x5fRz_gwLr8EAHa1Jg?pwd=1234 提取码: 1234
|
||||
config.setModelPath(MODEL_PATH + "/face_model/yolo-face/yolov5face-n-0.5-320x320.onnx");
|
||||
//只返回相似度大于该值的人脸,需要根据实际情况调整,分值越大越严格容易漏检,分值越小越宽松容易误识别
|
||||
config.setConfidenceThreshold(0.5f);
|
||||
//用于去除重复的人脸框,当两个框的重叠度超过该值时,只保留一个
|
||||
config.setNmsThresh(FaceDetectConstant.NMS_THRESHOLD);
|
||||
return FaceDetModelFactory.getInstance().getModel(config);
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
MODEL_PATH = System.getenv("SMART_MODEL_PATH");
|
||||
log.info("MODEL_PATH:" + MODEL_PATH);
|
||||
Config.setCachePath("/app/smartjavaai_cache");
|
||||
|
||||
FaceDetModel faceModel = getFaceDetModel();
|
||||
InputStream is = FaceDemo.class
|
||||
.getClassLoader()
|
||||
.getResourceAsStream("iu_1.jpg");
|
||||
//创建Image对象,可以从文件、url、InputStream创建、BufferedImage、Base64创建,具体使用方法可以查看文档
|
||||
Image image = SmartImageFactory.getInstance().fromInputStream(is);
|
||||
R<DetectionResponse> detectedResult = faceModel.detect(image);
|
||||
if(detectedResult.isSuccess()){
|
||||
log.info("人脸检测结果:{}", JSONObject.toJSONString(detectedResult.getData()));
|
||||
}else{
|
||||
log.info("人脸检测失败:{}", detectedResult.getMessage());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -31,9 +31,6 @@ import cn.smartjavaai.face.utils.FaceUtils;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import nu.pattern.OpenCV;
|
||||
import org.bytedeco.javacv.FFmpegFrameGrabber;
|
||||
import org.bytedeco.javacv.Frame;
|
||||
import org.bytedeco.javacv.Java2DFrameUtils;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.opencv.core.Mat;
|
||||
|
||||
35
examples/ocr-examples/Dockerfile
Normal file
35
examples/ocr-examples/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# 使用官方 Ubuntu 22.04 作为基础
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# 设置工作目录(可选,但推荐)
|
||||
WORKDIR /app
|
||||
|
||||
# 更新 apt 仓库并安装 OpenJDK 11
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends openjdk-11-jdk && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# (可选) 验证 Java 安装 (可以选择添加你的应用程序,并编译运行,或者只是执行 java -version)
|
||||
RUN java -version
|
||||
|
||||
# 设置默认的模型路径环境变量
|
||||
ENV SMART_MODEL_PATH=/app/models
|
||||
|
||||
# 创建该目录
|
||||
RUN mkdir -p /app/models
|
||||
|
||||
# 挂载
|
||||
VOLUME ["/app/models"]
|
||||
|
||||
# UTF-8
|
||||
ENV LANG=zh_CN.UTF-8
|
||||
ENV LC_ALL=zh_CN.UTF-8
|
||||
|
||||
|
||||
# 声明服务运行在8080端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 指定docker容器启动时运行jar包
|
||||
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
|
||||
@@ -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.1.0</smartjavaai.version>
|
||||
<smartjavaai.version>1.1.1</smartjavaai.version>
|
||||
<!--如果打包运行,需要替换成你的main-->
|
||||
<exec.mainClass>smartai.examples.ocr.common.OcrRecognizeDemo</exec.mainClass>
|
||||
|
||||
@@ -89,6 +89,19 @@
|
||||
<dependency>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>ocr</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.microsoft.onnxruntime</groupId>
|
||||
<artifactId>onnxruntime</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.onnxruntime</groupId>
|
||||
<artifactId>onnxruntime</artifactId>
|
||||
<version>1.20.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
35
examples/speech-examples/Dockerfile
Normal file
35
examples/speech-examples/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# 使用官方 Ubuntu 22.04 作为基础
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# 设置工作目录(可选,但推荐)
|
||||
WORKDIR /app
|
||||
|
||||
# 更新 apt 仓库并安装 OpenJDK 11
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends openjdk-11-jdk && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# (可选) 验证 Java 安装 (可以选择添加你的应用程序,并编译运行,或者只是执行 java -version)
|
||||
RUN java -version
|
||||
|
||||
# 设置默认的模型路径环境变量
|
||||
ENV SMART_MODEL_PATH=/app/models
|
||||
|
||||
# 创建该目录
|
||||
RUN mkdir -p /app/models
|
||||
|
||||
# 挂载
|
||||
VOLUME ["/app/models"]
|
||||
|
||||
# UTF-8
|
||||
ENV LANG=zh_CN.UTF-8
|
||||
ENV LC_ALL=zh_CN.UTF-8
|
||||
|
||||
|
||||
# 声明服务运行在8080端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 指定docker容器启动时运行jar包
|
||||
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
|
||||
@@ -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.1.0</smartjavaai.version>
|
||||
<smartjavaai.version>1.1.1</smartjavaai.version>
|
||||
<!--如果打包运行,需要替换成你的main-->
|
||||
<exec.mainClass>smartai.examples.speech.asr.common.OcrRecognizeDemo</exec.mainClass>
|
||||
|
||||
|
||||
@@ -234,6 +234,8 @@ public class SpeechRecognizeDemo {
|
||||
@Test
|
||||
public void testVosk() {
|
||||
try {
|
||||
//解决中文乱码问题
|
||||
System.setProperty("jna.encoding","utf-8");
|
||||
SpeechRecognizer recognizer = geVoskRecognizer();
|
||||
//建议上传 WAV 格式音频。其他格式将自动转换为 WAV,可能影响处理速度
|
||||
R<AsrResult> result = recognizer.recognize("src/main/resources/lff_zh.mp3");
|
||||
@@ -289,6 +291,8 @@ public class SpeechRecognizeDemo {
|
||||
@Test
|
||||
public void testVoskAdvanced() {
|
||||
try {
|
||||
//解决中文乱码问题
|
||||
System.setProperty("jna.encoding","utf-8");
|
||||
VoskRecognizer recognizer = (VoskRecognizer)geVoskRecognizer();
|
||||
//使用vosk内部接口,需要指定识别音频的采样率
|
||||
Recognizer voskRecognizer = recognizer.createAdvancedRecognizer(16000);
|
||||
@@ -318,6 +322,8 @@ public class SpeechRecognizeDemo {
|
||||
@Test
|
||||
public void testVoskRealTime() {
|
||||
try {
|
||||
//解决中文乱码问题
|
||||
System.setProperty("jna.encoding","utf-8");
|
||||
VoskRecognizer recognizer = (VoskRecognizer)geVoskRecognizer();
|
||||
//使用vosk内部接口,需要指定识别音频的采样率
|
||||
Recognizer voskRecognizer = recognizer.createAdvancedRecognizer(16000);
|
||||
|
||||
35
examples/translation-example/Dockerfile
Normal file
35
examples/translation-example/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# 使用官方 Ubuntu 22.04 作为基础
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# 设置工作目录(可选,但推荐)
|
||||
WORKDIR /app
|
||||
|
||||
# 更新 apt 仓库并安装 OpenJDK 11
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends openjdk-11-jdk && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# (可选) 验证 Java 安装 (可以选择添加你的应用程序,并编译运行,或者只是执行 java -version)
|
||||
RUN java -version
|
||||
|
||||
# 设置默认的模型路径环境变量
|
||||
ENV SMART_MODEL_PATH=/app/models
|
||||
|
||||
# 创建该目录
|
||||
RUN mkdir -p /app/models
|
||||
|
||||
# 挂载
|
||||
VOLUME ["/app/models"]
|
||||
|
||||
# UTF-8
|
||||
ENV LANG=zh_CN.UTF-8
|
||||
ENV LC_ALL=zh_CN.UTF-8
|
||||
|
||||
|
||||
# 声明服务运行在8080端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 指定docker容器启动时运行jar包
|
||||
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
|
||||
@@ -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.1.0</smartjavaai.version>
|
||||
<smartjavaai.version>1.1.1</smartjavaai.version>
|
||||
<!--如果打包运行,需要替换成你的main-->
|
||||
<exec.mainClass>smartai.examples.nlp.translation.TranslationDemo</exec.mainClass>
|
||||
|
||||
|
||||
35
examples/vision-example/Dockerfile
Normal file
35
examples/vision-example/Dockerfile
Normal file
@@ -0,0 +1,35 @@
|
||||
# 使用官方 Ubuntu 22.04 作为基础
|
||||
FROM ubuntu:22.04
|
||||
|
||||
# 设置工作目录(可选,但推荐)
|
||||
WORKDIR /app
|
||||
|
||||
# 更新 apt 仓库并安装 OpenJDK 11
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends openjdk-11-jdk && \
|
||||
apt-get clean && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
# (可选) 验证 Java 安装 (可以选择添加你的应用程序,并编译运行,或者只是执行 java -version)
|
||||
RUN java -version
|
||||
|
||||
# 设置默认的模型路径环境变量
|
||||
ENV SMART_MODEL_PATH=/app/models
|
||||
|
||||
# 创建该目录
|
||||
RUN mkdir -p /app/models
|
||||
|
||||
# 挂载
|
||||
VOLUME ["/app/models"]
|
||||
|
||||
# UTF-8
|
||||
ENV LANG=zh_CN.UTF-8
|
||||
ENV LC_ALL=zh_CN.UTF-8
|
||||
|
||||
|
||||
# 声明服务运行在8080端口
|
||||
EXPOSE 8080
|
||||
|
||||
# 指定docker容器启动时运行jar包
|
||||
ENTRYPOINT ["java", "-Dfile.encoding=UTF-8", "-jar", "app.jar"]
|
||||
@@ -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.1.0</smartjavaai.version>
|
||||
<smartjavaai.version>1.1.1</smartjavaai.version>
|
||||
<!--如果打包运行,需要替换成你的main-->
|
||||
<exec.mainClass>smartai.examples.vision.ObjectDetectionDemo</exec.mainClass>
|
||||
|
||||
@@ -86,6 +86,19 @@
|
||||
<dependency>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>vision</artifactId>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>com.microsoft.onnxruntime</groupId>
|
||||
<artifactId>onnxruntime</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.microsoft.onnxruntime</groupId>
|
||||
<artifactId>onnxruntime</artifactId>
|
||||
<version>1.20.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
@@ -241,17 +254,10 @@
|
||||
<dependency>
|
||||
<groupId>ai.djl.tensorflow</groupId>
|
||||
<artifactId>tensorflow-native-cpu</artifactId>
|
||||
<classifier>${javacv.platform.linux-arm64}</classifier>
|
||||
<classifier>${djl.platform.linux-aarch64}</classifier>
|
||||
<scope>runtime</scope>
|
||||
<version>2.16.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ai.djl.mxnet</groupId>
|
||||
<artifactId>mxnet-native-mkl</artifactId>
|
||||
<classifier>${javacv.platform.linux-arm64}</classifier>
|
||||
<scope>runtime</scope>
|
||||
<version>1.9.1</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
<!-- macOS M系列 平台 (保留对应平台的配置,可以减小包大小)-->
|
||||
|
||||
@@ -205,13 +205,16 @@ public class ObjectDetectionDemo {
|
||||
*/
|
||||
@Test
|
||||
public void testStream(){
|
||||
|
||||
StreamDetector detector = new StreamDetector.Builder()
|
||||
//视频源类型:支持视频流、本地摄像头、视频文件
|
||||
.sourceType(VideoSourceType.STREAM)
|
||||
//视频流地址,支持rtsp、rtmp、http等常见视频流
|
||||
.streamUrl("rtsp://username:password@ip:port/Streaming/Channels/101")
|
||||
.streamUrl("rtsp://127.0.0.1:8554/stream")
|
||||
//每隔多少帧检测一次(需要根据模型检测速度决定)
|
||||
.frameDetectionInterval(10)
|
||||
//是否打印调试日志
|
||||
.enableDebugLog(false)
|
||||
//目标检测模型
|
||||
.detectorModel(getModel())
|
||||
//回调函数:检测到指定目标时触发(getModel中可指定模型检测的物体)
|
||||
@@ -246,6 +249,7 @@ public class ObjectDetectionDemo {
|
||||
}
|
||||
}).build();
|
||||
detector.startDetection();
|
||||
|
||||
//阻塞主线程
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
try {
|
||||
@@ -319,8 +323,6 @@ public class ObjectDetectionDemo {
|
||||
.frameDetectionInterval(5)
|
||||
//目标检测模型
|
||||
.detectorModel(getModel())
|
||||
//同物体重复检测时间间隔,单位s
|
||||
.repeatGap(5)
|
||||
//回调函数:检测到指定目标时触发(getModel中可指定模型检测的物体)
|
||||
.listener(new StreamDetectionListener() {
|
||||
@Override
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>face</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<name>face</name>
|
||||
<description>SmartJavaAI</description>
|
||||
<url>https://github.com/geekwenjie/SmartJavaAI</url>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>ocr</artifactId>
|
||||
@@ -42,7 +42,7 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<name>ocr</name>
|
||||
<description>SmartJavaAI</description>
|
||||
<url>https://github.com/geekwenjie/SmartJavaAI</url>
|
||||
|
||||
4
pom.xml
4
pom.xml
@@ -7,7 +7,7 @@
|
||||
<name>SmartJavaAI</name>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<packaging>pom</packaging>
|
||||
<description>SmartJavaAI</description>
|
||||
<modules>
|
||||
@@ -109,7 +109,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.4</version>
|
||||
<version>1.18.34</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>speech</artifactId>
|
||||
@@ -57,7 +57,7 @@
|
||||
</dependencies>
|
||||
|
||||
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<name>speech</name>
|
||||
<description>SmartJavaAI</description>
|
||||
<url>https://github.com/geekwenjie/SmartJavaAI</url>
|
||||
|
||||
@@ -56,6 +56,8 @@ public class VoskRecognizer implements SpeechRecognizer{
|
||||
@Override
|
||||
public void loadModel(AsrModelConfig config) {
|
||||
this.config = config;
|
||||
//防止中文乱码
|
||||
System.setProperty("jna.encoding","utf-8");
|
||||
if(StringUtils.isBlank(config.getModelPath())){
|
||||
throw new AsrException("modelPath is null");
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<name>translate</name>
|
||||
<description>SmartJavaAI</description>
|
||||
<url>https://github.com/geekwenjie/SmartJavaAI</url>
|
||||
|
||||
@@ -6,11 +6,11 @@
|
||||
<parent>
|
||||
<groupId>cn.smartjavaai</groupId>
|
||||
<artifactId>smartjavaai-parent</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>vision</artifactId>
|
||||
<version>1.1.0</version>
|
||||
<version>1.1.1</version>
|
||||
<name>vision</name>
|
||||
<description>SmartJavaAI</description>
|
||||
<url>https://github.com/geekwenjie/SmartJavaAI</url>
|
||||
|
||||
@@ -29,10 +29,14 @@ public class CriteriaBuilderFactory {
|
||||
switch (config.getModelEnum()) {
|
||||
case YOLOV8_OFFICIAL_ONNX:
|
||||
return new YoloCriteriaBuilder().buildCriteria(config);
|
||||
case YOLOV11_OFFICIAL_ONNX:
|
||||
return new YoloCriteriaBuilder().buildCriteria(config);
|
||||
case YOLOV12_OFFICIAL_ONNX:
|
||||
return new YoloCriteriaBuilder().buildCriteria(config);
|
||||
case YOLOV8_CUSTOM_ONNX:
|
||||
return new YoloCriteriaBuilder().buildCriteria(config);
|
||||
case YOLOV11_CUSTOM_ONNX:
|
||||
return new YoloCriteriaBuilder().buildCriteria(config);
|
||||
case YOLOV12_CUSTOM_ONNX:
|
||||
return new YoloCriteriaBuilder().buildCriteria(config);
|
||||
case TENSORFLOW2_OFFICIAL:
|
||||
|
||||
@@ -49,7 +49,6 @@ public class StreamDetector implements AutoCloseable{
|
||||
//回调线程池
|
||||
ExecutorService callbackExecutor;
|
||||
private int frameDetectionInterval = 1;
|
||||
private long repeatGap = 5; // 秒
|
||||
private volatile boolean isRunning;
|
||||
private FrameGrabber grabber;
|
||||
private StreamDetectionListener listener;
|
||||
@@ -57,6 +56,8 @@ public class StreamDetector implements AutoCloseable{
|
||||
private VideoSourceType sourceType = VideoSourceType.STREAM; // 默认流
|
||||
private int cameraIndex = 0; // 默认第一个摄像头
|
||||
|
||||
private boolean enableDebugLog; //是否开启debug log
|
||||
|
||||
private Map<String, Long> lastDetectTime = new ConcurrentHashMap<>();
|
||||
private BlockingQueue<Frame> frameQueue = new LinkedBlockingQueue<>(100);
|
||||
|
||||
@@ -84,7 +85,8 @@ public class StreamDetector implements AutoCloseable{
|
||||
this.listener = builder.listener;
|
||||
this.sourceType = builder.sourceType;
|
||||
this.cameraIndex = builder.cameraIndex;
|
||||
this.repeatGap = builder.repeatGap;
|
||||
// this.repeatGap = builder.repeatGap;
|
||||
this.enableDebugLog = builder.enableDebugLog;
|
||||
this.converterToMat = new OpenCVFrameConverter.ToOrgOpenCvCoreMat();
|
||||
}
|
||||
|
||||
@@ -160,7 +162,7 @@ public class StreamDetector implements AutoCloseable{
|
||||
* 负责抓取视频帧到队列
|
||||
*/
|
||||
private void processFrames() {
|
||||
long frameCount = 0;
|
||||
long detectCounter = 0;
|
||||
while (!grabberFinished && isRunning) {
|
||||
try {
|
||||
Frame frame = grabber.grabFrame();
|
||||
@@ -192,11 +194,16 @@ public class StreamDetector implements AutoCloseable{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
frameCount++;
|
||||
if (frameCount % frameDetectionInterval != 0) continue;
|
||||
detectCounter++;
|
||||
if (detectCounter < frameDetectionInterval) {
|
||||
continue;
|
||||
}
|
||||
detectCounter = 0;
|
||||
Frame currentFrame = frame.clone();
|
||||
frameQueue.offer(currentFrame);
|
||||
// log.debug("正在抓取第{}帧,当前帧数:{}", frameCount, frameQueue.size());
|
||||
if (enableDebugLog){
|
||||
log.debug("当前未处理帧数:{}", frameQueue.size());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("抓取视频帧异常", e);
|
||||
}
|
||||
@@ -242,16 +249,15 @@ public class StreamDetector implements AutoCloseable{
|
||||
|
||||
Image image = SmartImageFactory.getInstance().fromMat(mat);
|
||||
DetectedObjects detectedObjects = predictor.predict(image);
|
||||
// log.info("内部检测结果:{}", detectedObjects.toString());
|
||||
if (enableDebugLog){
|
||||
log.debug("帧检测结果:{}", detectedObjects.toString());
|
||||
}
|
||||
DetectionResponse detectionResponse = DetectorUtils.convertToDetectionResponse(detectedObjects, image);
|
||||
if(Objects.isNull(detectionResponse)){
|
||||
return;
|
||||
}
|
||||
List<DetectionInfo> filtered = filterRepeatedObjects(detectionResponse);
|
||||
if (!filtered.isEmpty() && listener != null) {
|
||||
Image copyImage = image.duplicate();
|
||||
callbackExecutor.submit(() -> listener.onObjectDetected(filtered, copyImage));
|
||||
}
|
||||
Image copyImage = image.duplicate();
|
||||
callbackExecutor.submit(() -> listener.onObjectDetected(detectionResponse.getDetectionInfoList(), copyImage));
|
||||
} catch (Throwable e) {
|
||||
e.printStackTrace();
|
||||
log.error("单帧处理异常", e);
|
||||
@@ -260,21 +266,6 @@ public class StreamDetector implements AutoCloseable{
|
||||
}
|
||||
}
|
||||
|
||||
private List<DetectionInfo> filterRepeatedObjects(DetectionResponse response) {
|
||||
List<DetectionInfo> result = new ArrayList<>();
|
||||
long now = System.currentTimeMillis();
|
||||
for (DetectionInfo info : response.getDetectionInfoList()) {
|
||||
String name = info.getObjectDetInfo().getClassName();
|
||||
Long last = lastDetectTime.get(name);
|
||||
if (last == null || (now - last) > repeatGap * 1000) {
|
||||
lastDetectTime.put(name, now);
|
||||
result.add(info);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 开始检测下一个视频文件
|
||||
*/
|
||||
@@ -322,10 +313,6 @@ public class StreamDetector implements AutoCloseable{
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
// if(isRunning){
|
||||
// System.out.println("--isRunning:" + isRunning);
|
||||
// stopDetection();
|
||||
// }
|
||||
if (grabberExecutor != null){
|
||||
grabberExecutor.shutdownNow();
|
||||
}
|
||||
@@ -345,15 +332,11 @@ public class StreamDetector implements AutoCloseable{
|
||||
private VideoSourceType sourceType = VideoSourceType.STREAM; // 默认流
|
||||
private int cameraIndex = 0; // 默认第一个摄像头
|
||||
|
||||
private long repeatGap = 5;//同物体重复检测间隔
|
||||
private boolean enableDebugLog; //是否开启debug log
|
||||
|
||||
public Builder detectorModel(DetectorModel m) { this.detectorModel = m; return this; }
|
||||
public Builder streamUrl(String url) { this.streamUrl = url; return this; }
|
||||
public Builder listener(StreamDetectionListener listener) { this.listener = listener; return this; }
|
||||
public Builder repeatGap(long repeatGap) {
|
||||
this.repeatGap = repeatGap;
|
||||
return this;
|
||||
}
|
||||
public Builder sourceType(VideoSourceType sourceType) {
|
||||
this.sourceType = sourceType;
|
||||
return this;
|
||||
@@ -368,6 +351,11 @@ public class StreamDetector implements AutoCloseable{
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder enableDebugLog(boolean enableDebugLog) {
|
||||
this.enableDebugLog = enableDebugLog;
|
||||
return this;
|
||||
}
|
||||
|
||||
public StreamDetector build() {
|
||||
if (detectorModel == null) {
|
||||
throw new DetectionException("detectorModel 不能为空");
|
||||
|
||||
Reference in New Issue
Block a user