Jelajahi Sumber

fix:data augmentation

28968 8 bulan lalu
induk
melakukan
7788065889
23 mengubah file dengan 1093 tambahan dan 114 penghapusan
  1. 83 0
      script/sql/postgresql/data(postgresql).sql
  2. 3 4
      taais-admin/src/main/resources/application-dev.yml
  3. 3 4
      taais-admin/src/main/resources/application.yml
  4. 3 1
      taais-common/taais-common-core/src/main/java/com/taais/common/core/utils/file/MimeTypeUtils.java
  5. 10 3
      taais-modules/taais-biz/src/main/java/com/taais/biz/constant/BizConstant.java
  6. 25 9
      taais-modules/taais-biz/src/main/java/com/taais/biz/controller/DataAugmentationController.java
  7. 207 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/controller/ObjectTraceMergeController.java
  8. 24 9
      taais-modules/taais-biz/src/main/java/com/taais/biz/controller/PublicController.java
  9. 8 4
      taais-modules/taais-biz/src/main/java/com/taais/biz/controller/VideoStableController.java
  10. 64 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/domain/ObjectTraceMerge.java
  11. 77 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/domain/bo/ObjectTraceMergeBo.java
  12. 70 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/domain/vo/ObjectTraceMergeImportVo.java
  13. 78 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/domain/vo/ObjectTraceMergeVo.java
  14. 119 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/listener/ObjectTraceMergeImportListener.java
  15. 16 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/mapper/ObjectTraceMergeMapper.java
  16. 66 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/IObjectTraceMergeService.java
  17. 3 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/IVideoStableService.java
  18. 1 1
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/DataSeqServiceImpl.java
  19. 13 64
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/DataServiceImpl.java
  20. 148 0
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/ObjectTraceMergeServiceImpl.java
  21. 6 3
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/TargetIdentificationTaskServiceImpl.java
  22. 1 1
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/TrackSequenceServiceImpl.java
  23. 65 11
      taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/VideoStableServiceImpl.java

+ 83 - 0
script/sql/postgresql/data(postgresql).sql

