Browse Source

增加平面图ai识别

dengsixing 3 months ago
parent
commit
64f92e19a5

+ 2 - 0
src/main/java/com/fdkankan/scene/bean/SceneJsonBean.java

@@ -242,4 +242,6 @@ public class SceneJsonBean {
 
     private Integer hasRecognition;
 
+    private Integer hasFloorplanAi;
+
 }

+ 7 - 0
src/main/java/com/fdkankan/scene/constant/CmdConstant.java

@@ -3,6 +3,9 @@ package com.fdkankan.scene.constant;
 
 import jdk.nashorn.internal.ir.LexicalContext;
 
+import java.io.File;
+
+
 /**
  * Created by owen on 2020/12/31 0031 14:22
  */
@@ -153,4 +156,8 @@ public class CmdConstant {
 
     public final static String OBJ2_TILES ="bash /home/ubuntu/bin/Obj2Tiles.sh @inPath";
     public final static String OBJ2_TILES_WIN ="Obj2Tiles.bat @inPath";
+
+    public final static String LAYOUT_DETECT = "PotreeConverter.bat layout_detect @in @out";
+    public final static String PANO_DETECT = "PotreeConverter.bat pano_detect @in @out";
+
 }

+ 30 - 0
src/main/java/com/fdkankan/scene/constant/DetectType.java

@@ -0,0 +1,30 @@
+package com.fdkankan.scene.constant;
+
+/**
+ * 用户状态
+ *
+ * @author fdkk
+ */
+public enum DetectType
+{
+    PANO(1, "全景图识别"), PLAN(2, "平面图识别");
+
+    private final Integer code;
+    private final String info;
+
+    DetectType(Integer code, String info)
+    {
+        this.code = code;
+        this.info = info;
+    }
+
+    public Integer getCode()
+    {
+        return code;
+    }
+
+    public String getInfo()
+    {
+        return info;
+    }
+}

+ 1 - 1
src/main/java/com/fdkankan/scene/controller/SceneController.java

@@ -90,7 +90,7 @@ public class SceneController extends BaseController {
     }
 
     @PostMapping("/initScene")
