简单修改

淮阴
LAPTOP-S9HJSOEB\昊天 7 months ago
parent 3bb630a453
commit 521a2efcfd

@ -1,17 +0,0 @@
spring:
application:
name: LxCameraApi
server:
port: 8097
#两台相机
camera:
- id: 1
ip: 192.168.1.82
# 切割配置
convertConfPath: "E://pe.json"
# 位置配置
computeConfPath: "E://peconf.json"
swagger:
enabled: true

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

@ -96,7 +96,7 @@
<artifactId>opencv</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${project.basedir}/src/main/resources/libs/opencv-453.jar</systemPath>
<systemPath>${project.basedir}/src/main/resources/libs/opencv-480.jar</systemPath>
</dependency>

@ -22,6 +22,15 @@ public class AppConfig {
public List<SpecialBox> specialBox;
public DeleteFile deleteFile;
@Data
public static class DeleteFile{
String cron;
List<String> path;
Integer day;
}
@Data
public static class Camera{
String ip;
@ -29,6 +38,7 @@ public class AppConfig {
String streetId;
Integer direction;
String convertConfPath;
String deepConvertConfPath;
String computeConfPath;
String calibratePath;
}

@ -0,0 +1,82 @@
package com.example.lxcameraapi.conf;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Configurable;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.Scheduled;
import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.List;
@Configuration
@Slf4j
public class CronConfig {
@Resource
private AppConfig appConfig;
// 每天凌晨执行一次0 0 0 * * ?
@Scheduled(cron = "${deleteFile.cron}")
public void deleteOldFolders() {
List<String> targetPaths = appConfig.getDeleteFile().getPath();
for (String targetPath:targetPaths){
try {
File directory = new File(targetPath);
if (!directory.exists() || !directory.isDirectory()) {
log.warn("目标路径不存在或不是目录: {}", targetPath);
return;
}
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
for (File folder : directory.listFiles()) {
if (folder.isDirectory()) {
String folderName = folder.getName();
try {
LocalDate folderDate = LocalDate.parse(folderName, formatter);
long daysDifference = ChronoUnit.DAYS.between(folderDate, currentDate);
if (daysDifference > appConfig.getDeleteFile().getDay()) {
deleteDirectory(folder);
log.info("成功删除过期文件夹: {}", folder.getAbsolutePath());
}
} catch (Exception e) {
log.warn("忽略非日期格式的文件夹: {}", folderName);
}
}
}
} catch (Exception e) {
log.error("定时任务执行失败: ", e);
}
}
}
// 递归删除目录及其内容
private void deleteDirectory(File directory) {
if (directory.exists() && directory.isDirectory()) {
File[] files = directory.listFiles();
if (files != null) {
for (File file : files) {
if (file.isDirectory()) {
deleteDirectory(file); // 递归删除子目录
} else {
boolean deleted = file.delete();
if (!deleted) {
log.warn("无法删除文件: {}", file.getAbsolutePath());
}
}
}
}
boolean deleted = directory.delete();
if (!deleted) {
log.warn("无法删除目录: {}", directory.getAbsolutePath());
}
}
}
}

@ -1,12 +1,15 @@
package com.example.lxcameraapi.conf;
import com.example.lxcameraapi.service.IndustrialCamera.camera.hik.HikSaveImage;
import com.example.lxcameraapi.service.IndustrialCamera.camera.lx.LxPointCloudSaveImage;
import com.example.lxcameraapi.service.IndustrialCamera.distinguish.Calibration;
import org.opencv.core.Core;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
@Service
@ -16,9 +19,84 @@ public class Init {
AppConfig appConfig;
@PostConstruct
public void hikInit(){
//
// if (appConfig.getLxCamera().size() > 0) {
// Calibration.init(appConfig.getLxCamera());
// }
// if (appConfig.getHikCamera().size() > 0){
// HikSaveImage.forInit(appConfig.getHikCamera());
// }
}
@PostConstruct
public void LxInit(){
LxPointCloudSaveImage.init(appConfig.getLxCamera());
//
// if (appConfig.getLxCamera().size() > 0) {
// Calibration.init(appConfig.getLxCamera());
// }
// if (appConfig.getHikCamera().size() > 0){
// HikSaveImage.forInit(appConfig.getHikCamera());
// }
}
// 裁剪宽度
private static final int TARGET_WIDTH = 1696;
public static void cropAllBmpImagesInFolder(String inputFolderPath, String outputFolderPath) {
File inputFolder = new File(inputFolderPath);
File outputFolder = new File(outputFolderPath);
if (!outputFolder.exists()) {
outputFolder.mkdirs();
}
// 获取所有 bmp 文件
File[] files = inputFolder.listFiles((dir, name) -> name.toLowerCase().endsWith(".bmp"));
if (files == null || files.length == 0) {
System.out.println("❌ 没有找到 .bmp 图片");
return;
}
Calibration.init(appConfig.getHikCamera());
HikSaveImage.forInit(appConfig.getHikCamera());
for (File file : files) {
try {
BufferedImage originalImage = ImageIO.read(file);
int originalWidth = originalImage.getWidth();
int originalHeight = originalImage.getHeight();
// 如果原始图像宽度小于目标宽度,跳过或直接复制
if (originalWidth < TARGET_WIDTH) {
System.out.println("⚠️ 跳过 " + file.getName() + ":宽度不足 1696");
continue;
}
// 计算裁剪区域(水平居中,保留原高)
int startX = 670;
int startY = 352;
// 裁剪
BufferedImage croppedImage = originalImage.getSubimage(
startX, startY, TARGET_WIDTH, TARGET_WIDTH);
// 保存结果
File outputFile = new File(outputFolder, file.getName());
ImageIO.write(croppedImage, "bmp", outputFile);
System.out.println("✅ 已裁剪并保存: " + outputFile.getAbsolutePath());
} catch (Exception e) {
System.err.println("❌ 处理失败:" + file.getName());
e.printStackTrace();
}
}
}
public static void main(String[] args) {
String inputPath = "E:\\YXP\\新的三个品规取图\\images"; // 输入文件夹路径
String outputPath = "E:\\YXP\\新的三个品规取图\\images"; // 输出文件夹路径
cropAllBmpImagesInFolder(inputPath, outputPath);
}
}

@ -26,7 +26,7 @@ public class CategoryController {
int i = 0;
for (AppConfig.Camera c :cameras){
String sn = UUID.randomUUID().toString();
LxPointCloudSaveImage.saveImage(c.getIp(),"D:\\data\\"+sn+".pcd",c.getId());
LxPointCloudSaveImage.saveImage(c.getIp(),"D:\\data\\"+sn+".pcd");
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("D:\\data\\"+sn+".pcd");
pojo.setConfigPath(c.getConvertConfPath());
@ -58,7 +58,7 @@ public class CategoryController {
for (AppConfig.Camera c : cameras) {
if (Objects.equals(c.getId(), cameraId)) {
String sn = UUID.randomUUID().toString();
LxPointCloudSaveImage.saveImage(c.getIp(), "D:\\data\\" + sn + ".pcd", c.getId());
LxPointCloudSaveImage.saveImage(c.getIp(), "D:\\data\\" + sn + ".pcd");
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("D:\\data\\" + sn + ".pcd");
pojo.setConfigPath(c.getConvertConfPath());
@ -77,7 +77,7 @@ public class CategoryController {
for (AppConfig.Camera c : cameras) {
if (streetId.equals(c.getStreetId())) {
String sn = UUID.randomUUID().toString();
LxPointCloudSaveImage.saveImage(c.getIp(), "D:\\data\\" + sn + ".pcd", c.getId());
LxPointCloudSaveImage.saveImage(c.getIp(), "D:\\data\\" + sn + ".pcd");
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("D:\\data\\" + sn + ".pcd");
pojo.setConfigPath(c.getConvertConfPath());

@ -0,0 +1,126 @@
package com.example.lxcameraapi.controller;
import com.example.lxcameraapi.conf.AppConfig;
import com.example.lxcameraapi.service.IndustrialCamera.algorithm.BoxPositionConf;
import com.example.lxcameraapi.service.IndustrialCamera.algorithm.PcdPojo;
import com.example.lxcameraapi.service.IndustrialCamera.algorithm.PointCloudProcessor;
import com.example.lxcameraapi.service.IndustrialCamera.camera.lx.LxPointCloudSaveImage;
import org.apache.logging.log4j.util.Strings;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;
@RestController
@RequestMapping("/judge")
public class JudgeController {
@Resource
AppConfig appConfig;
/**
*
* @param direction 1 2
* @param separation 21
* @return
* @throws IOException
*/
@GetMapping("/judge")
public Boolean judge(int direction,int separation, String taskId) throws IOException {
List<AppConfig.Camera> cameras = appConfig.getLxCamera();
// 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
// 定义格式化模式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 格式化为字符串
String formattedDate = now.format(formatter);
for (AppConfig.Camera c :cameras){
if (direction != c.getDirection() ){
continue;
}
String uuid = UUID.randomUUID().toString();
if (!Strings.isEmpty(taskId)){
uuid = taskId;
}
LxPointCloudSaveImage.saveImage(c.getIp(),"D:\\data\\"+formattedDate+"\\"+uuid+".pcd");
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("D:\\data\\"+formattedDate+"\\"+uuid+".pcd");
if (separation== 1) {
pojo.setConfigPath(c.getConvertConfPath());
}else pojo.setConfigPath(c.getDeepConvertConfPath());
try {
pojo.setPCDInfo(pojo);
} catch (IOException e) {
throw new RuntimeException(e);
}
PointCloudProcessor pointCloudProcessor = new PointCloudProcessor();
Boolean judge = pointCloudProcessor.judge(pojo);
System.out.println("判断结果:"+judge);
if (c.getCalibratePath()!=null){
pojo.setConfigPath(c.getCalibratePath());
try {
pojo.setPCDInfo(pojo);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
PointCloudProcessor.saveImage(pojo, "D:\\data\\"+formattedDate+"\\"+uuid+".png");
// List<BoxPositionConf> confs = pointCloudProcessor.getBoxPositionConf(c.getComputeConfPath());
return judge;
}
return false;
}
@GetMapping("/judge1")
public Boolean judge1(Integer direction,Integer separation) throws IOException {
return false;
}
@GetMapping("/judgeTest")
public Boolean judgeTest(Integer direction,Integer separation) throws IOException {
List<AppConfig.Camera> cameras = appConfig.getLxCamera();
// 获取当前日期时间
LocalDateTime now = LocalDateTime.now();
// 定义格式化模式
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// 格式化为字符串
String formattedDate = now.format(formatter);
for (AppConfig.Camera c :cameras){
if (direction != c.getDirection() ) {
break;
}
// }
// String uuid = UUID.randomUUID().toString();
// LxPointCloudSaveImage.saveImage(c.getIp(),"D:\\data\\"+formattedDate+"\\"+uuid+".pcd");
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("E:\\工作\\淮阴卷烟厂3D取图\\20250519\\FD5451142170\\20250519_185136733_t.pcd");
if (separation== 2) {
pojo.setConfigPath(c.getConvertConfPath());
}else pojo.setConfigPath(c.getDeepConvertConfPath());
try {
pojo.setPCDInfo(pojo);
} catch (IOException e) {
throw new RuntimeException(e);
}
PointCloudProcessor pointCloudProcessor = new PointCloudProcessor();
// List<BoxPositionConf> confs = pointCloudProcessor.getBoxPositionConf(c.getComputeConfPath());
return pointCloudProcessor.judge(pojo);
}
return false;
}
}

@ -0,0 +1,149 @@
package com.example.lxcameraapi.service;
import java.io.*;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.stream.*;
public class FileProcessor {
// public static void main(String[] args) {
// String folderPath = "E:\\工作\\labels_my-project-name_2025-06-04-03-52-29"; // 替换为你的目标文件夹路径
// String outputFolderPath = "E:\\工作\\labels"; // 输出文件夹路径
//
// try {
// processFolder(folderPath, outputFolderPath);
// System.out.println("文件处理完成!");
// } catch (IOException e) {
// System.err.println("发生错误: " + e.getMessage());
// }
// }
/**
*
*/
public static void processFolder(String folderPath, String outputFolderPath) throws IOException {
Path inputDir = Paths.get(folderPath);
Path outputDir = Paths.get(outputFolderPath);
if (!Files.exists(outputDir)) {
Files.createDirectories(outputDir);
}
Files.walk(inputDir)
.filter(path -> !Files.isDirectory(path)) // 排除目录
.forEach(path -> processFile(path, outputDir)); // 处理每个文件
}
public static void main(String[] args) {
String sourceFolderPath = "D:\\PycharmProjects\\yolo\\gjg\\train\\images"; // 源文件夹路径
String targetFolderPath = "D:\\PycharmProjects\\yolo\\gjg\\val\\images"; // 目标文件夹路径
int numberOfFilesToMove = 32; // 要移动的文件数量
try {
moveRandomFiles(sourceFolderPath, targetFolderPath, numberOfFilesToMove);
System.out.println("成功移动了 " + numberOfFilesToMove + " 个文件!");
} catch (IOException e) {
System.err.println("发生错误: " + e.getMessage());
}
}
/**
*
*/
public static void moveRandomFiles(String sourcePath, String targetPath, int count) throws IOException {
Path sourceDir = Paths.get(sourcePath);
Path targetDir = Paths.get(targetPath);
if (!Files.exists(targetDir)) {
Files.createDirectories(targetDir); // 创建目标目录
}
List<Path> files = listFiles(sourceDir); // 获取所有文件列表
if (files.size() < count) {
throw new IllegalArgumentException("源文件夹中的文件数量不足!");
}
Collections.shuffle(files); // 打乱顺序,模拟“随机”
List<Path> selectedFiles = files.subList(0, count); // 取前N个作为要移动的文件
for (Path file : selectedFiles) {
String txtFileName = file.toString().replace(".bmp", ".txt").replace(".BMP", ".txt").replace("images", "labels");
String txtValFileName = file.toString().replace(".bmp", ".txt").replace(".BMP", ".txt").replace("images", "labels").replace("train", "val");
Path targetFile = targetDir.resolve(file.getFileName().toString());
Files.move(file, targetFile, StandardCopyOption.REPLACE_EXISTING); // 移动文件
// txt文件
Files.move(Paths.get(txtFileName), Paths.get(txtValFileName), StandardCopyOption.REPLACE_EXISTING); // 移动文件
System.out.println("已移动: " + file.getFileName());
}
}
/**
*
*/
public static List<Path> listFiles(String folderPath) throws IOException {
return listFiles(Paths.get(folderPath));
}
public static List<Path> listFiles(Path folderPath) throws IOException {
if (!Files.isDirectory(folderPath)) {
throw new IllegalArgumentException("不是有效的文件夹路径");
}
List<Path> result = new ArrayList<>();
try (DirectoryStream<Path> stream = Files.newDirectoryStream(folderPath)) {
for (Path entry : stream) {
if (Files.isRegularFile(entry)) {
result.add(entry);
}
}
}
return result;
}
/**
*
*/
public static void processFile(Path filePath, Path outputDir) {
String fileName = filePath.getFileName().toString();
Path outputFilePath = outputDir.resolve(fileName ); // 添加 .modified 后缀
try (
BufferedReader reader = Files.newBufferedReader(filePath);
BufferedWriter writer = Files.newBufferedWriter(outputFilePath)
) {
String line;
while ((line = reader.readLine()) != null) {
String modifiedLine = replaceFirstChar(line);
writer.write(modifiedLine);
writer.newLine(); // 每行写入后换行
}
} catch (IOException e) {
System.err.println("处理文件时出错: " + filePath + ", 错误: " + e.getMessage());
}
}
/**
*
*/
public static String replaceFirstChar(String line) {
if (line.isEmpty()) {
return line;
}
char firstChar = line.charAt(0);
switch (firstChar) {
case '0':
return '7' + line.substring(1);
case '1':
return '8' + line.substring(1);
case '2':
return '6' + line.substring(1);
default:
return line;
}
}
}

@ -1,157 +0,0 @@
package com.example.lxcameraapi.service.IndustrialCamera.QrCode;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.WritableRaster;
import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import javax.imageio.ImageIO;
import static org.opencv.imgcodecs.Imgcodecs.imread;
import org.opencv.*;
import org.opencv.wechat_qrcode.WeChatQRCode;
/**
*
*/
public class WeChatQRCodeTool {
private static volatile WeChatQRCodeTool instance;
private static volatile org.opencv.wechat_qrcode.WeChatQRCode detector;
//封装成了工具类,所以做成了单例
private WeChatQRCodeTool() {
System.load(new File(System.getProperty("user.dir")+"\\libs\\opencv\\opencv_java453.dll").getAbsolutePath());
//微信提供的4个模型配置文件放在resource/wechatqrcode文件夹里,
//下载地址WeChatCV/opencv_3rdparty: OpenCV - 3rdparty (github.com)
ClassLoader cl = WeChatQRCodeTool.class.getClassLoader();
URL detectprototxt = cl.getResource("wechatqrcode/detect.prototxt");
URL detectcaffemodel =cl.getResource("wechatqrcode/detect.caffemodel");
URL srprototxt=cl.getResource("wechatqrcode/sr.prototxt");
URL srcaffemodel =cl.getResource("wechatqrcode/sr.caffemodel");
//实例化微信二维码扫描对象//如果打成jar那么路径需要换到外部磁盘存储目录。
detector = new org.opencv.wechat_qrcode.WeChatQRCode(
detectprototxt.getPath().substring(1),
//因为使用的getResource方法获取的是URL对象而这个构造方法里需要传入File的路径所以substring1去掉/D:/xx开头的/
detectcaffemodel.getPath().substring(1),
srprototxt.getPath().substring(1),
srcaffemodel.getPath().substring(1));
}
public static WeChatQRCodeTool getInstance() {
if (instance == null) {
synchronized (WeChatQRCodeTool.class) {
if (instance == null) {
instance = new WeChatQRCodeTool();
}
}
}
return instance;
}
/**
* bufferimageFileImageIO.read()bufferimage.
*
*
*/
public String decode(BufferedImage srcImage) {
int cvtype = CvType.CV_8UC3;
if (srcImage.getType() == BufferedImage.TYPE_BYTE_GRAY) {
cvtype = CvType.CV_8UC1;
}
Mat image = bufImg2Mat(srcImage, srcImage.getType(), cvtype);
//返回解析的字符串,如果图片有多个二维码,则会返回多个。
List<String> result2 = detector.detectAndDecode(image);
if (result2 != null && result2.size() > 0) {
return result2.get(0);
}
return null;
}
public static void main(String[] args) {
File qrCodeImage = new File("E:\\work\\qqqY4.jpeg");
// 使用 ImageIO 读取图片
BufferedImage bufferedImage = null;
try {
bufferedImage = ImageIO.read(qrCodeImage);
} catch (IOException e) {
throw new RuntimeException(e);
}
WeChatQRCodeTool weChatQRCodeTool = new WeChatQRCodeTool();
String code = weChatQRCodeTool. decode(bufferedImage);
System.out.println(code);
}
/**
* BufferedImageMat *
*
* @param original BufferedImage
* @param imgType bufferedImage BufferedImage.TYPE_3BYTE_BGR
* @param matType mattype CvType.CV_8UC3
*    * BufferedImage.TYPE_3BYTE_BGR, CvType.CV_8UC3
*/
public static Mat bufImg2Mat(BufferedImage original, int imgType, int matType) {
if (original == null) {
throw new IllegalArgumentException("original == null");
}
byte[] pixels = null;
// Don't convert if it already has correct type
if (original.getType() != imgType) {
// Create a buffered image
BufferedImage image = new BufferedImage(original.getWidth(), original.getHeight(), imgType);
// Draw the image onto the new buffer
Graphics2D g = image.createGraphics();
try {
g.setComposite(AlphaComposite.Src);
g.drawImage(original, 0, 0, null);
pixels = ((DataBufferByte) image.getRaster().getDataBuffer()).getData();
} finally {
g.dispose();
}
} else {
pixels = ((DataBufferByte) original.getRaster().getDataBuffer()).getData();
}
Mat mat = Mat.eye(original.getHeight(), original.getWidth(), matType);
mat.put(0, 0, pixels);
return mat;
}
/**
* MatBufferedImage
*/
public static BufferedImage matToBufferedImage(Mat mat) {
if (mat.height() > 0 && mat.width() > 0) {
BufferedImage image = new BufferedImage(mat.width(), mat.height(),
BufferedImage.TYPE_3BYTE_BGR);
WritableRaster raster = image.getRaster();
DataBufferByte dataBuffer = (DataBufferByte) raster.getDataBuffer();
byte[] data = dataBuffer.getData();
mat.get(0, 0, data);
return image;
}
return null;
}
}

@ -7,12 +7,18 @@ import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.highgui.HighGui;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.util.*;
import java.util.List;
import java.util.stream.Collectors;
public class PointCloudProcessor {
@ -277,30 +283,40 @@ public class PointCloudProcessor {
}
return points;
}
private static List<double[]> readBinaryPCD(String filePath) throws IOException {
public static List<double[]> readBinaryPCD(String filePath) {
List<double[]> points = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(filePath)) {
ByteBuffer buffer = null;
buffer.order(ByteOrder.LITTLE_ENDIAN);
// Skip header (assuming header size is known, or read until DATA section)
// This example assumes 11 lines of header, which may vary
for (int i = 0; i < 11; i++) {
while (buffer.get() != '\n') {
// Skip header lines
try (DataInputStream dis = new DataInputStream(new FileInputStream(filePath))) {
// 读取头部信息
String line;
Map<String, String> header = new HashMap<>();
while (!(line = dis.readLine()).equals("DATA binary")) {
String[] parts = line.split(" ");
if (parts.length > 1) {
header.put(parts[0], parts[1]);
}
}
// Read binary data
while (buffer.hasRemaining()) {
double x = buffer.getFloat();
double y = buffer.getFloat();
double z = buffer.getFloat();
int rgb = buffer.getInt(); // Read 4 bytes for RGB
double[] point = {x, y, z};
// 获取点云的总点数
int pointCount = Integer.parseInt(header.get("POINTS"));
// 读取二进制数据
for (int i = 0; i < pointCount; i++) {
double[] point = new double[3]; // 存储 x, y, z 坐标
point[0] = dis.readFloat(); // 读取 x
point[1] = dis.readFloat(); // 读取 y
point[2] = dis.readFloat(); // 读取 z
int rgb = dis.readInt(); // 读取 RGB 值(无符号整数)
// 可选:解析 RGB如果需要的话
// int r = (rgb >> 16) & 0xFF;
// int g = (rgb >> 8) & 0xFF;
// int b = rgb & 0xFF;
// 你可以存储这些颜色信息,也可以仅处理坐标
points.add(point);
}
} catch (Exception e) {
return null;
} catch (IOException e) {
e.printStackTrace();
}
return points;
}
@ -419,19 +435,165 @@ public class PointCloudProcessor {
System.load(new File(System.getProperty("user.dir")+"\\libs\\opencv\\opencv_java480.dll").getAbsolutePath());
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("E:\\pr3d\\03bcfe74-2b4b-41e5-a9f1-09d60090f01b.pcd");
pojo.setConfigPath("E:\\pr3d\\2-pz-001.json");
pojo.setPcd1("E:\\1\\1ij.pcd");
pojo.setConfigPath("E:\\工作\\淮阴\\pz6.json");
try {
pojo.setPCDInfo(pojo);
} catch (IOException e) {
throw new RuntimeException(e);
}
PointCloudProcessor pointCloudProcessor = new PointCloudProcessor();
List<BoxPositionConf> confs = pointCloudProcessor.getBoxPositionConf("E:\\pr3d\\2-peconf-001.json");
int i = pointCloudProcessor.slicing(pojo, confs);
System.out.println(pojo.toString());
System.out.println(i);
try {
saveImage(pojo, "E:\\工作\\淮阴\\03bcfe74-2b4b-41e5-a9f1-09d60090f01b.png");
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
*
*
* @param pojo
*/
public boolean judge(PcdPojo pojo) {
// 计算pcd1
List<double[]> points = readPCD(pojo.getPcd1());
if (points == null || points.isEmpty()) {
}
//map xyz
List<double[]> clippedPoint = points.stream()
.map(point -> {
//旋转
return rotatePoints(point, pojo.getRotationMatrix());
})
.filter(point ->
//截取
clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())
)
.collect(Collectors.toList());
painting(points);
return clippedPoint.size()>500;
}
public static BufferedImage createImageFromPointCloud(List<double[]> pointCloud) {
// Step 1: 计算 x, y, z 的最大值和最小值
double xMin = Double.MAX_VALUE, xMax = Double.MIN_VALUE;
double yMin = Double.MAX_VALUE, yMax = Double.MIN_VALUE;
double zMin = Double.MAX_VALUE, zMax = Double.MIN_VALUE;
for (double[] point : pointCloud) {
double x = point[0];
double y = point[1];
double z = point[2];
xMin = Math.min(xMin, x);
xMax = Math.max(xMax, x);
yMin = Math.min(yMin, y);
yMax = Math.max(yMax, y);
zMin = Math.min(zMin, z);
zMax = Math.max(zMax, z);
}
// Step 2: 计算缩放比例
double scaleX = 1.0 / (xMax - xMin);
double scaleY = 1.0 / (yMax - yMin);
double scaleZ = 1.0 / (zMax - zMin);
// 设定图像的大小
int width = 800; // 假设图像宽度为800
int height = 600; // 假设图像高度为600
// 创建一个二维数组来存储每个像素位置的最小 z 值和对应的颜色
double[][] minZValues = new double[width][height];
Color[][] pixelColors = new Color[width][height];
// 初始化 minZValues 为最大值
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
minZValues[x][y] = Double.MAX_VALUE;
}
}
// 点的大小(半径)
int pointRadius = 3; // 改为需要的大小
// Step 3: 为每个点分配一个像素位置,并记录最小 z 值
for (double[] point : pointCloud) {
// 缩放点的坐标,保留 7% 边距
int x = (int) ((point[0] - xMin) * (width * 0.93) * scaleX) + (int) (width * 0.035);
int y = (int) ((point[1] - yMin) * (height * 0.93) * scaleY) + (int) (height * 0.035);
// 确保坐标在图像范围内
if (x >= 0 && x < width && y >= 0 && y < height) {
// 如果当前点的 z 值更小,则更新
if (point[2] < minZValues[x][y]) {
minZValues[x][y] = point[2];
// 获取深度颜色
pixelColors[x][y] = getColorFromDepth(point[2], zMin, zMax);
}
}
}
// 创建图像并填充白色背景
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = image.createGraphics();
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, width, height);
g2d.dispose();
// Step 4: 绘制点
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
if (minZValues[x][y] != Double.MAX_VALUE && pixelColors[x][y] != null) {
// 在指定位置绘制圆形点
for (int dy = -pointRadius; dy <= pointRadius; dy++) {
for (int dx = -pointRadius; dx <= pointRadius; dx++) {
int nx = x + dx;
int ny = y + dy;
if (nx >= 0 && nx < width && ny >= 0 && ny < height) {
// 如果是圆形区域内
if (dx*dx + dy*dy <= pointRadius*pointRadius) {
image.setRGB(nx, ny, pixelColors[x][y].getRGB());
}
}
}
}
}
}
}
return image;
}
private static Color getColorFromDepth(double z, double zMin, double zMax) {
// 将 z 深度值映射到 0 到 1 范围
double normalizedDepth = (z - zMin) / (zMax - zMin);
// 根据深度值生成 RGB 颜色,从蓝色到红色的渐变
int red = (int) (normalizedDepth * 255);
int green = 0;
int blue = (int) ((1 - normalizedDepth) * 255);
return new Color(red, green, blue); // 伪彩色:蓝色到红色渐变
}
public static void saveImage(PcdPojo pojo, String filePath) {
// 计算pcd1
List<double[]> points = readPCD(pojo.getPcd1());
BufferedImage image =createImageFromPointCloud(points);
try {
// 使用 ImageIO 将图像保存为文件
File outputfile = new File(filePath);
ImageIO.write(image, "PNG", outputfile); // 可以选择 "PNG", "JPEG", "BMP" 等格式
System.out.println("图像已保存为:" + filePath);
} catch (IOException e) {
System.err.println("保存图像失败: " + e.getMessage());
}
}
/**
@ -518,11 +680,12 @@ public class PointCloudProcessor {
Core.normalize(image, normalizedImage, 0, 255, Core.NORM_MINMAX);
// 显示图像
HighGui.imshow("Depth Image", normalizedImage);
HighGui.waitKey();
HighGui.destroyAllWindows();
// HighGui.imshow("Depth Image", normalizedImage);
// HighGui.waitKey();
// HighGui.destroyAllWindows();
}
public List<BoxPositionConf> getBoxPositionConf(String path) {
//读取点云位置
ObjectMapper mapper = new ObjectMapper();

@ -1,26 +1,91 @@
package com.example.lxcameraapi.service.IndustrialCamera.camera.lx;
import com.example.lxcameraapi.conf.AppConfig;
import com.sun.jna.Native;
import com.sun.jna.ptr.PointerByReference;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class LxPointCloudSaveImage {
static DcLibrary INSTANCE1 = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi1.dll", DcLibrary.class);
static DcLibrary INSTANCE2 = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi2.dll", DcLibrary.class);
static DcLibrary INSTANCE3 = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi3.dll", DcLibrary.class);
static DcLibrary INSTANCE4 = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi4.dll", DcLibrary.class);
static Map<String ,DcLibrary> instanceMap = new ConcurrentHashMap<>();
static Map<String, PointerByReference> handleMap = new ConcurrentHashMap<>();
public static PointerByReference getHandle(String sn,int type ,DcLibrary INSTANCE){
public static boolean copyFileIfNotExists(String sourcePath, String destinationPath) {
Path destPath = Paths.get(destinationPath);
// 检查目标文件是否存在
if (Files.exists(destPath)) {
System.out.println("文件已存在: " + destinationPath);
return false;
}
try {
// 创建父目录(如果不存在)
Files.createDirectories(destPath.getParent());
// 复制文件
Files.copy(Paths.get(sourcePath), destPath, StandardCopyOption.REPLACE_EXISTING);
System.out.println("文件复制成功: " + sourcePath + " -> " + destinationPath);
return true;
} catch (IOException e) {
System.err.println("文件复制失败: " + e.getMessage());
return false;
}
}
public static void init(List<AppConfig.Camera> cameras){
for (AppConfig.Camera camera :cameras){
// 创建instance
copyFileIfNotExists((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi.dll",(System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi-"+camera.getId()+".dll");
instanceMap.put(camera.getIp(),(DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi-"+camera.getId()+".dll", DcLibrary.class));
// 创建 Pointer 的引用
PointerByReference handleRef = new PointerByReference();
DcLibrary INSTANCE = (DcLibrary) instanceMap.get(camera.getIp());
// 创建 PointerByReference 的实例用于接收设备列表
// PointerByReference devlistRef = new PointerByReference();
// 创建 LxDeviceInfo 实例
DcLibrary.LxDeviceInfo info = new DcLibrary.LxDeviceInfo();
//library.DcGetDeviceList( devlistRef,0);
// 调用 DcOpenDevice 函数
System.out.println(camera.getIp()+" "+handleRef+" "+info);
try {
int result = INSTANCE.DcOpenDevice(1, camera.getIp(), handleRef, info);
int i = 0;
if(result ==0) {
handleMap.put(camera.getIp(), handleRef);
}else {
for (int ii=0;i<50;i++ ) {
result = INSTANCE.DcOpenDevice(1, camera.getIp(), handleRef, info);
System.out.println(i + "次尝试");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}catch (Exception e){
log.error("没有连接成功",e);
}
}
}
public static PointerByReference getHandle(String sn ,DcLibrary INSTANCE){
if(handleMap.get(sn)!=null){
return handleMap.get(sn);
}else {
@ -52,40 +117,18 @@ public class LxPointCloudSaveImage {
}
}
}
// 输出结果
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) {
public static boolean saveImage(String sn, String path) {
DcLibrary INSTANCE = null;
if (type==1){
INSTANCE = INSTANCE1;
}else if (type==2){
INSTANCE = INSTANCE2;
}else if (type==3){
INSTANCE = INSTANCE3;
}else if (type==4){
INSTANCE = INSTANCE4;
if (instanceMap.get(sn)!= null){
INSTANCE = instanceMap.get(sn);
}
int result = 0;
PointerByReference handleRef = getHandle(sn,type,INSTANCE);
PointerByReference handleRef = getHandle(sn,INSTANCE);
result = INSTANCE.DcStartStream(handleRef.getValue());
System.out.println("Result: " + result);
result = INSTANCE.DcSetCmd(handleRef.getValue(),5001);
@ -110,9 +153,4 @@ public class LxPointCloudSaveImage {
return true;
}
public static void main(String[] args) {
saveImage("1","E:\\1-8-2-R.pcd",1);
saveImage("2","E:\\12-R.pcd",2);
}
}

@ -1,4 +0,0 @@
package com.example.lxcameraapi.service;
public class ll {
}

@ -8,87 +8,20 @@ server:
lxCamera:
- id: 1
ip: 10.141.128.205
# 切割配置
convertConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//cj.json"
# 位置配置
computeConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//pz.json"
streetId: "001"
- id: 2
ip: 10.141.128.222
# 切割配置
convertConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//cj.json"
# 位置配置
computeConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//pz.json"
streetId: "001"
- id: 3
ip: 10.141.128.202
# 切割配置
# 切割配置
convertConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//cj.json"
# 位置配置
computeConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//pz.json"
streetId: "002"
- id: 4
ip: 10.141.128.207
# 切割配置
convertConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//cj.json"
# 位置配置
computeConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//pz.json"
streetId: 002
hikCamera:
- ip: 172.16.10.52
id: 1
streetId: "001"
direction: 1
# 标定配置
calibratePath: "E://2d_img(1).config"
- ip: 10.141.128.221
id: 2
streetId: "001"
direction: 2
# 标定配置
calibratePath: "D://hzleaper_auto_install//cameraApi//2d_img.config"
- ip: 10.141.128.218
id: 3
streetId: "002"
# 1左2右
direction: 1
# 标定配置
calibratePath: "D://hzleaper_auto_install//cameraApi//2d_img.config"
- ip: 10.141.128.219
id: 4
streetId: "002"
direction: 2
# 标定配置
calibratePath: "D://hzleaper_auto_install//cameraApi//2d_img.config"
#模版地址,进入模版地址里的文件夹识别都识别成功则返回正确
templatePath: "E://"
#拍照地址
picPath: "D://data//pic//"
#宽比高
actualRectangularRatio: 1.6
threshold: 0.75
#异形
specialBox:
# 相机id
- cameraId: 1
# 品规
category: 20
# 个数地址
computeConfPath: "D://hzleaper_auto_install//cameraApi//F83B51125814//pz.json"
# 异形烟345160
- cameraId: 1
# 品规
category: 345160
# 个数地址
computeConfPath: "D://hzleaper_auto_install//cameraApi//345160//pz1.json"
- cameraId: 2
# 品规
category: 345160
# 个数地址
computeConfPath: "D://hzleaper_auto_install//cameraApi//345160//pz2.json"
# 图片保存裁剪路径,若不指定,则不保存图片
calibratePath: "E://pz.json"
# 切割配置。浅货位的配置若切割后个数多与500个则认为有个数
convertConfPath: "E://pz.json"
# 深度切割配置深货位配置若切割后个数多与500个则认为有个数
DeepConvertConfPath: "E://pz.json"
swagger:
enabled: true
enabled: true
deleteFile:
cron: "0/5 * * * * ?"
path:
- "D://go/deleteFile"
day: 7
Loading…
Cancel
Save