@@ -1104,3 +1104,86 @@ values(2024081714395204, '目标识别子任务删除', 2024081714395200, '4',
 
 insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
 values(2024081714395205, '目标识别子任务导出', 2024081714395200, '5',  '', '', 1, 0, 'F', '0', '0', 'identification:identificationSubtask:export',       '', 1, now(), 1, null, '');
+
+CREATE TABLE "public"."object_trace_merge" (
+                                                                  "id" "pg_catalog"."int8" NOT NULL,
+                                                                  "name" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
+                                                                  "status" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
+                                                                  "parameters" "pg_catalog"."text" COLLATE "pg_catalog"."default",
+                                                                  "preprocess_path" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
+                                                                  "result_path" "pg_catalog"."varchar" COLLATE "pg_catalog"."default",
+                                                                  "start_time" "pg_catalog"."timestamp",
+                                                                  "end_time" "pg_catalog"."timestamp",
+                                                                  "cost_second" "pg_catalog"."int8",
+                                                                  "create_by" "pg_catalog"."int8",
+                                                                  "create_time" "pg_catalog"."timestamp" DEFAULT CURRENT_TIMESTAMP,
+                                                                  "update_by" "pg_catalog"."int8",
+                                                                  "update_time" "pg_catalog"."timestamp" DEFAULT CURRENT_TIMESTAMP,
+                                                                  "remarks" "pg_catalog"."varchar" COLLATE "pg_catalog"."default" DEFAULT NULL::character varying,
+                                                                  "tenant_id" "pg_catalog"."int8" DEFAULT 0,
+                                                                  version           integer                 DEFAULT 0,
+                                                                  del_flag      smallint               DEFAULT '0'::smallint         NOT NULL,
+                                                                  CONSTRAINT "target_identification_subtask_details_pk" PRIMARY KEY ("id")
+);
+
+ALTER TABLE "public"."object_trace_merge"
+    OWNER TO "postgres";
+
+COMMENT ON COLUMN "public"."object_trace_merge"."id" IS '主键ID';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."name" IS '任务名称';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."status" IS '任务状态';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."parameters" IS '调用算法时所用的参数';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."preprocess_path" IS '预处理数据路径';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."result_path" IS '结果数据路径';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."start_time" IS '开始时间';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."end_time" IS '结束时间';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."cost_second" IS '耗时';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."create_by" IS '创建人';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."create_time" IS '创建时间';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."update_by" IS '更新人';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."update_time" IS '更新时间';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."remarks" IS '备注';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."version" IS '乐观锁';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."tenant_id" IS '租户编码';
+
+COMMENT ON COLUMN "public"."object_trace_merge"."del_flag" IS '逻辑删除标志(0代表存在 1代表删除)';
+
+COMMENT ON TABLE "public"."object_trace_merge" IS '多物体融合轨迹识别';
+
+-- 菜单 SQL
+insert into sys_menu (menu_id, menu_name, order_num, path, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(4, '多目标选择', '1', 'multiObj', 1, 0, 'M', '0', '0', 'demo:traceMerge:list', '', 1, now(), 1, null, '多目标选择');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(2024101614471100, '多物体融合轨迹识别', 4, '1', '/demo/traceMerge', 'demo/traceMerge/index', 1, 0, 'C', '0', '0', 'demo:traceMerge:list', '', 1, now(), 1, null, '多物体融合轨迹识别菜单');
+
+-- 按钮 SQL
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(2024101614471101, '多物体融合轨迹识别查询', 2024101614471100, '1',  '', '', 1, 0, 'F', '0', '0', 'demo:traceMerge:query',        '', 1, now(), 1, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(2024101614471102, '多物体融合轨迹识别新增', 2024101614471100, '2',  '', '', 1, 0, 'F', '0', '0', 'demo:traceMerge:add',          '', 1, now(), 1, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(2024101614471103, '多物体融合轨迹识别修改', 2024101614471100, '3',  '', '', 1, 0, 'F', '0', '0', 'demo:traceMerge:edit',         '', 1, now(), 1, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(2024101614471104, '多物体融合轨迹识别删除', 2024101614471100, '4',  '', '', 1, 0, 'F', '0', '0', 'demo:traceMerge:remove',       '', 1, now(), 1, null, '');
+
+insert into sys_menu (menu_id, menu_name, parent_id, order_num, path, component, is_frame, is_cache, menu_type, visible, status, perms, icon, create_by, create_time, update_by, update_time, remark)
+values(2024101614471105, '多物体融合轨迹识别导出', 2024101614471100, '5',  '', '', 1, 0, 'F', '0', '0', 'demo:traceMerge:export',       '', 1, now(), 1, null, '');

+ 3 - 4
taais-admin/src/main/resources/application-dev.yml

@@ -1,10 +1,9 @@
 server:
+  video_stable_url: http://localhost:11002/video_stable
   video_stable_start_url: http://localhost:11002/video_stable
   video_stable_stop_url: http://localhost:11002/video_stable_stop
-  to_infrared_stop_url: http://localhost:11002/to_infrared_stop
-  track_sequence_stop_url: http://localhost:11003/track_sequence_stop
-  target_detection_stop_url: http://localhost:11003/target_detection_stop
   task_stop_url: http://localhost:11003/stop
+
 # 数据源配置
 spring:
   datasource:
@@ -42,7 +41,7 @@ mybatis-flex:
       #      password: Root@369
       #postgresql数据库
       driver-class-name: org.postgresql.Driver
-      #      url: jdbc:postgresql://localhost:5432/taais?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
+#      url: jdbc:postgresql://localhost:5432/taais?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
       url: jdbc:postgresql://110.41.34.83:5432/taais?useUnicode=true&characterEncoding=utf8&useSSL=true&autoReconnect=true&reWriteBatchedInserts=true
       username: postgres
       password: P3x0LG8jzyHRX59l

+ 3 - 4
taais-admin/src/main/resources/application.yml

@@ -9,11 +9,10 @@ taais:
   # 实例演示开关
   demoEnabled: true
   # 文件路径 示例( Windows配置D:/km/uploadPath,Linux配置 /home/km/uploadPath)
-  profile: D:/taais/uploadPath
-  #profile: /home/ObjectDetection_Web
+  # profile: D:/taais/uploadPath
+  profile: D:/home/ObjectDetection_Web
   # 获取ip地址开关
   addressEnabled: false
-  video_stable_url: http://localhost:11001/video_stable
 
 captcha:
   enable: true
@@ -263,7 +262,7 @@ sa-token:
   timeout: 604800
   # 多端不同 token 有效期 可查看 LoginHelper.loginByDevice 方法自定义
   # token最低活跃时间 (指定时间无操作就过期) 单位: 秒
-  active-timeout: 1800
+  active-timeout: 604800
   # 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
   is-concurrent: true
   # 在多人登录同一账号时,是否共用一个token (为true时所有登录共用一个token, 为false时每次登录新建一个token)

+ 3 - 1
taais-common/taais-common-core/src/main/java/com/taais/common/core/utils/file/MimeTypeUtils.java

@@ -37,7 +37,9 @@ public class MimeTypeUtils {
         // pdf
         "pdf",
         // pt
-        "pt"
+        "pt",
+        // mat
+        "mat"
     };
 
     public static String getExtension(String prefix) {

+ 10 - 3
taais-modules/taais-biz/src/main/java/com/taais/biz/constant/BizConstant.java

@@ -11,6 +11,7 @@ public class BizConstant {
     public static final String PREDICT_PATH = "predict";
 
     public static final String UNZIP_SUFFIX = "_unzip";
+    public static final String STABLE_SUFFIX = "_stable";
     public static final String TO_INFRARED_SUFFIX = "_to_infrared";
     public static final String TRACK_SEQUENCE_SUFFIX = "_track_sequence";
     public static final String TARGET_DETECTION_SUFFIX = "_target_detection";
@@ -106,9 +107,15 @@ public class BizConstant {
     public static final String R_CURVE = "R_curve.png";
     public static final String P_CURVE = "P_curve.png";
     public static final String F1_CURVE = "F1_curve.png";
-    public static final String ORIGINAL_IMAGE = "原始图片";
-    public static final String DOCKER_BASE_PATH = "/home/ObjectDetection_Web";
-    public static final String DOCKER_PT_PATH = "weights/best.pt";
+    public static final String ORIGINAL_IMAGE= "原始图片";
+    public static final String DOCKER_BASE_PATH= "/home/ObjectDetection_Web";
+//    public static final String DOCKER_BASE_PATH= "ObjectDetection_Web";
+    public static final String DOCKER_PT_PATH= "weights/best.pt";
 
     public static final String REMARK_PREFIX = "__URL__";
+
+    public static final String TYPE_OBJ_TRACE = "OBJ_TRACE";
+    public static final String DOCKER_MAT_TASK = DOCKER_BASE_PATH + "/obj_track";
+    public static final String MULTI_OBJ_TRACE_URL = "127.0.0.1:10027/objTrace";
+
 }

+ 25 - 9
taais-modules/taais-biz/src/main/java/com/taais/biz/controller/DataAugmentationController.java

@@ -2,6 +2,7 @@ package com.taais.biz.controller;
 
 
 import java.io.IOException;
+import java.nio.file.DirectoryStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -91,17 +92,29 @@ public class DataAugmentationController extends BaseController {
             System.out.println("inputPath: " + inputPath.toString());
             System.out.println("outputPath: " + outputPath.toString());
             Path imagePath = getImageAtPathIdx(inputPath, idx);
+
             String fileName = imagePath.getFileName().toString();
             Map<String, List<String>> images = new HashMap<>();
-
             //图像拼接算法有多个输入图片
-            if ("图像拼接".equals(dataAugmentation.getTaskType())) {
-
-                Stream<Path> pathStream = Files.list(imagePath);
-                Optional<Path> firstPath = pathStream.filter(Files::isRegularFile).findFirst();
-                String firstFileName = firstPath.get().getFileName().toString();
-                int lastDotIndex = firstFileName.lastIndexOf('.');
-                fileName = fileName + firstFileName.substring(lastDotIndex);
+            if ("图像拼接_sift".equals(dataAugmentation.getTaskType()) || "图像拼接_coordinate".equals(dataAugmentation.getTaskType())) {
+                String lastDirectoryName = imagePath.getFileName().toString();
+                outputPath = outputPath.resolve(lastDirectoryName);  //得到推理结果目录
+                DirectoryStream<Path> stream = Files.newDirectoryStream(outputPath);
+                if (Files.exists(outputPath) && Files.isDirectory(outputPath)) {
+                    if (stream.iterator().hasNext()) {
+                        for (Path entry : stream) {
+                            if (Files.isRegularFile(entry)) {
+                                fileName = entry.getFileName().toString();
+                                break;
+                            }
+                        }
+                    } else {
+                        System.out.println("图像拼接算法未在结果目录下保存结果文件!");
+                    }
+                } else {
+                    System.out.println("图像拼接算法未创建结果目录!");
+                    return ResponseEntity.status(500).build();
+                }
                 // 收集所有文件的路径,并编码为Base64字符串
                 Stream<Path> newPathStream = Files.list(imagePath);
                 List<String> origin = newPathStream
@@ -123,8 +136,11 @@ public class DataAugmentationController extends BaseController {
                 images.put("origin", origin);
             }
             Path resolve = outputPath.resolve(fileName);
+            if (!Files.exists(resolve)) {
+                System.out.println("结果文件不存在:" + resolve.toString());
+                return ResponseEntity.status(500).build();
+            }
             byte[] image2 = Files.readAllBytes(resolve);
-
             String base64Image2 = Base64.getEncoder().encodeToString(image2);   // 将图片编码成Base64字符串
             ArrayList<String> stable = new ArrayList<>();
             stable.add(base64Image2);

+ 207 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/controller/ObjectTraceMergeController.java

@@ -0,0 +1,207 @@
+package com.taais.biz.controller;
+
+import java.io.File;
+import java.util.*;
+
+import cn.hutool.http.HttpUtil;
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import com.taais.biz.constant.BizConstant;
+import com.taais.biz.domain.ObjectTraceMerge;
+import com.taais.biz.domain.bo.ObjectTraceMergeBo;
+import com.taais.biz.domain.vo.ObjectTraceMergeVo;
+import com.taais.biz.service.IObjectTraceMergeService;
+import com.taais.biz.service.impl.ObjectTraceMergeServiceImpl;
+import com.taais.common.core.utils.MapstructUtils;
+import com.taais.common.core.utils.uuid.UUID;
+import lombok.RequiredArgsConstructor;
+import jakarta.servlet.http.HttpServletResponse;
+import cn.dev33.satoken.annotation.SaCheckPermission;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.validation.annotation.Validated;
+import com.taais.common.core.core.domain.CommonResult;
+import com.taais.common.excel.utils.ExcelUtil;
+import com.taais.common.log.annotation.Log;
+import com.taais.common.log.enums.BusinessType;
+import com.taais.common.web.annotation.RepeatSubmit;
+import com.taais.common.web.core.BaseController;
+import jakarta.annotation.Resource;
+
+import com.taais.common.core.core.page.PageResult;
+
+import static com.taais.biz.constant.BizConstant.*;
+
+/**
+ * 多物体融合轨迹识别Controller
+ *
+ * @author km
+ * 2024-10-16
+ */
+@Validated
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/demo/traceMerge")
+public class ObjectTraceMergeController extends BaseController {
+    @Resource
+    private ObjectTraceMergeServiceImpl objectTraceMergeService;
+
+    /**
+     * 查询多物体融合轨迹识别列表
+     */
+    @SaCheckPermission("demo:traceMerge:list")
+    @GetMapping("/list")
+    public CommonResult<PageResult<ObjectTraceMergeVo>> list(ObjectTraceMergeBo objectTraceMergeBo) {
+        return CommonResult.success(objectTraceMergeService.selectPage(objectTraceMergeBo));
+    }
+
+    /**
+     * 导出多物体融合轨迹识别列表
+     */
+    @SaCheckPermission("demo:traceMerge:export")
+    @Log(title = "多物体融合轨迹识别", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, ObjectTraceMergeBo objectTraceMergeBo) {
+        List<ObjectTraceMergeVo> list = objectTraceMergeService.selectList(objectTraceMergeBo);
+        ExcelUtil.exportExcel(list, "多物体融合轨迹识别", ObjectTraceMergeVo.class, response);
+    }
+
+    /**
+     * 获取多物体融合轨迹识别详细信息
+     */
+    @SaCheckPermission("demo:traceMerge:query")
+    @GetMapping(value = "/{id}")
+    public CommonResult<ObjectTraceMergeVo> getInfo(@PathVariable Long id) {
+        return CommonResult.success(objectTraceMergeService.selectById(id));
+    }
+
+
+    /**
+     * 新增多物体融合轨迹识别
+     */
+    @SaCheckPermission("demo:traceMerge:add")
+    @Log(title = "多物体融合轨迹识别", businessType = BusinessType.INSERT)
+    @RepeatSubmit()
+    @PostMapping
+    public CommonResult<Void> add(@Validated @RequestBody ObjectTraceMergeBo objectTraceMergeBo) {
+        String uuid = UUID.randomUUID().toString();
+        String resultPath = DOCKER_MAT_TASK + "/" + uuid;
+        objectTraceMergeBo.setResultPath(resultPath);
+        objectTraceMergeBo.setStatus(TASK_STATUS_PENDING);
+        objectTraceMergeBo.setPreprocessPath(objectTraceMergeBo.getPreprocessPath().replace("/profile", DOCKER_BASE_PATH));
+        boolean inserted = objectTraceMergeService.insert(objectTraceMergeBo);
+        if (!inserted) {
+            return CommonResult.fail("新增多物体融合轨迹识别记录失败!");
+        }
+        // 创建结果路径
+        try {
+            File dir = new File(resultPath);
+            if (!dir.exists()) {
+                dir.mkdirs();
+            }
+        } catch (Exception e) {
+            return CommonResult.fail("创建结果路径失败!");
+        }
+
+        return CommonResult.success();
+    }
+
+    @PostMapping("/execute")
+    public CommonResult<Void> execute(@RequestBody Map<String, String> _params) {
+        if (!_params.containsKey("taskId")) {
+            return CommonResult.fail("请提供任务ID!");
+        }
+        String taskId = _params.get("taskId");
+        ObjectTraceMergeBo vo = objectTraceMergeService.getById(Long.valueOf(taskId));
+        if (vo == null) {
+            return CommonResult.fail("未找到任务内容!");
+        }
+        if (TASK_STATUS_SUCCEED.equals(vo.getStatus())) {
+            return CommonResult.fail("任务已经执行完毕!");
+        }
+        if (!(TASK_STATUS_PENDING.equals(vo.getStatus()) || TASK_STATUS_FAILED.equals(vo.getStatus()))) {
+            return CommonResult.fail("任务正在执行中!");
+        }
+        vo.setStartTime(new Date());
+
+        Map<String, String> params = new HashMap<>();
+        params.put("bizType", TYPE_OBJ_TRACE);
+        params.put("bizId", String.valueOf(vo.getId()));
+        params.put("logPath", vo.getResultPath());
+        params.put("sourcePath", vo.getPreprocessPath());
+        params.put("resultPath", vo.getResultPath());
+        params.put("otherParams", new JSONObject().toString());
+
+        try {
+            String res = HttpUtil.post(MULTI_OBJ_TRACE_URL, JSONUtil.toJsonStr(params));
+            vo.setStatus(TASK_STATUS_PROCESSING);
+        } catch (Exception e) {
+            vo.setStatus(TASK_STATUS_FAILED);
+            return CommonResult.fail("HTTP请求失败" + e.getMessage());
+        } finally {
+            objectTraceMergeService.update(vo);
+        }
+        return CommonResult.success();
+    }
+
+    @GetMapping("/result")
+    public CommonResult<List<String>> execute(String taskId) {
+        if (taskId == null) {
+            return CommonResult.fail("请提供任务ID!", new ArrayList<>());
+        }
+        ObjectTraceMergeBo bo = objectTraceMergeService.getById(Long.valueOf(taskId));
+        if (bo == null) {
+            return CommonResult.fail("无法查找到任务!", new ArrayList<>());
+        }
+//        if (!TASK_STATUS_SUCCEED.equals(bo.getStatus())) {
+//            return CommonResult.fail("任务未成功执行!", new ArrayList<>());
+//        }
+        try {
+            String res = bo.getResultPath();
+            File dir = new File(res);
+            File[] files = dir.listFiles();
+            List<String> resList = new ArrayList<>();
+            int maxNum = -1;
+            for (File _file: files) {
+                if (_file.getName().contains("number")) {
+                    maxNum = Math.max(maxNum, Integer.parseInt(_file.getName()
+                        .replace("number", "")
+                        .replace(".png", "")
+                    ));
+                }
+            }
+            resList.add(String.valueOf(maxNum));
+            return CommonResult.success(resList);
+        } catch (Exception e) {
+            return CommonResult.fail("查找结果失败!", new ArrayList<>());
+        }
+    }
+
+    /**
+     * 修改多物体融合轨迹识别
+     */
+    @SaCheckPermission("demo:traceMerge:edit")
+    @Log(title = "多物体融合轨迹识别", businessType = BusinessType.UPDATE)
+    @RepeatSubmit()
+    @PutMapping
+    public CommonResult<Void> edit(@Validated @RequestBody ObjectTraceMergeBo objectTraceMergeBo) {
+        Boolean updated = objectTraceMergeService.update(objectTraceMergeBo);
+        if (!updated) {
+            return CommonResult.fail("修改多物体融合轨迹识别记录失败!");
+        }
+        return CommonResult.success();
+    }
+
+    /**
+     * 删除多物体融合轨迹识别
+     */
+    @SaCheckPermission("demo:traceMerge:remove")
+    @Log(title = "多物体融合轨迹识别", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public CommonResult<Void> remove(@PathVariable Long[] ids) {
+        boolean deleted = objectTraceMergeService.deleteByIds(ids);
+        if (!deleted) {
+            return CommonResult.fail("删除多物体融合轨迹识别记录失败!");
+        }
+        return CommonResult.success();
+    }
+}

+ 24 - 9
taais-modules/taais-biz/src/main/java/com/taais/biz/controller/PublicController.java

@@ -4,6 +4,7 @@ import com.alibaba.fastjson2.JSON;
 import com.taais.biz.constant.BizConstant;
 import com.taais.biz.domain.TaskTrackResultBo;
 import com.taais.biz.domain.bo.AlgorithmModelBo;
+import com.taais.biz.domain.bo.ObjectTraceMergeBo;
 import com.taais.biz.domain.bo.TargetIdentificationSubtaskDetailsBo;
 import com.taais.biz.domain.bo.ToInfraredBo;
 import com.taais.biz.domain.bo.ToInfraredStartResultBo;
@@ -11,6 +12,7 @@ import com.taais.biz.domain.bo.VideoStableStartResultBo;
 import com.taais.biz.domain.dto.TaskResultDTO;
 import com.taais.biz.service.*;
 import com.taais.biz.service.impl.AlgorithmModelServiceImpl;
+import com.taais.biz.service.impl.ObjectTraceMergeServiceImpl;
 import com.taais.biz.service.impl.TargetIdentificationSubtaskDetailsServiceImpl;
 import com.taais.common.core.core.domain.CommonResult;
 import com.taais.common.log.annotation.Log;
@@ -64,6 +66,9 @@ public class PublicController extends BaseController {
     @Resource
     AlgorithmModelServiceImpl algorithmModelService;
 
+    @Resource
+    ObjectTraceMergeServiceImpl objectTraceMergeService;
+
 
 
     // todo: 2024080906
@@ -76,14 +81,15 @@ public class PublicController extends BaseController {
             return CommonResult.fail(errorMsg);
         }
         String bizType = resultDTO.getBizType();
-        if (BizConstant.TYPE_DATA_BIZ_PROCESS.equals(bizType)) {
-            // errorMsg = bizProcessService.taskResult(resultDTO);
+
+        if(BizConstant.TYPE_DATA_BIZ_PROCESS.equals(bizType)){
+            //errorMsg = bizProcessService.taskResult(resultDTO);
             TargetIdentificationSubtaskDetailsBo detailsBo = detailsService.getById(resultDTO.getBizId());
             detailsBo.setStatus(resultDTO.getStatus() != 200 ? BizConstant.TASK_STATUS_FAILED :
                 resultDTO.getMsg().contains("finish") ? BizConstant.TASK_STATUS_SUCCEED : BizConstant.TASK_STATUS_PROCESSING);
             detailsBo.setRemarks(JSON.toJSONString(Arrays.asList(resultDTO.getMin(), resultDTO.getMax(), resultDTO.getAverage())));
             detailsBo.setEndTime(new Date());
-            detailsBo.setCostSecond(detailsBo.getEndTime().getTime() - detailsBo.getStartTime().getTime());
+            detailsBo.setCostSecond((detailsBo.getEndTime().getTime() - detailsBo.getStartTime().getTime()) / 1000);
             detailsService.update(detailsBo);
 
             // 保存模型
@@ -95,14 +101,23 @@ public class PublicController extends BaseController {
                 bo.setModelName(detailsBo.getName() + "_" + detailsBo.getCreateTime().toString());
                 algorithmModelService.insert(bo);
             }
+        } else if (BizConstant.TYPE_OBJ_TRACE.equals(bizType)){
+            ObjectTraceMergeBo bo = objectTraceMergeService.getById(resultDTO.getBizId());
+            if (bo == null) {
+                return CommonResult.fail("bo为null");
+            }
+            bo.setEndTime(new Date());
+            bo.setCostSecond((bo.getEndTime().getTime() - bo.getStartTime().getTime()) / 1000);
+            bo.setStatus(resultDTO.getStatus() == 200 ? BizConstant.TASK_STATUS_SUCCEED : BizConstant.TASK_STATUS_FAILED);
+            objectTraceMergeService.update(bo);
         } else if (BizConstant.TYPE_DATA_PROCESS.equals(bizType)) {
             errorMsg = dataProcessService.taskResult(resultDTO);
         } else {
-            log.error("这种情况是不可能发生的,参数:{}", resultDTO);
+            log.error("这种情况是不可能发生的,参数:{}",resultDTO);
             return CommonResult.fail("这种情况是不可能发生的");
         }
 
-        if (StringUtils.isNotEmpty(errorMsg)) {
+        if(StringUtils.isNotEmpty(errorMsg)){
             return CommonResult.fail(errorMsg);
         }
         return CommonResult.success();
@@ -110,16 +125,16 @@ public class PublicController extends BaseController {
 
     private String checkDTO(TaskResultDTO resultDTO) {
         Integer status = resultDTO.getStatus();
-        if (status != 200 && status != 500) {
+        if(status != 200 && status != 500){
             return "status 只能是200或500";
         }
         Long bizId = resultDTO.getBizId();
-        if (bizId == null) {
+        if(bizId == null){
             return "bizId 不能为null";
         }
         String bizType = resultDTO.getBizType();
-        if (!BizConstant.TYPE_DATA_BIZ_PROCESS.equals(bizType) && !BizConstant.TYPE_DATA_PROCESS.equals(bizType)) {
-            return "status 只能是" + BizConstant.TYPE_DATA_BIZ_PROCESS + "或" + BizConstant.TYPE_DATA_PROCESS;
+        if(!BizConstant.TYPE_OBJ_TRACE.equals(bizType) && !BizConstant.TYPE_DATA_BIZ_PROCESS.equals(bizType) && !BizConstant.TYPE_DATA_PROCESS.equals(bizType)){
+            return "status 只能是"+BizConstant.TYPE_DATA_BIZ_PROCESS+"或"+BizConstant.TYPE_DATA_PROCESS;
         }
         return null;
     }

+ 8 - 4
taais-modules/taais-biz/src/main/java/com/taais/biz/controller/VideoStableController.java

@@ -54,7 +54,6 @@ public class VideoStableController extends BaseController {
     }
 
 
-
     @GetMapping("/compare/{task_id}/{idx}")
     public ResponseEntity<Map<String, String>> getCompareImages(@PathVariable("task_id") Long taskId, @PathVariable("idx") int idx) {
         try {
@@ -68,8 +67,8 @@ public class VideoStableController extends BaseController {
 //                inputPath = Paths.get("C:", videoStable.getInputPath());
 //                outputPath = Paths.get("C:", videoStable.getOutputPath());
 //            } else {
-                inputPath = Paths.get(videoStable.getInputPath());
-                outputPath = Paths.get(videoStable.getOutputPath());
+            inputPath = Paths.get(videoStable.getInputPath());
+            outputPath = Paths.get(videoStable.getOutputPath());
 //            }
             System.out.println("inputPath: " + inputPath.toString());
             System.out.println("outputPath: " + outputPath.toString());
@@ -105,7 +104,7 @@ public class VideoStableController extends BaseController {
         return videoStableService.start(id);
     }
 
-        @GetMapping("/stop/{id}")
+    @GetMapping("/stop/{id}")
     public CommonResult stop(@PathVariable("id") Long id) {
         return videoStableService.stop(id);
     }
@@ -182,4 +181,9 @@ public class VideoStableController extends BaseController {
         }
         return CommonResult.success();
     }
+
+    @GetMapping("/images/{ossId}")
+    public CommonResult<List<Map<String, String>>> getImages(@PathVariable("ossId") Long ossId) {
+        return CommonResult.success(videoStableService.getImages(ossId));
+    }
 }

+ 64 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/domain/ObjectTraceMerge.java

@@ -0,0 +1,64 @@
+package com.taais.biz.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.mybatisflex.annotation.Column;
+import com.mybatisflex.annotation.Id;
+import com.mybatisflex.annotation.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serial;
+import com.taais.common.orm.core.domain.BaseEntity;
+
+/**
+ * 多物体融合轨迹识别对象 object_trace_merge
+ *
+ * @author km
+ * 2024-10-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(value = "object_trace_merge")
+public class ObjectTraceMerge extends BaseEntity
+    {
+@Serial
+private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    @Id
+    private Long id;
+
+    /** 任务名称 */
+    private String name;
+
+    /** 任务状态 */
+    private String status;
+
+    /** 调用算法时所用的参数 */
+    private String parameters;
+
+    /** 预处理数据路径 */
+    private String preprocessPath;
+
+    /** 结果数据路径 */
+    private String resultPath;
+
+    /** 开始时间 */
+    private Date startTime;
+
+    /** 结束时间 */
+    private Date endTime;
+
+    /** 耗时 */
+    private Long costSecond;
+
+    /** 备注 */
+    private String remarks;
+
+    /** 逻辑删除标志(0代表存在 1代表删除) */
+    @Column(isLogicDelete = true)
+    private Integer delFlag;
+
+
+}

+ 77 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/domain/bo/ObjectTraceMergeBo.java

@@ -0,0 +1,77 @@
+package com.taais.biz.domain.bo;
+
+import com.taais.biz.domain.ObjectTraceMerge;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import jakarta.validation.constraints.*;
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.taais.common.orm.core.domain.BaseEntity;
+
+/**
+ * 多物体融合轨迹识别业务对象 object_trace_merge
+ *
+ * @author km
+ * @date 2024-10-16
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ObjectTraceMerge.class, reverseConvertGenerate = false)
+public class ObjectTraceMergeBo extends BaseEntity{
+    /**
+     * 主键ID
+     */
+    private Long id;
+
+    /**
+     * 任务名称
+     */
+    @NotBlank(message = "任务名称不能为空")
+    private String name;
+
+    /**
+     * 任务状态
+     */
+    private String status;
+
+    /**
+     * 调用算法时所用的参数
+     */
+    private String parameters;
+
+    /**
+     * 预处理数据路径
+     */
+    @NotBlank(message = "预处理数据路径不能为空")
+    private String preprocessPath;
+
+    /**
+     * 结果数据路径
+     */
+    private String resultPath;
+
+    /**
+     * 开始时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date startTime;
+
+    /**
+     * 结束时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd")
+    private Date endTime;
+
+    /**
+     * 耗时
+     */
+    private Long costSecond;
+
+    /**
+     * 备注
+     */
+    private String remarks;
+
+
+}

+ 70 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/domain/vo/ObjectTraceMergeImportVo.java

@@ -0,0 +1,70 @@
+package com.taais.biz.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.taais.common.excel.annotation.ExcelDictFormat;
+import com.taais.common.excel.convert.ExcelDictConvert;
+import lombok.Data;
+import java.io.Serial;
+import java.io.Serializable;
+import lombok.NoArgsConstructor;
+
+/**
+ * 多物体融合轨迹识别导入视图对象 object_trace_merge
+ *
+ * @author km
+ * @date 2024-10-16
+ */
+
+@Data
+@NoArgsConstructor
+public class ObjectTraceMergeImportVo implements Serializable
+{
+
+    @Serial
+    private static final long serialVersionUID = 1L;
+
+
+     /** 任务名称 */
+    @ExcelProperty(value = "任务名称")
+    private String name;
+
+     /** 任务状态 */
+    @ExcelProperty(value = "任务状态")
+    private String status;
+
+     /** 调用算法时所用的参数 */
+    @ExcelProperty(value = "调用算法时所用的参数")
+    private String parameters;
+
+     /** 预处理数据路径 */
+    @ExcelProperty(value = "预处理数据路径")
+    private String preprocessPath;
+
+     /** 结果数据路径 */
+    @ExcelProperty(value = "结果数据路径")
+    private String resultPath;
+
+     /** 开始时间 */
+    @ExcelProperty(value = "开始时间")
+    private Date startTime;
+
+     /** 结束时间 */
+    @ExcelProperty(value = "结束时间")
+    private Date endTime;
+
+     /** 耗时 */
+    @ExcelProperty(value = "耗时")
+    private Long costSecond;
+
+     /** 备注 */
+    @ExcelProperty(value = "备注")
+    private String remarks;
+
+     /** 逻辑删除标志(0代表存在 1代表删除) */
+    @ExcelProperty(value = "逻辑删除标志(0代表存在 1代表删除)")
+    private Integer delFlag;
+
+
+}

+ 78 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/domain/vo/ObjectTraceMergeVo.java

@@ -0,0 +1,78 @@
+package com.taais.biz.domain.vo;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
+import com.taais.biz.domain.ObjectTraceMerge;
+import com.taais.common.excel.annotation.ExcelDictFormat;
+import com.taais.common.excel.convert.ExcelDictConvert;
+import io.github.linpeilie.annotations.AutoMapper;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.io.Serial;
+import java.io.Serializable;
+import com.taais.common.orm.core.domain.BaseEntity;
+
+/**
+ * 多物体融合轨迹识别视图对象 object_trace_merge
+ *
+ * @author km
+ * @date 2024-10-16
+ */
+@Data
+@ExcelIgnoreUnannotated
+@EqualsAndHashCode(callSuper = true)
+@AutoMapper(target = ObjectTraceMerge.class)
+public class ObjectTraceMergeVo extends BaseEntity implements Serializable {
+
+@Serial
+private static final long serialVersionUID = 1L;
+
+    /** 主键ID */
+    @ExcelProperty(value = "主键ID")
+    private Long id;
+
+    /** 任务名称 */
+    @ExcelProperty(value = "任务名称")
+    private String name;
+
+    /** 任务状态 */
+    @ExcelProperty(value = "任务状态")
+    private String status;
+
+    /** 调用算法时所用的参数 */
+    @ExcelProperty(value = "调用算法时所用的参数")
+    private String parameters;
+
+    /** 预处理数据路径 */
+    @ExcelProperty(value = "预处理数据路径")
+    private String preprocessPath;
+
+    /** 结果数据路径 */
+    @ExcelProperty(value = "结果数据路径")
+    private String resultPath;
+
+    /** 开始时间 */
+    @ExcelProperty(value = "开始时间")
+    private Date startTime;
+
+    /** 结束时间 */
+    @ExcelProperty(value = "结束时间")
+    private Date endTime;
+
+    /** 耗时 */
+    @ExcelProperty(value = "耗时")
+    private Long costSecond;
+
+    /** 备注 */
+    @ExcelProperty(value = "备注")
+    private String remarks;
+
+    /** 逻辑删除标志(0代表存在 1代表删除) */
+    @ExcelProperty(value = "逻辑删除标志(0代表存在 1代表删除)")
+    private Integer delFlag;
+
+
+
+}

+ 119 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/listener/ObjectTraceMergeImportListener.java

@@ -0,0 +1,119 @@
+package com.taais.biz.listener;
+
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.excel.context.AnalysisContext;
+import com.alibaba.excel.event.AnalysisEventListener;
+import com.taais.biz.domain.bo.ObjectTraceMergeBo;
+import com.taais.biz.domain.vo.ObjectTraceMergeImportVo;
+import com.taais.biz.domain.vo.ObjectTraceMergeVo;
+import com.taais.biz.service.IObjectTraceMergeService;
+import com.taais.common.core.exception.ServiceException;
+import com.taais.common.core.utils.SpringUtils;
+import com.taais.common.core.utils.ValidatorUtils;
+import com.taais.common.excel.core.ExcelListener;
+import com.taais.common.excel.core.ExcelResult;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.List;
+
+/**
+ * 多物体融合轨迹识别自定义导入
+ *
+ * @author km
+ */
+@Slf4j
+public class ObjectTraceMergeImportListener extends AnalysisEventListener<ObjectTraceMergeImportVo> implements ExcelListener<ObjectTraceMergeImportVo> {
+    private final IObjectTraceMergeService objectTraceMergeService;
+
+    private final Boolean isUpdateSupport;
+    private int successNum = 0;
+    private int failureNum = 0;
+    private final StringBuilder successMsg = new StringBuilder();
+    private final StringBuilder failureMsg = new StringBuilder();
+
+    public ObjectTraceMergeImportListener(Boolean isUpdateSupport) {
+        this.objectTraceMergeService = SpringUtils.getBean(IObjectTraceMergeService.class);
+        this.isUpdateSupport = isUpdateSupport;
+    }
+
+    @Override
+    public void invoke(ObjectTraceMergeImportVo objectTraceMergeVo, AnalysisContext context) {
+        try {
+
+            ObjectTraceMergeBo objectTraceMergeBo = BeanUtil.toBean(objectTraceMergeVo, ObjectTraceMergeBo.class);
+
+            //TODO:根据某个字段,查询数据库表中是否存在记录,不存在就新增,存在就更新
+            ObjectTraceMergeVo objectTraceMergeVo1 = null;
+
+            //objectTraceMergeVo1 = objectTraceMergeService.selectBySomefield(objectTraceMergeVo.getSomefield());
+            if (ObjectUtil.isNull(objectTraceMergeVo1)) {
+                //不存在就新增
+                objectTraceMergeBo.setVersion(0);
+                ValidatorUtils.validate(objectTraceMergeBo);
+                boolean inserted = objectTraceMergeService.insert(objectTraceMergeBo);
+
+                if (inserted) {
+                    successNum++;
+                    successMsg.append("<br/>").append(successNum).append("、多物体融合轨迹识别 记录导入成功");
+                    return;
+                } else {
+                    failureNum++;
+                    failureMsg.append("<br/>").append(failureNum).append("、多物体融合轨迹识别 记录导入失败");
+                    return;
+                }
+            } else if (isUpdateSupport) {
+                //存在就更新
+                objectTraceMergeBo.setId(objectTraceMergeVo1.getId());//主键
+                objectTraceMergeBo.setVersion(objectTraceMergeVo1.getVersion());
+                boolean updated = objectTraceMergeService.update(objectTraceMergeBo);
+                if (updated) {
+                    successNum++;
+                    successMsg.append("<br/>").append(successNum).append("、多物体融合轨迹识别 记录更新成功");
+                    return;
+                } else {
+                    failureNum++;
+                    failureMsg.append("<br/>").append(failureNum).append("、多物体融合轨迹识别 记录更新失败");
+                    return;
+                }
+            }
+        } catch (Exception e) {
+            failureNum++;
+            String msg = "<br/>" + failureNum + "、多物体融合轨迹识别 记录导入失败:";
+            failureMsg.append(msg).append(e.getMessage());
+            log.error(msg, e);
+        }
+    }
+
+    @Override
+    public void doAfterAllAnalysed(AnalysisContext context) {
+
+    }
+
+    @Override
+    public ExcelResult<ObjectTraceMergeImportVo> getExcelResult() {
+        return new ExcelResult<>() {
+
+            @Override
+            public String getAnalysis() {
+                if (failureNum > 0) {
+                    failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据没有成功导入,错误如下:");
+                    throw new ServiceException(failureMsg.toString());
+                } else {
+                    successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+                }
+                return successMsg.toString();
+            }
+
+            @Override
+            public List<ObjectTraceMergeImportVo> getList() {
+                return null;
+            }
+
+            @Override
+            public List<String> getErrorList() {
+                return null;
+            }
+        };
+    }
+}

+ 16 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/mapper/ObjectTraceMergeMapper.java

@@ -0,0 +1,16 @@
+package com.taais.biz.mapper;
+
+import com.mybatisflex.core.BaseMapper;
+import com.taais.biz.domain.ObjectTraceMerge;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * 多物体融合轨迹识别Mapper接口
+ *
+ * @author km
+ * 2024-10-16
+ */
+@Mapper
+public interface ObjectTraceMergeMapper extends BaseMapper<ObjectTraceMerge> {
+
+}

+ 66 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/service/IObjectTraceMergeService.java

@@ -0,0 +1,66 @@
+package com.taais.biz.service;
+
+import java.util.List;
+
+import com.taais.biz.domain.ObjectTraceMerge;
+import com.taais.biz.domain.bo.ObjectTraceMergeBo;
+import com.taais.biz.domain.vo.ObjectTraceMergeVo;
+import com.taais.common.orm.core.service.IBaseService;
+import com.taais.common.core.core.page.PageResult;
+
+/**
+ * 多物体融合轨迹识别Service接口
+ *
+ * @author km
+ * 2024-10-16
+ */
+public interface IObjectTraceMergeService extends IBaseService<ObjectTraceMerge> {
+    /**
+     * 查询多物体融合轨迹识别
+     *
+     * @param id 多物体融合轨迹识别主键
+     * @return 多物体融合轨迹识别
+     */
+        ObjectTraceMergeVo selectById(Long id);
+
+    /**
+     * 查询多物体融合轨迹识别列表
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 多物体融合轨迹识别集合
+     */
+    List<ObjectTraceMergeVo> selectList(ObjectTraceMergeBo objectTraceMergeBo);
+
+    /**
+     * 分页查询多物体融合轨迹识别列表
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 分页多物体融合轨迹识别集合
+     */
+    PageResult<ObjectTraceMergeVo> selectPage(ObjectTraceMergeBo objectTraceMergeBo);
+
+    /**
+     * 新增多物体融合轨迹识别
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 结果:true 操作成功,false 操作失败
+     */
+    boolean insert(ObjectTraceMergeBo objectTraceMergeBo);
+
+    /**
+     * 修改多物体融合轨迹识别
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 结果:true 更新成功,false 更新失败
+     */
+    boolean update(ObjectTraceMergeBo objectTraceMergeBo);
+
+    /**
+     * 批量删除多物体融合轨迹识别
+     *
+     * @param ids 需要删除的多物体融合轨迹识别主键集合
+     * @return 结果:true 删除成功,false 删除失败
+     */
+    boolean deleteByIds(Long[] ids);
+
+}

+ 3 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/service/IVideoStableService.java

@@ -1,6 +1,7 @@
 package com.taais.biz.service;
 
 import java.util.List;
+import java.util.Map;
 
 import com.taais.biz.domain.VideoStable;
 import com.taais.biz.domain.bo.VideoStableStartResultBo;
@@ -72,4 +73,6 @@ public interface IVideoStableService extends IBaseService<VideoStable> {
     Object getCompareNum(Long taskId);
 
     CommonResult stop(Long id);
+
+    List<Map<String, String>> getImages(Long ossId);
 }

+ 1 - 1
taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/DataSeqServiceImpl.java

@@ -253,7 +253,7 @@ public class DataSeqServiceImpl extends BaseServiceImpl<DataSeqMapper, DataSeq>
     };
 
     // 判断文件是否为常见图片格式
-    private static boolean isImageFile(File file) {
+    public static boolean isImageFile(File file) {
         if (file.isDirectory()) {
             return false;
         }

+ 13 - 64
taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/DataServiceImpl.java

@@ -1,4 +1,5 @@
 package com.taais.biz.service.impl;
+import java.util.Date;
 
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.http.HttpRequest;
@@ -279,70 +280,16 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
     @Override
     @Transactional
     public CommonResult<Boolean> dataAmplify(DataAmplifyDto dataAmplifyDto) {
-        //根据批次号获取该批次的所有文件数据
-        QueryWrapper query = query();
-        query.eq(Data::getBatchNum, dataAmplifyDto.getBatchNum());
-        List<Data> dataList = dataMapper.selectListByQuery(query);
-        if (dataList.isEmpty()) {
-            return CommonResult.fail("该批次下没有文件数据,请重新选择批次!");
-        }
-
-        List<Data> dataListInfo = dataList.stream().filter(data -> !StringUtils.isEmpty(data.getUrl())).toList();
-        if (dataListInfo.isEmpty()) {
-            return CommonResult.fail("该批次下没有文件数据,请重新选择批次!");
-        }
-        String filePath = TaaisConfig.getUploadPath();
-        LocalDate currentDate = LocalDate.now();
-        // 定义日期格式器
-        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
-        String formattedDate = currentDate.format(formatter);
-        filePath = filePath + File.separator + formattedDate;
-        String finalFilePath = filePath;
-        Date startTime = new Date();
-        AtomicBoolean success = new AtomicBoolean(true);
-        AtomicReference<String> message = new AtomicReference<>("");
-        dataListInfo.forEach(dataInfo -> {
-            try {
-                //循环调用Python扩增接口
-                Map<String, Object> bodyJson = new HashMap<>();
-                bodyJson.put("augmentationType", dataAmplifyDto.getAugmentationType());
-                bodyJson.put("inputImagePath", dataInfo.getUrl());
-                String outputImagePath = finalFilePath + AMPLIFY + System.currentTimeMillis();
-                File desc = new File(outputImagePath);
-                if (!desc.exists()) {
-                    log.info("创建文件目录: {}", desc.mkdirs());
-                }
-                bodyJson.put("outputImagePath", outputImagePath);
-                bodyJson.put("otherParams", dataAmplifyDto.getOtherParams());
-                //实际请求接口,接口未提供,暂且注释
-                String response = HttpRequest.post(PYTHON_DATA_AMPLIFY_API)
-                    .body(JsonUtils.toJsonString(bodyJson))
-                    .execute().body();
-//                String response = "{\"status\":200,\"msg\":\"扩增成功\"}";
-                ObjectMapper objectMapper = new ObjectMapper();
-                JsonNode rootNode = objectMapper.readTree(response);
-                String resultCode = rootNode.path(RESULT_CODE).asText();
-                //判断接口是否响应成功
-                if (!RESULT_STATUS.equals(resultCode)) {
-                    success.set(true);
-                }
-                message.set(rootNode.path("msg").asText());
-                //处理当前目录文件,并进行入库
-                saveDataInfo(outputImagePath, dataInfo);
-            } catch (Exception e) {
-                throw new RuntimeException(e);
-            }
-        });
-        Date endTime = new Date();
-        DataAmplificationTaskBo update = new DataAmplificationTaskBo();
-        update.setId(Long.valueOf(dataAmplifyDto.getId()));
-        update.setStartTime(startTime);
-        update.setEndTime(endTime);
-        update.setCostSecond((int) (endTime.getTime() - startTime.getTime()));
-        update.setStatus(success.get() ? BizConstant.TASK_STATUS_SUCCEED : BizConstant.TASK_STATUS_FAILED);
-        update.setLog(message.get());
-        dataAmplificationTaskService.update(update);
-        return CommonResult.fail("该批次下没有文件数据,请重新选择批次!");
+        DataAmplifyDto amplifyDto = new DataAmplifyDto();
+        DataAmplificationTaskBo dataAmplificationTaskBo = new DataAmplificationTaskBo();
+        dataAmplificationTaskBo.setName(amplifyDto.getTaskName());
+        dataAmplificationTaskBo.setStatus(BizConstant.TASK_STATUS_PENDING);
+        dataAmplificationTaskBo.setDataBatchNums(amplifyDto.getBatchNum());
+        dataAmplificationTaskBo.setAugmentationType(amplifyDto.getAugmentationType());
+        dataAmplificationTaskBo.setParameters(JsonUtils.toJsonString(amplifyDto.getOtherParams()));
+        dataAmplificationTaskBo.setDelFlag(0);
+        dataAmplificationTaskService.insert(dataAmplificationTaskBo);
+        return this.amplifyForData(dataAmplificationTaskBo.getId().toString());
     }
 
     private void initFileInfo(String dest, List<File> extractedImagesFileList, boolean directory, String fileName) {
@@ -414,6 +361,8 @@ public class DataServiceImpl extends BaseServiceImpl<DataMapper, Data> implement
     public boolean update(DataBo dataBo) {
         Data data = MapstructUtils.convert(dataBo, Data.class);
         if (ObjectUtil.isNotNull(data) && ObjectUtil.isNotNull(data.getId())) {
+            // 不更新采集时间
+            data.setGatherTime(null);
             boolean updated = this.updateById(data);
             //新增之后清除缓存
             deleteFormSelectKey();

+ 148 - 0
taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/ObjectTraceMergeServiceImpl.java

@@ -0,0 +1,148 @@
+package com.taais.biz.service.impl;
+
+import java.util.Arrays;
+import java.util.List;
+
+import cn.hutool.core.util.ObjectUtil;
+import com.mybatisflex.core.paginate.Page;
+import com.mybatisflex.core.query.QueryWrapper;
+import com.taais.biz.domain.ObjectTraceMerge;
+import com.taais.biz.domain.bo.ObjectTraceMergeBo;
+import com.taais.biz.domain.bo.TargetIdentificationSubtaskDetailsBo;
+import com.taais.biz.domain.vo.ObjectTraceMergeVo;
+import com.taais.biz.mapper.ObjectTraceMergeMapper;
+import com.taais.biz.service.IObjectTraceMergeService;
+import com.taais.common.core.utils.MapstructUtils;
+import com.taais.common.core.utils.StringUtils;
+import com.taais.common.orm.core.page.PageQuery;
+import com.taais.common.core.core.page.PageResult;
+import com.taais.common.orm.core.service.impl.BaseServiceImpl;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import static com.taais.biz.domain.table.ObjectTraceMergeTableDef.OBJECT_TRACE_MERGE;
+import static com.taais.biz.domain.table.TargetIdentificationSubtaskDetailsTableDef.TARGET_IDENTIFICATION_SUBTASK_DETAILS;
+
+/**
+ * 多物体融合轨迹识别Service业务层处理
+ *
+ * @author km
+ * 2024-10-16
+ */
+@Service
+public class ObjectTraceMergeServiceImpl extends BaseServiceImpl<ObjectTraceMergeMapper, ObjectTraceMerge> implements IObjectTraceMergeService {
+    @Resource
+    private ObjectTraceMergeMapper objectTraceMergeMapper;
+
+    @Override
+    public QueryWrapper query() {
+        return super.query().from(OBJECT_TRACE_MERGE);
+    }
+
+    private QueryWrapper buildQueryWrapper(ObjectTraceMergeBo objectTraceMergeBo) {
+        QueryWrapper queryWrapper = super.buildBaseQueryWrapper();
+        queryWrapper.and(OBJECT_TRACE_MERGE.NAME.like
+        (objectTraceMergeBo.getName()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.STATUS.eq
+        (objectTraceMergeBo.getStatus()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.PARAMETERS.eq
+        (objectTraceMergeBo.getParameters()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.PREPROCESS_PATH.eq
+        (objectTraceMergeBo.getPreprocessPath()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.RESULT_PATH.eq
+        (objectTraceMergeBo.getResultPath()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.START_TIME.eq
+        (objectTraceMergeBo.getStartTime()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.END_TIME.eq
+        (objectTraceMergeBo.getEndTime()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.COST_SECOND.eq
+        (objectTraceMergeBo.getCostSecond()));
+        queryWrapper.and(OBJECT_TRACE_MERGE.REMARKS.eq
+        (objectTraceMergeBo.getRemarks()));
+
+        return queryWrapper;
+    }
+
+    /**
+     * 查询多物体融合轨迹识别
+     *
+     * @param id 多物体融合轨迹识别主键
+     * @return 多物体融合轨迹识别
+     */
+    @Override
+    public ObjectTraceMergeVo selectById(Long id) {
+        return this.getOneAs(query().where(OBJECT_TRACE_MERGE.ID.eq(id)), ObjectTraceMergeVo.class);
+    }
+
+    public ObjectTraceMergeBo getById(Long id) {
+        return this.getOneAs(query().where(OBJECT_TRACE_MERGE.ID.eq(id)), ObjectTraceMergeBo.class);
+    }
+
+    /**
+     * 查询多物体融合轨迹识别列表
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 多物体融合轨迹识别集合
+     */
+    @Override
+    public List<ObjectTraceMergeVo> selectList(ObjectTraceMergeBo objectTraceMergeBo) {
+        QueryWrapper queryWrapper = buildQueryWrapper(objectTraceMergeBo);
+            return this.listAs(queryWrapper, ObjectTraceMergeVo.class);
+    }
+
+    /**
+     * 分页查询多物体融合轨迹识别列表
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 分页多物体融合轨迹识别集合
+     */
+    @Override
+    public PageResult<ObjectTraceMergeVo> selectPage(ObjectTraceMergeBo objectTraceMergeBo) {
+        QueryWrapper queryWrapper = buildQueryWrapper(objectTraceMergeBo);
+            Page<ObjectTraceMergeVo> page = this.pageAs(PageQuery.build(), queryWrapper, ObjectTraceMergeVo.class);
+        return PageResult.build(page);
+    }
+
+    /**
+     * 新增多物体融合轨迹识别
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 结果:true 操作成功,false 操作失败
+     */
+    @Override
+    public boolean insert(ObjectTraceMergeBo objectTraceMergeBo) {
+    ObjectTraceMerge objectTraceMerge =MapstructUtils.convert(objectTraceMergeBo, ObjectTraceMerge. class);
+
+        return this.save(objectTraceMerge);//使用全局配置的雪花算法主键生成器生成ID值
+    }
+
+    /**
+     * 修改多物体融合轨迹识别
+     *
+     * @param objectTraceMergeBo 多物体融合轨迹识别Bo
+     * @return 结果:true 更新成功,false 更新失败
+     */
+    @Override
+    public boolean update(ObjectTraceMergeBo objectTraceMergeBo) {
+        ObjectTraceMerge objectTraceMerge =MapstructUtils.convert(objectTraceMergeBo, ObjectTraceMerge. class);
+        if (ObjectUtil.isNotNull(objectTraceMerge) && ObjectUtil.isNotNull(objectTraceMerge.getId())){
+            boolean updated = this.updateById(objectTraceMerge);
+                return updated;
+        }
+        return false;
+    }
+
+    /**
+     * 批量删除多物体融合轨迹识别
+     *
+     * @param ids 需要删除的多物体融合轨迹识别主键集合
+     * @return 结果:true 删除成功,false 删除失败
+     */
+    @Transactional
+    @Override
+    public boolean deleteByIds(Long[] ids) {
+        return this.removeByIds(Arrays.asList(ids));
+    }
+
+}

+ 6 - 3
taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/TargetIdentificationTaskServiceImpl.java

@@ -20,6 +20,7 @@ import com.taais.biz.domain.vo.AlgorithmModelVo;
 import com.taais.biz.domain.vo.AlgorithmTaskConfigurationVo;
 import com.taais.biz.domain.vo.DataVo;
 import com.taais.biz.service.*;
+import com.taais.common.core.config.TaaisConfig;
 import com.taais.common.core.utils.MapstructUtils;
 import com.taais.common.core.utils.StringUtils;
 import com.taais.common.core.utils.uuid.UUID;
@@ -220,7 +221,9 @@ public class TargetIdentificationTaskServiceImpl extends BaseServiceImpl<TargetI
 
         // 创建扩增子任务
         if (taskDto.getHasTrainAugmentation()) {
-            createDataAmplifyTask(taskBo.getId(), taskDto);
+            if (taskDto.getTrainAugmentationParams() != null && StringUtils.isNotEmpty(taskDto.getTrainAugmentationParams().getOtherParams())) {
+                createDataAmplifyTask(taskBo.getId(), taskDto);
+            }
         }
         return null;
     }
@@ -277,8 +280,8 @@ public class TargetIdentificationTaskServiceImpl extends BaseServiceImpl<TargetI
         return records;
     }
 
-    public static final String PATH_PREFIX = "/home/ObjectDetection_Web/task";
-    public static final String WORK_DIR = "/home/ObjectDetection_Web";
+    public static final String PATH_PREFIX = TaaisConfig.getProfile() + "/task";
+    public static final String WORK_DIR = TaaisConfig.getProfile();
     //public static final String PATH_PREFIX = "ObjectDetection_Web/task";
     //public static final String WORK_DIR = "ObjectDetection_Web";
     /**

+ 1 - 1
taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/TrackSequenceServiceImpl.java

@@ -271,7 +271,7 @@ public class TrackSequenceServiceImpl extends BaseServiceImpl<TrackSequenceMappe
 
         if (BizConstant.AlgorithmType.REASONING.equals(algorithmConfigTrack.getType())) {
             if(algorithmModelTrack.getModelName().startsWith("masc") || algorithmModelTrack.getModelName().startsWith("MASC")) {
-                String modelPath = algorithmModelTrack.getModelAddress() + File.separator + algorithmModelTrack.getModelName();
+                String modelPath = algorithmModelTrack.getModelAddress() + File.separator + algorithmModelTrack.getModelName().substring(5);
                 startToInfraredTask.setModel_path(modelPath);
             }
             else if(algorithmModelTrack.getModelName().startsWith("cat") || algorithmModelTrack.getModelName().startsWith("CAT")) {

+ 65 - 11
taais-modules/taais-biz/src/main/java/com/taais/biz/service/impl/VideoStableServiceImpl.java

@@ -1,13 +1,9 @@
 package com.taais.biz.service.impl;
 
 import java.io.File;
-import java.io.IOException;
 import java.nio.file.Path;
 import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
+import java.util.*;
 
 import cn.hutool.core.util.ObjectUtil;
 import com.mybatisflex.core.paginate.Page;
@@ -29,7 +25,6 @@ import com.taais.system.domain.vo.SysOssVo;
 import com.taais.system.service.ISysOssService;
 import jakarta.annotation.Resource;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FileUtils;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.entity.StringEntity;
 import org.apache.http.client.methods.CloseableHttpResponse;
@@ -38,7 +33,6 @@ import org.apache.http.impl.client.HttpClients;
 import org.apache.http.util.EntityUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.actuate.autoconfigure.observation.ObservationProperties;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import com.taais.biz.mapper.VideoStableMapper;
@@ -48,6 +42,7 @@ import com.taais.biz.domain.vo.VideoStableVo;
 import com.taais.biz.service.IVideoStableService;
 
 import static com.taais.biz.domain.table.VideoStableTableDef.VIDEO_STABLE;
+import static com.taais.biz.service.impl.DataSeqServiceImpl.isImageFile;
 
 /**
  * 视频去抖动Service业务层处理
@@ -222,8 +217,8 @@ public class VideoStableServiceImpl extends BaseServiceImpl<VideoStableMapper, V
         String fileName_without_suffix = removeFileExtension(fileName);
 
         Path path = Paths.get(resourcePath);
-        Path inputPath = path.resolveSibling(fileName_without_suffix + "_images");
-        Path outputPath = path.resolveSibling(fileName_without_suffix + "_stable");
+        Path inputPath = path.resolveSibling(fileName_without_suffix + BizConstant.UNZIP_SUFFIX);
+        Path outputPath = path.resolveSibling(fileName_without_suffix + BizConstant.STABLE_SUFFIX);
 
         makeDir(inputPath.toString());
         makeDir(outputPath.toString());
@@ -304,8 +299,8 @@ public class VideoStableServiceImpl extends BaseServiceImpl<VideoStableMapper, V
 //            inputPath = Paths.get("C:", videoStable.getInputPath());
 //            outputPath = Paths.get("C:", videoStable.getOutputPath());
 //        } else {
-            inputPath = Paths.get(videoStable.getInputPath());
-            outputPath = Paths.get(videoStable.getOutputPath());
+        inputPath = Paths.get(videoStable.getInputPath());
+        outputPath = Paths.get(videoStable.getOutputPath());
 //        }
 
         // 创建File对象
@@ -340,6 +335,65 @@ public class VideoStableServiceImpl extends BaseServiceImpl<VideoStableMapper, V
         }
     }
 
+    @Override
+    public List<Map<String, String>> getImages(Long inputOdssId) {
+        // 检查input_oss_id是否存在
+        if (ObjectUtil.isNull(inputOdssId)) {
+            return null;
+        }
+        SysOssVo ossEntity = ossService.getById(inputOdssId);
+        if (ObjectUtil.isNull(ossEntity)) {
+            return null;
+        }
+
+        String filePath = ossEntity.getFileName();
+        String localPath = TaaisConfig.getProfile();
+        String resourcePath = localPath + StringUtils.substringAfter(filePath, Constants.RESOURCE_PREFIX);
+        String unzipPath = resourcePath.substring(0, resourcePath.lastIndexOf(".")) + BizConstant.UNZIP_SUFFIX;
+        String resultPath = resourcePath.substring(0, resourcePath.lastIndexOf(".")) + BizConstant.STABLE_SUFFIX;
+
+        try {
+            List<String> inputImageList = getImageUrls(ossEntity, unzipPath, BizConstant.UNZIP_SUFFIX);
+            List<String> outputImageList = getImageUrls(ossEntity, resultPath, BizConstant.STABLE_SUFFIX);
+
+            HashMap<String,String> nameToUrl1 = new HashMap<>();
+            for (String imageUrl : inputImageList) {
+                String name = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
+                nameToUrl1.put(name, imageUrl);
+            }
+            HashMap<String,String> nameToUrl2 = new HashMap<>();
+            for (String imageUrl : outputImageList) {
+                String name = imageUrl.substring(imageUrl.lastIndexOf("/") + 1);
+                nameToUrl2.put(name, imageUrl);
+            }
+            List<String> inputImageNames = new ArrayList<>(nameToUrl1.keySet());
+
+            inputImageNames.sort(Comparator.naturalOrder());
+
+            List<Map<String, String>> resultList = new ArrayList<>();
+            for (String inputImageName : inputImageNames) {
+                Map<String, String> map = new HashMap<>();
+                map.put("inputUrl", nameToUrl1.get(inputImageName));
+                map.put("outputUrl", nameToUrl2.get(inputImageName));
+                resultList.add(map);
+            }
+
+            return resultList;
+        } catch (Exception e) {
+            System.out.println("getImages error: " + e.getMessage());
+            return null;
+        }
+    }
+
+    public List<String> getImageUrls(SysOssVo ossEntity, String path,  String suffix) {
+        String urlPrefix = ossEntity.getUrl().substring(0, ossEntity.getUrl().lastIndexOf(".")) + suffix;
+        // 列出unzipPath下所有图片文件
+        File directory = new File(path);
+        File[] files = directory.listFiles();
+        List<String> imageList = Arrays.asList(files).stream().filter(file -> isImageFile(file)).map(file -> urlPrefix + "/" + file.getName()).toList();
+        return imageList;
+    }
+
     /**
      * 递归统计文件夹中的文件数量
      *