-    public ResultData initScene(@RequestBody InitSceneParamVO param){
+    public ResultData initScene(@RequestBody InitSceneParamVO param) throws Exception {
         return scenePlusService.initScene(param.getBucket(), param.getNum(), param.getTitle(), param.getDes(),
                 param.getSceneSource(), param.getDataSource(), param.getSceneScheme(),
                 param.getSceneResolution(), param.getSceneFrom(), param.getModelKind(), param.getAlgorithmTime(), param.getOrientation());

+ 4 - 0
src/main/java/com/fdkankan/scene/entity/ScenePlus.java

@@ -133,5 +133,9 @@ public class ScenePlus implements Serializable {
     @TableField("remove_portrait")
     private Integer removePortrait;
 
+    @TableField("has_floorplan_ai")
+    private Integer hasFloorplanAi;
+
+
 
 }

+ 12 - 0
src/main/java/com/fdkankan/scene/service/FloorplanAiService.java

@@ -0,0 +1,12 @@
+package com.fdkankan.scene.service;
+
+import java.io.IOException;
+import java.util.LinkedHashMap;
+
+public interface FloorplanAiService {
+
+    LinkedHashMap<Integer, Boolean> detFloorplan(String path)  throws Exception ;
+
+    boolean detFloorPlanAi(String num, String path, LinkedHashMap<Integer, Boolean> detFloorplan, String bucket) throws IOException;
+
+}

+ 2 - 0
src/main/java/com/fdkankan/scene/service/ISceneMarkShapeService.java

@@ -31,4 +31,6 @@ public interface ISceneMarkShapeService extends IService<SceneMarkShape> {
     List<SceneMarkShape> findByNumAndType(String num,Integer type);
 
     List<SceneMarkShape> findByNum(String num);
+
+    SceneMarkShape readDetectJson(String jsonPath);
 }

+ 1 - 1
src/main/java/com/fdkankan/scene/service/IScenePlusService.java

@@ -41,7 +41,7 @@ public interface IScenePlusService extends IService<ScenePlus> {
 
     ResultData initScene(String bucket, String num, String title, String des, Integer sceneSource,
                          String dataSource, Integer sceneScheme, String sceneResolution, String sceneFrom, String mdoelKind, Date algorithmTime,
-                         String orientation);
+                         String orientation) throws Exception;
 
     ResultData editScene(LaserSceneBean param);
 

+ 149 - 0
src/main/java/com/fdkankan/scene/service/impl/FloorplanAiServiceImpl.java

@@ -0,0 +1,149 @@
+package com.fdkankan.scene.service.impl;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.ObjUtil;
+import cn.hutool.core.util.ObjectUtil;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.fdkankan.model.constants.UploadFilePath;
+import com.fdkankan.model.utils.ComputerUtil;
+import com.fdkankan.scene.constant.CmdConstant;
+import com.fdkankan.scene.constant.DetectType;
+import com.fdkankan.scene.entity.SceneMarkShape;
+import com.fdkankan.scene.oss.OssUtil;
+import com.fdkankan.scene.service.FloorplanAiService;
+import com.fdkankan.scene.service.ISceneMarkShapeService;
+import com.fdkankan.scene.util.CmdUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+
+@Slf4j
+@Service
+public class FloorplanAiServiceImpl implements FloorplanAiService {
+
+    @Autowired
+    private ISceneMarkShapeService sceneMarkShapeService;
+    @Resource
+    private OssUtil ossUtil;
+
+    @Override
+    public LinkedHashMap<Integer, Boolean> detFloorplan(String path) throws Exception {
+        LinkedHashMap<Integer, Boolean> result = new LinkedHashMap<>();
+        String workDir = path + "/detFloorplan/";
+        if(FileUtil.exist(workDir)){
+            FileUtil.del(workDir);
+        }
+        String infoJsonPath = path + "/results/floorplan/info.json";
+        if(!FileUtil.exist(infoJsonPath)){
+            return result;
+        }
+
+        JSONObject infoObj = JSON.parseObject(FileUtil.readUtf8String(infoJsonPath));
+        JSONArray floors = infoObj.getJSONArray("floors");
+        if(CollUtil.isEmpty(floors)){
+            return result;
+        }
+        for (Object o : floors) {
+            JSONObject floor = (JSONObject) o;
+            Integer subgroup = floor.getInteger("subgroup");
+            String detectPath = workDir + subgroup + "/detect.json";
+            String floorKeyPath = path + "/results/floorplan/floor_" + subgroup + ".png";
+            String parent = FileUtil.getParent(detectPath, 1);
+            FileUtil.mkdir(parent);
+            result.put(subgroup, false);
+            if(!FileUtil.exist(floorKeyPath)){
+                continue;
+            }
+            String cmd = CmdConstant.LAYOUT_DETECT;
+            cmd = cmd.replace("@in", floorKeyPath);
+            cmd = cmd.replace("@out", detectPath);
+            CmdUtils.callLineWin(cmd, 50);
+            if (ComputerUtil.checkComputeCompleted(detectPath,5, 500)) {
+                result.put(subgroup, true);
+            }
+        }
+
+        return result;
+    }
+
+    @Override
+    public boolean detFloorPlanAi(String num, String path, LinkedHashMap<Integer, Boolean> detFloorplan, String bucket) throws IOException {
+
+        try {
+            String aiJsonKey = String.format(UploadFilePath.DATA_VIEW_PATH, num) + "floorplan/ai.json";
+            //先清空历史数据,因为数据格式改动很多个版本,已经无法按照规律进行过滤删除,所以这里先删除历史数据,而后再根据算法生成去插入数据
+            sceneMarkShapeService.remove(new LambdaQueryWrapper<SceneMarkShape>().eq(SceneMarkShape::getNum, num).eq(SceneMarkShape::getType, DetectType.PLAN.getCode()));
+            if(ossUtil.doesObjectExist(bucket, aiJsonKey)){
+                ossUtil.deleteObject(bucket, aiJsonKey);
+            }
+            if(CollUtil.isEmpty(detFloorplan)){
+                return false;
+            }
+            boolean hasFloorplanAi = false;
+            String workDir = path + "/detFloorplan/";
+            for (Integer subgroup : detFloorplan.keySet()) {
+                Boolean yes = detFloorplan.get(subgroup);
+                SceneMarkShape sceneMarkShape = null;
+                if(yes){
+                    String detectPath = workDir + subgroup + "/detect.json";
+                    sceneMarkShape = sceneMarkShapeService.readDetectJson(detectPath);
+                }
+                if (ObjUtil.isNull(sceneMarkShape)){
+                    sceneMarkShape = new SceneMarkShape();
+                    String infoJsonPath = path + "/results/floorplan/info.json";
+                    JSONObject infoObj = JSON.parseObject(FileUtil.readUtf8String(infoJsonPath));
+                    JSONArray floors = infoObj.getJSONArray("floors");
+                    for (Object floor : floors) {
+                        JSONObject floorObj = (JSONObject)floor;
+                        Integer group = floorObj.getInteger("subgroup");
+                        if(!subgroup.equals(group)){
+                            continue;
+                        }
+                        JSONObject resolution = floorObj.getJSONObject("resolution");
+                        sceneMarkShape.setImageWidth(resolution.getInteger("width"));
+                        sceneMarkShape.setImageHeight(resolution.getInteger("height"));
+                    }
+                }
+                if(Objects.isNull(sceneMarkShape.getShapes())){
+                    sceneMarkShape.setShapes(new ArrayList<>());
+                }
+                sceneMarkShape.setNum(num);
+                sceneMarkShape.setCreateTime(new Date());
+                sceneMarkShape.setType(DetectType.PLAN.getCode());
+                sceneMarkShapeService.save(sceneMarkShape);
+                if(CollUtil.isNotEmpty(sceneMarkShape.getShapes())){
+                    hasFloorplanAi = true;
+                }
+            }
+
+            List<SceneMarkShape> sceneMarkShapes = sceneMarkShapeService.findByNumAndType(num, DetectType.PLAN.getCode());
+            for (SceneMarkShape ms : sceneMarkShapes) {
+                if (ObjectUtil.isNotEmpty(ms.getShapes())){
+                    for (JSONObject s : ms.getShapes()) {
+                        String category = s.getString("category");
+                        if (category.contains("Tag_")){
+                            s.put("category","Tag");
+                        }
+                    }
+                }
+            }
+
+            ossUtil.uploadFileBytes(bucket, aiJsonKey, JSON.toJSONString(sceneMarkShapes).getBytes(StandardCharsets.UTF_8));
+            return hasFloorplanAi;
+        }catch (Exception e){
+            log.error("平面图ai识别处理报错", e);
+            return false;
+        }finally {
+//            FileUtil.del(workDir);
+        }
+    }
+}

+ 2 - 0
src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java

@@ -243,6 +243,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         sceneJson.setModelKind(scenePlusExt.getModelKind());
         sceneJson.setOrientation(scenePlusExt.getOrientation());
         sceneJson.setHasRecognition(scenePlusExt.getHasRecognition());
+        sceneJson.setHasFloorplanAi(scenePlus.getHasFloorplanAi());
         if(StrUtil.isNotEmpty(scenePlusExt.getVideos())){
             sceneJson.setVideos(scenePlusExt.getVideos());
         }
@@ -501,6 +502,7 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
         sceneInfoVO.setStarted(JSON.parseObject(sceneEditInfoExt.getStarted()));
         sceneInfoVO.setOrientation(scenePlusExt.getOrientation());
         sceneInfoVO.setHasRecognition(scenePlusExt.getHasRecognition());
+        sceneInfoVO.setHasFloorplanAi(scenePlus.getHasFloorplanAi());
 
         sceneInfoVO.setBucket(mappping);
 

+ 28 - 0
src/main/java/com/fdkankan/scene/service/impl/SceneMarkShapeServiceImpl.java

@@ -13,8 +13,10 @@ import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.fdkankan.common.constant.ErrorCode;
 import com.fdkankan.model.constants.ConstantFilePath;
 import com.fdkankan.scene.entity.SceneMarkShape;
+import com.fdkankan.scene.entity.SceneShapeEnum;
 import com.fdkankan.scene.mapper.MarkShapeMapper;
 import com.fdkankan.scene.service.ISceneMarkShapeService;
+import com.fdkankan.scene.service.SceneShapeEnumService;
 import com.fdkankan.scene.util.ConverxyUtil;
 import com.fdkankan.scene.vo.SceneMarkShapeParamVO;
 import com.fdkankan.scene.vo.SceneMarkShapeReDetectParamVO;
@@ -44,6 +46,9 @@ public class SceneMarkShapeServiceImpl extends ServiceImpl<MarkShapeMapper, Scen
 //    private String yolov5TrainQueue;
     @Value("${main.url:xxx}")
     private String mainUrl;
+    @Autowired
+    private SceneShapeEnumService sceneShapeEnumService;
+
 
     @Override
     public void editTrainStatus(SceneMarkShapeParamVO param) {
@@ -191,4 +196,27 @@ public class SceneMarkShapeServiceImpl extends ServiceImpl<MarkShapeMapper, Scen
         wrapper.eq(SceneMarkShape::getNum,num);
         return list(wrapper);
     }
+
+    @Override
+    public SceneMarkShape readDetectJson(String jsonPath) {
+        String strings = FileUtil.readString(jsonPath, "UTF-8");
+        JSONObject bbbb = JSONObject.parseObject(strings);
+        SceneMarkShape parse = JSONObject.toJavaObject(bbbb, SceneMarkShape.class);
+        if (ObjectUtil.isNull(parse.getShapes())){
+            return null;
+        }
+        List<JSONObject> shapes = parse.getShapes();
+        for (JSONObject shape : shapes) {
+            SceneShapeEnum category = sceneShapeEnumService.findByClassName(shape.getString("category"));
+            if (ObjectUtil.isNull(category)){
+                SceneShapeEnum sceneShapeEnum = new SceneShapeEnum();
+                //删除数字shape.getString("name")
+                String nameWithoutNumbers = shape.getString("name").replaceAll("\\d+", "");
+                sceneShapeEnum.setName(nameWithoutNumbers);
+                sceneShapeEnum.setClassName(shape.getString("category"));
+                sceneShapeEnumService.save(sceneShapeEnum);
+            }
+        }
+        return parse;
+    }
 }

+ 17 - 3
src/main/java/com/fdkankan/scene/service/impl/ScenePlusServiceImpl.java

@@ -105,6 +105,8 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
     private ISceneDelLogService sceneDelLogService;
     @Autowired
     private ICommonService commonService;
+    @Autowired
+    private FloorplanAiService floorplanAiService;
 
     @Override
     public ScenePlus getScenePlusByNum(String num) {
@@ -288,7 +290,7 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
     @Override
     public ResultData initScene(String bucket, String num, String title, String des, Integer sceneSource,
         String dataSource, Integer sceneScheme, String sceneResolution, String sceneFrom, String mdoelKind, Date algorithmTime,
-                                String orientation) {
+                                String orientation) throws Exception {
 
         ScenePlus scenePlus = this.getScenePlusByNum(num);
 
@@ -304,7 +306,7 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
             scenePlus = new ScenePlus();
         }
         scenePlus.setNum(num);
-        scenePlus.setSceneStatus(SceneStatus.SUCCESS.code());
+        scenePlus.setSceneStatus(SceneStatus.wait.code());
         scenePlus.setSceneSource(sceneSource);
         scenePlus.setPayStatus(PayStatus.PAY.code());
         scenePlus.setSceneType(SceneType.OTHER.code());
@@ -360,7 +362,6 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
         sceneEditInfoExt.setEditInfoId(sceneEditInfo.getId());
         sceneEditInfoExt.setLinks(this.checkIsExistLinks(num) ? CommonStatus.YES.code().intValue() : CommonStatus.NO.code().intValue());
         sceneEditInfoExtService.saveOrUpdate(sceneEditInfoExt);
-        sceneEditInfoExt = sceneEditInfoExtService.getByEditInfoId(sceneEditInfo.getId());
 
         //生成编辑显示控制表
         SceneEditControls sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId());
@@ -375,6 +376,18 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
         sceneEditControlsService.saveOrUpdate(sceneEditControls);
         sceneEditControls = sceneEditControlsService.getBySceneEditId(sceneEditInfo.getId());
 
+        //平面图ai识别
+        LinkedHashMap<Integer, Boolean> detFloorplan = floorplanAiService.detFloorplan(dataSource);
+        boolean hasFloorplanAi = floorplanAiService.detFloorPlanAi(num, dataSource, detFloorplan, bucket);
+        if(hasFloorplanAi){
+            scenePlus.setHasFloorplanAi(CommonStatus.YES.code().intValue());
+        }else{
+            scenePlus.setHasFloorplanAi(CommonStatus.NO.code().intValue());
+        }
+        scenePlus.setSceneStatus(SceneStatus.SUCCESS.code());
+        this.saveOrUpdate(scenePlus);
+
+
         //清除用户编辑业务数据
         Set<String> bizs = new HashSet<>();
         bizs.add(UserEditDataType.BOX_MODEL.message());
@@ -405,6 +418,7 @@ public class ScenePlusServiceImpl extends ServiceImpl<IScenePlusMapper, ScenePlu
             List<JSONObject> mosaicList = JSON.parseObject(oldSceneJson, SceneJsonBean.class).getMosaicList();
             sceneJson.setMosaicList(mosaicList);
         }
+        sceneJson.setHasFloorplanAi(scenePlus.getHasFloorplanAi());
         //本地写sceneJson文件
         ossUtil.uploadFileBytes(bucket, sceneJsonPath, JSON.toJSONString(sceneJson).getBytes(StandardCharsets.UTF_8));
 

+ 1 - 1
src/main/java/com/fdkankan/scene/util/CmdUtils.java

@@ -57,7 +57,7 @@ public class CmdUtils {
      *
      * @param command
      */
-    private static void callLineWin(String command, Integer lineSize) {
+    public static void callLineWin(String command, Integer lineSize) {
         CmdUtils.log.info("cmd: " + command);
         try {
             String[] cmd = new String[]{"cmd ", "/c", command};

+ 2 - 0
src/main/java/com/fdkankan/scene/vo/SceneInfoVO.java

@@ -272,4 +272,6 @@ public class SceneInfoVO {
 
     private Integer hasRecognition;
 
+    private Integer hasFloorplanAi;
+
 }