diff --git a/README.md b/README.md index 8694a68..dd3d11a 100644 --- a/README.md +++ b/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)** + + + + ## 🚀 能力展示
@@ -498,7 +514,7 @@ SmartJavaAI是专为JAVA 开发者打造的一个功能丰富、开箱即用的 cn.smartjavaai all - 1.1.0 + 1.1.1 ``` diff --git a/all/pom.xml b/all/pom.xml index 63c7d14..bb154f0 100644 --- a/all/pom.xml +++ b/all/pom.xml @@ -6,11 +6,11 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 all - 1.1.0 + 1.1.1 ${project.artifactId} SmartJavaAI https://github.com/geekwenjie/SmartJavaAI diff --git a/android.md b/android.md new file mode 100644 index 0000000..d978646 --- /dev/null +++ b/android.md @@ -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 在真机上的运行实拍: + +| **人脸检测** | **人脸比对** | +|:----------------------------------------------------------------------------------------------------------------:|:------------------------------------------------------------------------------------------------:| +| | | + +--- + +## 🚀 免费试用申请 (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) diff --git a/bom/pom.xml b/bom/pom.xml index 815bba0..d4af111 100644 --- a/bom/pom.xml +++ b/bom/pom.xml @@ -6,10 +6,10 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 - 1.1.0 + 1.1.1 bom bom 统一版本管理的 BOM 包,同时支持 import 和全量依赖 diff --git a/common/pom.xml b/common/pom.xml index e8d4e2c..80a80fd 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -6,7 +6,7 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 common diff --git a/common/src/main/java/cn/smartjavaai/common/cv/SmartImageFactory.java b/common/src/main/java/cn/smartjavaai/common/cv/SmartImageFactory.java index 2d0a184..6cc513f 100644 --- a/common/src/main/java/cn/smartjavaai/common/cv/SmartImageFactory.java +++ b/common/src/main/java/cn/smartjavaai/common/cv/SmartImageFactory.java @@ -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)); + } + } diff --git a/examples/face-example/Dockerfile b/examples/face-example/Dockerfile new file mode 100644 index 0000000..45829d4 --- /dev/null +++ b/examples/face-example/Dockerfile @@ -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"] diff --git a/examples/face-example/pom.xml b/examples/face-example/pom.xml index 78c8918..bb240c3 100644 --- a/examples/face-example/pom.xml +++ b/examples/face-example/pom.xml @@ -12,9 +12,9 @@ 11 11 UTF-8 - 1.1.0 + 1.1.1 - smartai.examples.face.facedet.FaceDetDemo + smartai.examples.face.FaceDemo 1.5.10 @@ -86,8 +86,22 @@ cn.smartjavaai face + + + com.microsoft.onnxruntime + onnxruntime + + + + com.microsoft.onnxruntime + onnxruntime + 1.20.0 + runtime + + + ai.djl.pytorch pytorch-jni diff --git a/examples/face-example/src/main/java/smartai/examples/face/FaceDemo.java b/examples/face-example/src/main/java/smartai/examples/face/FaceDemo.java new file mode 100644 index 0000000..e3f6e1d --- /dev/null +++ b/examples/face-example/src/main/java/smartai/examples/face/FaceDemo.java @@ -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 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); + } + + } + +} diff --git a/examples/face-example/src/main/java/smartai/examples/face/liveness/LivenessDetDemo.java b/examples/face-example/src/main/java/smartai/examples/face/liveness/LivenessDetDemo.java index e6854e2..9366930 100644 --- a/examples/face-example/src/main/java/smartai/examples/face/liveness/LivenessDetDemo.java +++ b/examples/face-example/src/main/java/smartai/examples/face/liveness/LivenessDetDemo.java @@ -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; diff --git a/examples/ocr-examples/Dockerfile b/examples/ocr-examples/Dockerfile new file mode 100644 index 0000000..45829d4 --- /dev/null +++ b/examples/ocr-examples/Dockerfile @@ -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"] diff --git a/examples/ocr-examples/pom.xml b/examples/ocr-examples/pom.xml index b444855..f2ee663 100644 --- a/examples/ocr-examples/pom.xml +++ b/examples/ocr-examples/pom.xml @@ -12,7 +12,7 @@ 11 11 UTF-8 - 1.1.0 + 1.1.1 smartai.examples.ocr.common.OcrRecognizeDemo @@ -89,6 +89,19 @@ cn.smartjavaai ocr + + + com.microsoft.onnxruntime + onnxruntime + + + + + + com.microsoft.onnxruntime + onnxruntime + 1.20.0 + runtime diff --git a/examples/speech-examples/Dockerfile b/examples/speech-examples/Dockerfile new file mode 100644 index 0000000..45829d4 --- /dev/null +++ b/examples/speech-examples/Dockerfile @@ -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"] diff --git a/examples/speech-examples/pom.xml b/examples/speech-examples/pom.xml index cc0c81c..8407683 100644 --- a/examples/speech-examples/pom.xml +++ b/examples/speech-examples/pom.xml @@ -12,7 +12,7 @@ 11 11 UTF-8 - 1.1.0 + 1.1.1 smartai.examples.speech.asr.common.OcrRecognizeDemo diff --git a/examples/speech-examples/src/main/java/smartai/examples/speech/asr/SpeechRecognizeDemo.java b/examples/speech-examples/src/main/java/smartai/examples/speech/asr/SpeechRecognizeDemo.java index 23795d8..7b544a6 100644 --- a/examples/speech-examples/src/main/java/smartai/examples/speech/asr/SpeechRecognizeDemo.java +++ b/examples/speech-examples/src/main/java/smartai/examples/speech/asr/SpeechRecognizeDemo.java @@ -234,6 +234,8 @@ public class SpeechRecognizeDemo { @Test public void testVosk() { try { + //解决中文乱码问题 + System.setProperty("jna.encoding","utf-8"); SpeechRecognizer recognizer = geVoskRecognizer(); //建议上传 WAV 格式音频。其他格式将自动转换为 WAV,可能影响处理速度 R 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); diff --git a/examples/translation-example/Dockerfile b/examples/translation-example/Dockerfile new file mode 100644 index 0000000..45829d4 --- /dev/null +++ b/examples/translation-example/Dockerfile @@ -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"] diff --git a/examples/translation-example/pom.xml b/examples/translation-example/pom.xml index b4f85e4..52610c8 100644 --- a/examples/translation-example/pom.xml +++ b/examples/translation-example/pom.xml @@ -12,7 +12,7 @@ 11 11 UTF-8 - 1.1.0 + 1.1.1 smartai.examples.nlp.translation.TranslationDemo diff --git a/examples/vision-example/Dockerfile b/examples/vision-example/Dockerfile new file mode 100644 index 0000000..45829d4 --- /dev/null +++ b/examples/vision-example/Dockerfile @@ -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"] diff --git a/examples/vision-example/pom.xml b/examples/vision-example/pom.xml index db39394..81a5277 100644 --- a/examples/vision-example/pom.xml +++ b/examples/vision-example/pom.xml @@ -12,7 +12,7 @@ 11 11 UTF-8 - 1.1.0 + 1.1.1 smartai.examples.vision.ObjectDetectionDemo @@ -86,6 +86,19 @@ cn.smartjavaai vision + + + com.microsoft.onnxruntime + onnxruntime + + + + + + com.microsoft.onnxruntime + onnxruntime + 1.20.0 + runtime @@ -241,17 +254,10 @@ ai.djl.tensorflow tensorflow-native-cpu - ${javacv.platform.linux-arm64} + ${djl.platform.linux-aarch64} runtime 2.16.1 - - ai.djl.mxnet - mxnet-native-mkl - ${javacv.platform.linux-arm64} - runtime - 1.9.1 - diff --git a/examples/vision-example/src/main/java/smartai/examples/vision/ObjectDetectionDemo.java b/examples/vision-example/src/main/java/smartai/examples/vision/ObjectDetectionDemo.java index 50fd93c..af6972b 100644 --- a/examples/vision-example/src/main/java/smartai/examples/vision/ObjectDetectionDemo.java +++ b/examples/vision-example/src/main/java/smartai/examples/vision/ObjectDetectionDemo.java @@ -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 diff --git a/face/pom.xml b/face/pom.xml index e5ea7ce..56f3654 100644 --- a/face/pom.xml +++ b/face/pom.xml @@ -6,11 +6,11 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 face - 1.1.0 + 1.1.1 face SmartJavaAI https://github.com/geekwenjie/SmartJavaAI diff --git a/ocr/pom.xml b/ocr/pom.xml index 67ad098..32df199 100644 --- a/ocr/pom.xml +++ b/ocr/pom.xml @@ -6,7 +6,7 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 ocr @@ -42,7 +42,7 @@ - 1.1.0 + 1.1.1 ocr SmartJavaAI https://github.com/geekwenjie/SmartJavaAI diff --git a/pom.xml b/pom.xml index c07ea22..1104534 100644 --- a/pom.xml +++ b/pom.xml @@ -7,7 +7,7 @@ SmartJavaAI cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 pom SmartJavaAI @@ -109,7 +109,7 @@ org.projectlombok lombok - 1.18.4 + 1.18.34 diff --git a/speech/pom.xml b/speech/pom.xml index bfaf7c7..fdc832f 100644 --- a/speech/pom.xml +++ b/speech/pom.xml @@ -6,7 +6,7 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 speech @@ -57,7 +57,7 @@ - 1.1.0 + 1.1.1 speech SmartJavaAI https://github.com/geekwenjie/SmartJavaAI diff --git a/speech/src/main/java/cn/smartjavaai/speech/asr/model/VoskRecognizer.java b/speech/src/main/java/cn/smartjavaai/speech/asr/model/VoskRecognizer.java index cbb4fcc..31693de 100644 --- a/speech/src/main/java/cn/smartjavaai/speech/asr/model/VoskRecognizer.java +++ b/speech/src/main/java/cn/smartjavaai/speech/asr/model/VoskRecognizer.java @@ -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"); } diff --git a/translate/pom.xml b/translate/pom.xml index 2469f02..b476a82 100644 --- a/translate/pom.xml +++ b/translate/pom.xml @@ -25,7 +25,7 @@ - 1.1.0 + 1.1.1 translate SmartJavaAI https://github.com/geekwenjie/SmartJavaAI diff --git a/vision/pom.xml b/vision/pom.xml index ed6baf0..225de2f 100644 --- a/vision/pom.xml +++ b/vision/pom.xml @@ -6,11 +6,11 @@ cn.smartjavaai smartjavaai-parent - 1.1.0 + 1.1.1 vision - 1.1.0 + 1.1.1 vision SmartJavaAI https://github.com/geekwenjie/SmartJavaAI diff --git a/vision/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java b/vision/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java index 10a70ab..753b402 100644 --- a/vision/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java +++ b/vision/src/main/java/cn/smartjavaai/objectdetection/criteria/CriteriaBuilderFactory.java @@ -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: diff --git a/vision/src/main/java/cn/smartjavaai/objectdetection/stream/StreamDetector.java b/vision/src/main/java/cn/smartjavaai/objectdetection/stream/StreamDetector.java index 9269bd9..f8ce7f2 100644 --- a/vision/src/main/java/cn/smartjavaai/objectdetection/stream/StreamDetector.java +++ b/vision/src/main/java/cn/smartjavaai/objectdetection/stream/StreamDetector.java @@ -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 lastDetectTime = new ConcurrentHashMap<>(); private BlockingQueue 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 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 filterRepeatedObjects(DetectionResponse response) { - List 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 不能为空");