From dbc376afd95a693575dcfa4c73f1a526aed16468 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?LAPTOP-S9HJSOEB=5C=E6=98=8A=E5=A4=A9?= Date: Wed, 21 May 2025 18:40:53 +0800 Subject: [PATCH] =?UTF-8?q?=E4=B8=AA=E6=95=B0=E7=AE=97=E6=B3=95=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=20=E5=A4=B9=E5=8F=A4=E4=BA=95=E8=B4=A1=E5=9B=BE?= =?UTF-8?q?=E7=89=87=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../web/controller/BatchImageCropper.java | 115 ++++++++++++++++++ .../zhehekeji/web/service/CameraService.java | 15 ++- .../IndustrialCamera/CameraSaveUtil.java | 4 + .../IndustrialCamera/HikSaveImage.java | 67 ++++++++++ .../LxPointCloudSaveImage.java | 57 ++++++++- .../zhehekeji/web/service/InitService.java | 10 ++ .../service/algorithm/InventoryService.java | 5 + .../algorithm/PointCloudProcessor.java | 11 +- 8 files changed, 274 insertions(+), 10 deletions(-) create mode 100644 web/src/main/java/com/zhehekeji/web/controller/BatchImageCropper.java diff --git a/web/src/main/java/com/zhehekeji/web/controller/BatchImageCropper.java b/web/src/main/java/com/zhehekeji/web/controller/BatchImageCropper.java new file mode 100644 index 0000000..80f03c9 --- /dev/null +++ b/web/src/main/java/com/zhehekeji/web/controller/BatchImageCropper.java @@ -0,0 +1,115 @@ +package com.zhehekeji.web.controller; + +import java.awt.*; +import java.awt.image.BufferedImage; +import java.io.*; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.nio.file.StandardCopyOption; +import java.util.*; +import java.util.List; +import javax.imageio.ImageIO; + +public class BatchImageCropper { + public static void moveRandomFiles(String sourceDir, String targetDir, int numFiles) throws Exception { + File sourceFolder = new File(sourceDir); + File[] files = sourceFolder.listFiles((dir, name) -> new File(dir, name).isFile()); + + if (files == null || files.length == 0) { + System.out.println("源文件夹中没有文件可供移动。"); + return; + } + + List fileList = Arrays.asList(files); + Collections.shuffle(fileList); // 随机打乱文件列表 + + int moveCount = Math.min(numFiles, fileList.size()); + for (int i = 0; i < moveCount; i++) { + File fileToMove = fileList.get(i); + Path targetPath = Paths.get(targetDir, fileToMove.getName()); + Files.move(fileToMove.toPath(), targetPath, StandardCopyOption.REPLACE_EXISTING); +// txt 文件名 + String txtFileName = fileToMove.getPath().replace("images","labels").replace(".BMP", ".txt"); + String txtPath = fileToMove.getPath().replace("train","val").replace("images","labels").replace(".BMP", ".txt"); + Files.move(Paths.get(txtFileName), Paths.get(txtPath), StandardCopyOption.REPLACE_EXISTING); + System.out.println("Moved: " + fileToMove.getName()); + } + } + + public static void main2(String[] args) { + try { + String sourceDir = "D:\\PycharmProjects\\yolo\\gjg\\train\\images"; + String targetDir = "D:\\PycharmProjects\\yolo\\gjg\\val\\images"; + int numFiles = 30; + + moveRandomFiles(sourceDir, targetDir, numFiles); + } catch (Exception e) { + e.printStackTrace(); + } + } + public static void main(String[] args) throws IOException { + // 图片文件夹路径 + String imagesFolderPath = "D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2025-05\\新建文件夹\\献礼"; + // 标注文件夹路径 + String labelsFolderPath = "D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2025-05\\新建文件夹\\献礼\\labels"; + // 裁剪区域的坐标和尺寸 + int cropX = 950, cropY = 356, cropWidth = 1680, cropHeight = 1680; + + // 获取所有图片文件 + File imagesFolder = new File(imagesFolderPath); + File[] imageFiles = imagesFolder.listFiles((dir, name) -> name.endsWith(".BMP")); + + // 对每张图片进行处理 + for (File imageFile : imageFiles) { + // 读取图片 + BufferedImage image = ImageIO.read(imageFile); + + // 裁剪图片 +// BufferedImage croppedImage = image.getSubimage(cropX, cropY, cropWidth, cropHeight); +// // 直接覆盖原图片 +// ImageIO.write(croppedImage, "BMP", imageFile); + + // 处理标注文件 + String labelFilePath = labelsFolderPath + "/" + imageFile.getName().replaceAll("\\.BMP$", ".txt"); + File labelFile = new File(labelFilePath); + if (labelFile.exists()) { + List newLabels = adjustYoloLabels(labelFilePath, cropX, cropY, cropWidth, cropHeight,6); + // 直接覆盖原标注文件 + BufferedWriter writer = new BufferedWriter(new FileWriter(labelFilePath)); + for (String line : newLabels) { + writer.write(line); + writer.newLine(); + } + writer.close(); + } + } + } + + // 修改YOLO标注坐标 + public static List adjustYoloLabels(String labelFilePath, int cropX, int cropY, int cropWidth, int cropHeight,int classId) throws IOException { + List newLabels = new ArrayList<>(); + BufferedReader reader = new BufferedReader(new FileReader(labelFilePath)); + String line; + + while ((line = reader.readLine()) != null) { + String[] parts = line.split(" "); + double centerX = Double.parseDouble(parts[1]); + double centerY = Double.parseDouble(parts[2]); + double width = Double.parseDouble(parts[3]); + double height = Double.parseDouble(parts[4]); + + // 计算裁剪后的相对坐标 + centerX = (centerX * 3072 - cropX) / cropWidth; + centerY = (centerY * 2048 - cropY) / cropHeight; + width = width * cropWidth / cropWidth; + height = height * cropHeight / cropHeight; + + // 更新YOLO标注格式 + newLabels.add(classId + " " + centerX + " " + centerY + " " + width + " " + height); + } + + reader.close(); + return newLabels; + } +} diff --git a/web/src/main/java/com/zhehekeji/web/service/CameraService.java b/web/src/main/java/com/zhehekeji/web/service/CameraService.java index 830ca6a..019a458 100644 --- a/web/src/main/java/com/zhehekeji/web/service/CameraService.java +++ b/web/src/main/java/com/zhehekeji/web/service/CameraService.java @@ -331,11 +331,16 @@ public class CameraService { public void cameraTimeUpdate() { - log.info(" cameraTimeUpdate"); - long timeStamp = System.currentTimeMillis(); - List cameras = cameraMapper.selectList(new QueryWrapper<>()); - for (Camera camera : cameras){ - cameraTimeUpdate( camera); +ConfigProperties.KSEC ksec = configProperties.getKsec(); + + if(ksec != null&& ksec.getIp()!=null&& !ksec.getIp().equals("")) { + + log.info(" cameraTimeUpdate"); + long timeStamp = System.currentTimeMillis(); + List cameras = cameraMapper.selectList(new QueryWrapper<>()); + for (Camera camera : cameras) { + cameraTimeUpdate(camera); + } } } diff --git a/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/CameraSaveUtil.java b/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/CameraSaveUtil.java index ef67264..c67e35e 100644 --- a/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/CameraSaveUtil.java +++ b/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/CameraSaveUtil.java @@ -1,5 +1,7 @@ package com.zhehekeji.web.service.IndustrialCamera; +import java.util.List; + public interface CameraSaveUtil { /** * @@ -9,4 +11,6 @@ public interface CameraSaveUtil { * @return */ boolean saveImage(String sn,String path,String type); + + void init(List sns,String type); } diff --git a/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/HikSaveImage.java b/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/HikSaveImage.java index b599723..0715c6d 100644 --- a/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/HikSaveImage.java +++ b/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/HikSaveImage.java @@ -20,6 +20,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -255,6 +256,72 @@ public class HikSaveImage implements CameraSaveUtil{ return false; } + public void init(List sns,String type){ + ArrayList stDeviceList = new ArrayList<>(); + + System.out.println("SDK Version " + MvCameraControl.MV_CC_GetSDKVersion()); + + // Enuerate GigE and USB devices + try { + stDeviceList = MV_CC_EnumDevices(MV_GIGE_DEVICE | MV_USB_DEVICE); + if (0 >= stDeviceList.size()) { + System.out.println("No devices found!"); + } + } catch (CameraControlException e) { + System.err.println("Enumrate devices failed!" + e.toString()); + e.printStackTrace(); + + } + for (String sn : sns) { + int nRet = MV_OK; + int camIndex = -1; + + Handle hCamera = null; + try { + if (handleMap.containsKey(sn) && handleMap.get(sn) != null) { + //已经获得句柄 + hCamera = handleMap.get(sn); + } else { + System.out.println("创建句柄"); + camIndex = chooseCamera(stDeviceList, sn, type); + if (camIndex == -1) { + System.out.println("未找到摄像头"); + } + //未获得句柄并初始化 + hCamera = MvCameraControl.MV_CC_CreateHandle(stDeviceList.get(camIndex)); + handleMap.put(sn, hCamera); + + // Open device + nRet = MvCameraControl.MV_CC_OpenDevice(hCamera); + if (MV_OK != nRet) { + System.err.printf("Connect to camera failed, errcode: [%#x]\n", nRet); + + } + + // Make sure that trigger mode is off + nRet = MvCameraControl.MV_CC_SetEnumValueByString(hCamera, "TriggerMode", "Off"); + if (MV_OK != nRet) { + System.err.printf("SetTriggerMode failed, errcode: [%#x]\n", nRet); + + } + // Get payload size + + + // Start grabbing + nRet = MvCameraControl.MV_CC_StartGrabbing(hCamera); + if (MV_OK != nRet) { + System.err.printf("Start Grabbing fail, errcode: [%#x]\n", nRet); + + } + } + } catch (CameraControlException e) { + System.err.println("Create handle failed!" + e.toString()); + e.printStackTrace(); + + } + System.out.println(hCamera); + } + } Handle init(String sn, ArrayList stDeviceList,String type){ int nRet = MV_OK; int camIndex = -1; diff --git a/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/LxPointCloudSaveImage.java b/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/LxPointCloudSaveImage.java index 1dee438..5ea9d94 100644 --- a/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/LxPointCloudSaveImage.java +++ b/web/src/main/java/com/zhehekeji/web/service/IndustrialCamera/LxPointCloudSaveImage.java @@ -13,7 +13,7 @@ import java.util.concurrent.ConcurrentHashMap; @Slf4j public class LxPointCloudSaveImage { - static DcLibrary INSTANCER = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\lx\\LxCameraApi.dll", DcLibrary.class); + public static DcLibrary INSTANCER = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\lx\\LxCameraApi.dll", DcLibrary.class); static Map handleMap = new ConcurrentHashMap<>(); public static PointerByReference getHandle(String sn,int type ,DcLibrary INSTANCE){ @@ -69,6 +69,61 @@ public class LxPointCloudSaveImage { } } + public static PointerByReference init(String sn){ + + if(handleMap.get(sn)!=null){ + return handleMap.get(sn); + }else { + // 创建 Pointer 的引用 + PointerByReference handleRef = new PointerByReference(); + + + // 创建 PointerByReference 的实例用于接收设备列表 + // PointerByReference devlistRef = new PointerByReference(); + // 创建 LxDeviceInfo 实例 + DcLibrary.LxDeviceInfo info = new DcLibrary.LxDeviceInfo(); + + //library.DcGetDeviceList( devlistRef,0); + + // 调用 DcOpenDevice 函数 + System.out.println(sn+" "+handleRef+" "+info); + int result = INSTANCER.DcOpenDevice(1, sn, handleRef, info); + int i = 0; + if(result ==0) { + handleMap.put(sn, handleRef); + }else { + for (int ii=0;i<50;i++ ) { + result = INSTANCER.DcOpenDevice(1, sn, handleRef, info); + System.out.println(i + "次尝试;"+"异常:"+result); + try { + Thread.sleep(500); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + } + // 输出结果 + System.out.println("Result: " + result); + System.out.println("Handle: " + handleRef.getValue()); // 获取 DcHandle 的值 + System.out.println("Device Type: " + info.dev_type); + System.out.println("ID: " + new String(info.id).trim()); + System.out.println("IP: " + new String(info.ip).trim()); + System.out.println("SN: " + new String(info.sn).trim()); + System.out.println("MAC: " + new String(info.mac).trim()); + System.out.println("Firmware Version: " + new String(info.firmware_ver).trim()); + System.out.println("Algorithm Version: " + new String(info.algor_ver).trim()); + System.out.println("Name: " + new String(info.name).trim()); + System.out.println("Reserve: " + new String(info.reserve).trim()); + System.out.println("Reserve2: " + new String(info.reserve2).trim()); + System.out.println("Reserve3: " + new String(info.reserve3).trim()); + System.out.println("Reserve4: " + new String(info.reserve4).trim());//lxPointCloudApi.DcCloseDevice(handle); + + + return handleRef; + } + + } + public static boolean saveImage(String sn, String path,int type) { DcLibrary INSTANCE; INSTANCE = INSTANCER; diff --git a/web/src/main/java/com/zhehekeji/web/service/InitService.java b/web/src/main/java/com/zhehekeji/web/service/InitService.java index 8e21bad..c294b66 100644 --- a/web/src/main/java/com/zhehekeji/web/service/InitService.java +++ b/web/src/main/java/com/zhehekeji/web/service/InitService.java @@ -10,6 +10,8 @@ import com.zhehekeji.web.lib.joyware.JoywareCameraControlModuleImpl; import com.zhehekeji.web.lib.joyware.JoywareLoginModuleImpl; import com.zhehekeji.web.mapper.CameraMapper; import com.zhehekeji.web.mapper.StreetMapper; +import com.zhehekeji.web.service.IndustrialCamera.HikSaveImage; +import com.zhehekeji.web.service.algorithm.InventoryService; import com.zhehekeji.web.service.client.ClientChanel; import com.zhehekeji.web.service.client.NettyServer; import com.zhehekeji.web.service.com.SerialPortManager; @@ -78,11 +80,19 @@ public class InitService implements ApplicationRunner { return cameraControlModule; } + @Resource + InventoryService inventoryService; + + @Resource + HikSaveImage hikSaveImage; + @Override public void run(ApplicationArguments args) throws Exception { SerialPortManager.connectSerialPort(configProperties.getComConfig()); ConfigProperties.KSEC ksec = configProperties.getKsec(); + inventoryService.init(); + hikSaveImage.init(configProperties.getCameraConfig().getIndustrialCamera(),"sn"); if(ksec != null&& ksec.getIp()!=null&& !ksec.getIp().equals("")){ diff --git a/web/src/main/java/com/zhehekeji/web/service/algorithm/InventoryService.java b/web/src/main/java/com/zhehekeji/web/service/algorithm/InventoryService.java index 4cb2643..1b47e52 100644 --- a/web/src/main/java/com/zhehekeji/web/service/algorithm/InventoryService.java +++ b/web/src/main/java/com/zhehekeji/web/service/algorithm/InventoryService.java @@ -1,5 +1,6 @@ package com.zhehekeji.web.service.algorithm; +import com.sun.jna.ptr.PointerByReference; import com.zhehekeji.web.config.ConfigProperties; import com.zhehekeji.web.entity.CheckLog; import com.zhehekeji.web.entity.Stock; @@ -7,6 +8,7 @@ import com.zhehekeji.web.entity.Street; import com.zhehekeji.web.mapper.CheckLogMapper; import com.zhehekeji.web.mapper.StockMapper; import com.zhehekeji.web.service.IndustrialCamera.CameraSaveUtil; +import com.zhehekeji.web.service.IndustrialCamera.DcLibrary; import com.zhehekeji.web.service.IndustrialCamera.LxPointCloudSaveImage; import com.zhehekeji.web.service.PlcService; import com.zhehekeji.web.service.StreetService; @@ -63,6 +65,9 @@ public class InventoryService { return flag; } + public void init(){ + PointerByReference handleRef = LxPointCloudSaveImage.init(configProperties.getCameraConfig().getCamera3D()); + } public int match3D(String category,String path){ //拍照 log.info("3D拍照pcd: "+path); diff --git a/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java b/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java index 566f389..66cc2b0 100644 --- a/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java +++ b/web/src/main/java/com/zhehekeji/web/service/algorithm/PointCloudProcessor.java @@ -5,6 +5,7 @@ import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.zhehekeji.web.entity.Interval3D; import lombok.Data; +import lombok.extern.slf4j.Slf4j; import java.io.*; import java.nio.ByteBuffer; @@ -13,7 +14,7 @@ import java.text.DecimalFormat; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Collectors; - +@Slf4j public class PointCloudProcessor { // @@ -441,6 +442,7 @@ public class PointCloudProcessor { } catch (IOException e) { e.printStackTrace(); } + log.info("读取配置文件:pcdPojo:"+pcdPojo.toString()); return getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType()); @@ -621,6 +623,7 @@ public class PointCloudProcessor { private static int getLongitudinalType(List points, PcdPojo pojo, int l, int w, int height,String type){ //pojo里面的floorHeight为地板的值,以后所有的height都将根据地板值进行计算地板值减去当前点的z轴值,为高度,且当为height的倍数的时候,认为是有效的点,其中1倍的冗余在50mm,每高一层,冗余增加20mm // 计算 + System.out.println("新方法调用"); double baseTolerance = 50; // 初始冗余 50mm double additionalTolerancePerLevel = 20; // 每层增加 20mm 冗余 Map> map = new HashMap<>(); @@ -681,9 +684,9 @@ public class PointCloudProcessor { } public static void main(String[] args) { - String path ="E:\\工作\\泸州测试\\2025-05-12\\7d5a619e-190d-4e7d-95a9-1e47aa49eef8--192.168.48.11.pcd"; - String configPath = "E:\\工作\\泸州测试\\27.json"; - String typeConfPath = "E:\\工作\\泸州测试\\temlent\\40014847.json"; + String path ="E:\\工作\\泸州测试\\2\\62de6477-2ae4-47b8-91d8-f0ca54ea4a05--192.168.40.11.pcd"; + String configPath = "E:\\工作\\泸州测试\\2\\27.json"; + String typeConfPath = "E:\\工作\\泸州测试\\2\\40014845.json"; List points = readPCD(path); PcdPojo pojo = new PcdPojo(); PcdPojo pcdPojo = new PcdPojo();