修改判断方法

泸州-视觉+扫码-昆船
LAPTOP-S9HJSOEB\昊天 8 months ago
parent 5b1688422e
commit ecbca1127f

@ -154,6 +154,12 @@ public class IndustrialCameraController {
}
@ApiOperation("直接上传")
@PostMapping("sendWithRetry")
public Result<String> sendWithRetry(@RequestBody IndustrialCameraVO industrialCameraVo) {
kuKouService.sendWithRetry(industrialCameraVo, true,0);
return Result.success("yes");
}
@ApiOperation("站点盘点")
@PostMapping("siteInventory")
public Result<KuKou> siteInventory(@RequestBody IndustrialCameraVO industrialCameraVo) {
@ -162,8 +168,15 @@ public class IndustrialCameraController {
Result<List<String>> listResult = pic();
boolean re = false;
//sick识别
String code = SickSocket.readOCR(configProperties.getCameraConfig().getSickIp(), configProperties.getCameraConfig().getSickPort());
Integer count = 0;
String code = "";
String pa = "";
try {
Thread.sleep(400);
code = SickSocket.readOCR(configProperties.getCameraConfig().getSickIp(), configProperties.getCameraConfig().getSickPort());
//2d识别
for (String path : listResult.getData()) {
re = FeatureMatchingExample.matchTemplate(
@ -185,21 +198,24 @@ public class IndustrialCameraController {
String pathPcd = configProperties.getSavePath().getMediaPath()
+ "camera3D/"
+ currentDate.format(formatter) + "/" + UUID.randomUUID() + "-";
int count = inventoryService.match3D(industrialCameraVo.getTypeMacth(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd","");
//3d识别
count = inventoryService.match3D(industrialCameraVo.getTypeMacth(), pathPcd + "-" + configProperties.getCameraConfig().getCamera3D() + ".pcd", "");
} catch (Exception e) {
log.error("识别异常", e);
}//3d识别
//保存信息
KuKou kuKou = new KuKou();
kuKou.setCreateTime(LocalDateTime.now());
kuKou.setCategoryName(industrialCameraVo.getTypeMacth());
if (re && count==industrialCameraVo.getCount() && code.endsWith(industrialCameraVo.getCode())) {
kuKou.setFlag(1);
}else kuKou.setFlag(0);
kuKou.setCount(count);
kuKou.setCode(code);
kuKou.setWmsCount(industrialCameraVo.getCount());
kuKou.setWmsCode(industrialCameraVo.getCode());
kuKou.setPath(configProperties.getSavePath().getNetPicPath() + pa + ".jpg");
kuKou.setCategoryName(industrialCameraVo.getTypeMacth());
if (re && count == industrialCameraVo.getCount() && code.endsWith(industrialCameraVo.getCode())) {
kuKou.setFlag(1);
} else kuKou.setFlag(0);
kuKouService.save(kuKou);
// serialPortExample.openLight(0);
return new Result<>(kuKou);

@ -58,7 +58,7 @@ public class KuKouService extends ServiceImpl<KukouMapper,KuKou> implements IS
CommandQueue.addCommand(scTransmission);
}
private void sendWithRetry(IndustrialCameraVO scTransmission, Boolean flag, int retryCount) {
public void sendWithRetry(IndustrialCameraVO scTransmission, Boolean flag, int retryCount) {
try {
HttpHeaders headers = new HttpHeaders();
headers.set("Content-Type", "application/json");

@ -5,6 +5,8 @@ package com.zhehekeji.web.service.RFID;
*
*/
public class CMD {
/**UHF mark to indicate the head of data package */
public final static byte HEAD = (byte) 0xA0;
public final static byte RESET = 0x70;
public final static byte SET_UART_BAUDRATE = 0x71;
public final static byte GET_FIRMWARE_VERSION = 0x72;

@ -111,6 +111,60 @@ public class RFIDSocket {
thread.start();
}
public void readData6C(){
running = true;
buffer = new LinkedList();
Thread thread = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true){
if(!running){
System.out.println("stop");
break;
}
int i = 0;
try {
//读不到会阻塞 返回-1表示连接已断开
i = is.read();
} catch (IOException e) {
log.error("disconnect");
}
if(i == -1){
break;
}
int count = 0;
try {
count = is.available();
if(count > 0){
//把之前read的字节嫁过来
byte[]readBytes = new byte[count+1];
readBytes[0] = (byte)i;
is.read(readBytes,1,count);
for(byte b:readBytes){
buffer.offer(b);
}
}
} catch (IOException e) {
log.error("");
}
while (buffer.size()> 0){
String code = readTag();
if(code != null){
tags.add(code);
}
}
}
}
});
thread.start();
}
private String readTag(){
String tag = null;
Byte b = buffer.poll();
@ -227,8 +281,10 @@ public class RFIDSocket {
}
public static void main(String[] args) throws IOException, InterruptedException {
RFIDSocket rfid = new RFIDSocket("172.16.0.220",4001);
RFIDSocket rfid = new RFIDSocket("127.0.0.1",5002);
rfid.startCheck();
rfid.readData();
Thread.sleep(30000);

@ -0,0 +1,434 @@
package com.zhehekeji.web.service.RFID;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.*;
/**
* sick
*/
@Slf4j
public class RFIDSocketNew {
public byte cmd;
private Socket socket;
private OutputStream os;
private InputStream is;
private Queue<Byte> buffer;
private boolean running;
private int step;
private int length;
private int index;
/**
* code
*/
private Set<String> tags = new HashSet<>();
private List<Byte> byteList = new ArrayList<>(30);
public Set<String> getTags() {
return tags;
}
public RFIDSocketNew(String ip, int port, String cmd) {
if (cmd.equals("6C")) {
this.cmd = (byte) CMD.INVENTORY;
} else {
this.cmd = (byte) CMD.REAL_TIME_INVENTORY;
}
socket = new Socket();
os = null;
is = null;
try {
socket.connect(new InetSocketAddress(ip, port), 3000);
os = socket.getOutputStream();
is = socket.getInputStream();
} catch (IOException e) {
log.error("RFIDSocket time out,ip:{},info:{}", ip, e);
close();
}
}
public void startCheck() {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
int i = 0;
while (true) {
if (!running) {
break;
}
byte[] antChanges = new byte[6];
antChanges[0] = (byte) 0xa0;
antChanges[1] = (byte) 0x04;
antChanges[2] = (byte) 0x01;
antChanges[3] = (byte) 0x74;
if (i % 2 == 0) {
//切换天线 使用天线0
antChanges[4] = (byte) 0x00;
antChanges[5] = (byte) 0xe7;
} else {
//切换天线 使用天线1
antChanges[4] = (byte) 0x01;
antChanges[5] = (byte) 0xe6;
}
i++;
try {
os.write(antChanges);
Thread.sleep(10);
} catch (InterruptedException | IOException e) {
log.error("send cmd error:{}", e);
}
byte[] bytes = new byte[5];
bytes[0] = (byte) 0xa0;
bytes[1] = (byte) 0x03;
bytes[2] = (byte) 0x01;
bytes[3] = cmd;
bytes[4] = (byte) 0xac;
try {
os.write(bytes);
Thread.sleep(70);
} catch (InterruptedException | IOException e) {
log.warn("send rfid cmd error:{}", e);
}
}
}
});
thread.start();
}
public void readData() {
running = true;
buffer = new LinkedList();
Thread thread = new Thread(new Runnable() {
@SneakyThrows
@Override
public void run() {
while (true) {
if (!running) {
System.out.println("stop");
break;
}
int count = 0;
byte[] header = new byte[1];
byte[] lenBuf = new byte[1];
// 1. 读取头部0xA0
int headerRead = is.read(header);
if (headerRead == -1) {
System.out.println("连接已关闭或没有更多数据");
break;
}
if (header[0] != (byte) 0xA0) {
System.out.println("无效数据包头: 0x" + String.format("%02X", header[0]));
continue; // 跳过非有效数据包
}
// 2. 读取长度字段
int lenRead = is.read(lenBuf);
if (lenRead == -1) {
System.out.println("连接中断,无法读取长度字段");
break;
}
int dataLength = lenBuf[0] & 0xFF; // 将byte转为无符号int
// 3. 读取data部分
int totalRead = 0;
// 3. 构造完整数据包 bufferhead(1) + len(1) + data(dataLength)
byte[] fullPacket = new byte[1 + 1 + dataLength];
fullPacket[0] = (byte) 0xA0;
fullPacket[1] = lenBuf[0];
// 4. 读取剩余部分data
while (totalRead < dataLength) {
int bytesRead = is.read(fullPacket, 2 + totalRead, dataLength - totalRead);
if (bytesRead == -1) {
System.out.println("连接中断,数据未完全读取");
break;
}
totalRead += bytesRead;
}
if (totalRead != dataLength) {
System.out.println("数据包不完整,跳过");
continue;
}
// 4. 成功读取一个完整数据包,可以进行处理
tags.add(parse(fullPacket));
}
}
});
thread.start();
}
private void clear() {
byteList.clear();
step = 0;
length = 0;
index = 0;
}
public void close() {
running = false;
try {
is.close();
socket.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
log.error("warn rfid close:{}", e);
}
}
//
// public static void main(String[] args) throws IOException, InterruptedException {
// RFIDSocketNew rfid = new RFIDSocketNew("127.0.0.1",5002);
// rfid.startCheck();
// rfid.readData();
// Thread.sleep(30000);
// rfid.close();
// System.out.println(rfid.getTags());
//// 03 01 B0 AC
//
// byte[]bytes = new byte[5];
// bytes[0] = (byte)0xa0;
// bytes[1] = (byte)0x03;
// bytes[2] = (byte)0x01;
// bytes[3] = (byte)0xb0;
// bytes[4] = (byte) calculateChecksum(bytes);
//// int b = ;
// System.out.println((byte)0xac);
// }
/**
* C
*
* @param buffer Check
* @return 0x00 ~ 0xFF int
*/
public static byte[] calculateChecksum(byte[] buffer) {
// 1. 创建子数组,排除最后一个字节
byte[] data = new byte[buffer.length - 1];
System.arraycopy(buffer, 0, data, 0, data.length);
// 2. 计算校验和
int sum = 0;
for (byte b : data) {
sum += b & 0xFF; // 转为无符号 int
}
sum &= 0xFF; // 取低8位
int checksum = (~sum + 1) & 0xFF; // 补码 + 屏蔽高位
// 3. 写入校验和到 buffer 最后一个位置
buffer[buffer.length - 1] = (byte) checksum;
return buffer;
}
public static boolean calculateCheck(byte[] buffer) {
int sum = 0;
for (int i = 0; i < buffer.length - 1; i++) {
sum += buffer[ i] & 0xFF; // 将 byte 转换为无符号 int0~255
}
sum &= 0xFF; // 取低8位
int checksum = (~sum + 1) & 0xFF; // 补码 + 屏蔽高位
return sum == buffer[buffer.length - 1];
}
/**
* RFID
*
* @param packet byte
*/
public static String parse6C(byte[] packet) {
if (packet == null || packet.length < 8) {
System.out.println("数据包为空或长度不足");
return "";
}
// Step 1: 检查 Head 是否为 0xA0
if (packet[0] != (byte) 0xA0) {
System.out.println("无效的数据包头: " + java.lang.String.format("%02X", packet[0]));
return "";
}
// Step 2: 获取 Len 字段
int len = packet[1] & 0xFF; // 不包含 Len 自身
if (packet.length != 2 + len) { // Head(1) + Len(1) + 数据(len) + Check(1)
System.out.println("数据包长度不匹配");
return "";
}
// Step 3: 验证校验和
if (!calculateCheck(packet)) {
System.out.println("校验失败,数据可能损坏");
return "";
}
// Step 4: 解析各个字段
int offset = 2; // Head + Len = 偏移2
byte address = packet[offset++];
byte cmd = packet[offset++];
byte freqAnt = packet[offset++];
// 提取 FreqAnt 的高6位频点 和 低2位天线号
int freqPoint = (freqAnt & 0xFC) >>> 2; // 高6位
int antennaNo = (freqAnt & 0x03); // 低2位
// Step 5: PC字段2字节
byte[] pcBytes = new byte[2];
System.arraycopy(packet, offset, pcBytes, 0, 2);
offset += 2;
// Step 6: RSSI1字节
byte rssiByte = packet[offset + 1];
int rssi = rssiByte & 0xFF; // 转无符号int
// Step 7: EPC剩余字段
int epcLength = len - 5; // Len - (Address + Cmd + FreqAnt + PC + RSSI)
byte[] epcBytes = new byte[epcLength];
System.arraycopy(packet, offset, epcBytes, 0, epcLength);
offset += epcLength;
// Step 8: 输出解析结果
System.out.println("Head: " + java.lang.String.format("%02X", packet[0] & 0xFF));
System.out.println("Len: " + len);
System.out.println("Address: " + java.lang.String.format("%02X", address & 0xFF));
System.out.println("Cmd: " + java.lang.String.format("%02X", cmd & 0xFF));
System.out.println("FreqAnt: " + java.lang.String.format("%02X", freqAnt & 0xFF));
System.out.println(" 频点: " + freqPoint);
System.out.println(" 天线号: " + antennaNo);
System.out.println("PC: " + bytesToHex(pcBytes));
System.out.println("EPC: " + bytesToHex(epcBytes));
System.out.println("RSSI: " + rssi + " dBm");
System.out.println("Check: " + java.lang.String.format("%02X", packet[packet.length - 1] & 0xFF));
return bytesToHex(epcBytes);
}
/**
* Check
*/
/**
* byte[] Hex
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(java.lang.String.format("%02X ", b & 0xFF));
}
return sb.toString().trim();
}
String parse(byte[] byteArray) {
if (byteArray == null ) {
return "";
}
if (cmd == CMD.REAL_TIME_INVENTORY) {
return parse6C(byteArray);
} else {
return parse6B(byteArray);
}
}
/**
* RFID
*
* @param packet byte
*/
public static String parse6B(byte[] packet) {
if (packet == null || packet.length < 8) { // 最小长度Head(1)+Len(1)+Address(1)+Cmd(1)+AntID(1)+UID(8)+Check(1)=12
System.out.println("数据包为空或长度不足");
return "";
}
// Step 1: 检查 Head 是否为 0xA0
if (packet[0] != (byte) 0xA0) {
System.out.println("无效的数据包头: " + java.lang.String.format("%02X", packet[0]));
return "";
}
// Step 2: 获取 Len 字段
int len = packet[1] & 0xFF; // 不包含 Len 自身
if (packet.length != 2 + len) { // Head(1) + Len(1) + 数据(len) + Check(1)
System.out.println("数据包长度不匹配");
return "";
}
// Step 3: 验证校验和
// if (!calculateCheck(packet)) {
// System.out.println("校验失败,数据可能损坏");
// return "";
// }
// Step 4: 解析各个字段
int offset = 2; // Head + Len = 偏移2
byte address = packet[offset++];
byte cmd = packet[offset++];
byte antId = packet[offset++];
// Step 5: UID8字节
byte[] uidBytes = new byte[8];
System.arraycopy(packet, offset, uidBytes, 0, 8);
offset += 8;
// Step 6: 输出解析结果
System.out.println("Head: " + java.lang.String.format("%02X", packet[0] & 0xFF));
System.out.println("Len: " + len);
System.out.println("Address: " + java.lang.String.format("%02X", address & 0xFF));
System.out.println("Cmd: " + java.lang.String.format("%02X", cmd & 0xFF));
System.out.println("AntID: " + java.lang.String.format("%02X", antId & 0xFF));
System.out.println("UID: " + bytesToHex(uidBytes));
System.out.println("Check: " + java.lang.String.format("%02X", packet[packet.length - 1] & 0xFF));
return bytesToHex(uidBytes);
}
public static void main(String[] args) {
// A0 0A FF 89 05 01 02 03 04 05 01
System.out.println(parse6B(calculateChecksum(new byte[]{(byte) 0xA0, 0x0C, (byte) 0xFF, (byte) 0xb0, 0x05, 0x01,0x01, 0x06, 0x01, 0x01, 0x01, 0x01, 0x01,0x00})));
RFIDSocketNew rfidSocket = new RFIDSocketNew("127.0.0.1", 6000,"6B");
// rfidSocket.startCheck();
rfidSocket.readData();
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
rfidSocket.close();
System.out.println(rfidSocket.getTags());
}
}

@ -23,6 +23,8 @@ import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
@ -81,10 +83,42 @@ public class InventoryService {
public int match3D(String category,String path,String configPath){
//拍照
log.info("3D拍照pcd "+path);
LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path,1);
List<Integer> results = new ArrayList<>();
for (int i = 0; i < 3; i++) {
String currentPath = path.replace(".pcd", "_" + i + ".pcd"); // 添加索引以区分不同次拍照的文件路径
LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), currentPath, 1);
Integer result = PointCloudProcessor.getBaijiuBox(
currentPath,
configProperties.getSavePath().getCroppingPath(),
configProperties.getSavePath().getWinePreparationPath() + category + ".json"
);
results.add(result);
if (i >= 1 && results.get(i).equals(results.get(i - 1))) {
// 如果当前结果与上一次结果相同,则直接返回
return results.get(i);
}
if (i == 2) {
// 第三次拍照后检查是否有两个相同的结果
return results.get(2);
}
try {
Thread.sleep(300*(i+1)); // 间隔300ms
} catch (InterruptedException e) {
log.error("线程休眠异常", e);
}
}
return results.get(results.size() - 1);
return PointCloudProcessor.getBaijiuBox(path,configProperties.getSavePath().getCroppingPath(),configProperties.getSavePath().getWinePreparationPath()+category+".json");
// return PointCloudProcessor.getBaijiuBox(path,configProperties.getSavePath().getCroppingPath(),configProperties.getSavePath().getWinePreparationPath()+category+".json");
}

@ -17,8 +17,6 @@ import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import static com.zhehekeji.web.service.algorithm.PointToImageMapper.drawPointsAndCalculateArea;
@Slf4j
public class PointCloudProcessor {
@ -449,7 +447,7 @@ public class PointCloudProcessor {
}
log.info("读取配置文件pcdPojo:"+pcdPojo.toString());
return getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType());
return PointToImageMapper.getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType());
}
@ -628,6 +626,8 @@ public class PointCloudProcessor {
private static int getLongitudinalType(List<double[]> points, PcdPojo pojo, int l, int w, int height,String type){
//pojo里面的floorHeight为地板的值以后所有的height都将根据地板值进行计算地板值减去当前点的z轴值为高度且当为height的倍数的时候认为是有效的点其中1倍的冗余在50mm每高一层冗余增加20mm
// 计算
System.load(new File(System.getProperty("user.dir")+"\\libs\\opencv_java480.dll").getAbsolutePath());
System.out.println("新方法调用");
double baseTolerance = 50; // 初始冗余 50mm
double additionalTolerancePerLevel = 20; // 每层增加 20mm 冗余
@ -691,42 +691,88 @@ public class PointCloudProcessor {
}
public static void main(String[] args) {
String path ="E:\\泸州\\27\\40016743\\30,31\\d970c134-98ff-4e7a-b951-b2cbdf9acfd4--192.168.56.11.pcd";
String configPath = "E:\\泸州\\27\\27.json";
String typeConfPath = "E:\\泸州\\27\\temlent\\40016743.json";
List<double[]> points = readPCD(path);
PcdPojo pojo = new PcdPojo();
PcdPojo pcdPojo = new PcdPojo();
pojo.setConfigPath(configPath);
ObjectMapper mapper = new ObjectMapper();
try {
// 读取 JSON 文件并转换为 配置信息
PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class));
// 打印转换后的实体类列表
pojo = pojo.setPCDInfo(pojoIn);
// 读取 JSON 文件并转换为 配置信息
pcdPojo = mapper.readValue(new File(typeConfPath), mapper.getTypeFactory().constructType(PcdPojo.class));
String configPath = "E:\\工作\\pcd\\27.json";
File rootFolder = new File("E:\\pr3d\\新建文件夹\\4-2"); // 替换为你自己的路径
// 调用处理方法
processAllSubFolders(rootFolder,configPath);
}
// 20 47 16
/**
* .pcd .json
*/
public static void processAllSubFolders(File folder,String configPath) {
if (!folder.exists() || !folder.isDirectory()) {
System.out.println("无效目录: " + folder.getAbsolutePath());
return;
}
//报错则认为没有配置文件,返回盘点失败
} catch (JsonMappingException e) {
e.printStackTrace();
// 获取所有子文件夹和文件
File[] files = folder.listFiles();
} catch (JsonProcessingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
if (files == null) return;
for (File file : files) {
if (file.isDirectory()) {
// 如果是子文件夹,继续递归
processAllSubFolders(file,configPath);
}
}
// int i = getLongitudinalType(points,pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType());
// 在当前文件夹中查找 pcd 和 json 文件
File pcdFile = null;
File jsonFile = null;
int i = PointToImageMapper.getLongitudinalType(points,pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(),pcdPojo.getArrangeType());
for (File file : files) {
if (file.isFile()) {
if (file.getName().endsWith(".pcd")) {
pcdFile = file;
} else if (file.getName().endsWith(".json")) {
jsonFile = file;
}
}
}
// 如果两个文件都存在,则执行你的逻辑
if (pcdFile != null && jsonFile != null) {
// System.out.println("原个数"+folder.getName());
System.out.println(i);
int count = adfadasdf(pcdFile.getAbsolutePath(),jsonFile.getAbsolutePath(),configPath);
if (count != Integer.parseInt(folder.getName().split("_")[1])){
System.out.println("个数有问题 index:"+folder.getName().split("_")[0]+" 记录数量:"+folder.getName().split("_")[1]
+" 计算数量:"+count+" pcd位置"+pcdFile.getAbsolutePath());
}
} else {
// 可选:打印缺失文件的信息
// System.out.println("缺少 pcd 或 json 文件: " + folder.getAbsolutePath());
}
}
static int adfadasdf(String pcdPath, String jsonPath, String configPath){
try {
List<double[]> points = readPCD(pcdPath);
PcdPojo pojo = new PcdPojo();
PcdPojo pcdPojo = new PcdPojo();
ObjectMapper mapper = new ObjectMapper();
// 读取 JSON 配置
PcdPojo pojoIn = mapper.readValue(new File(configPath), mapper.getTypeFactory().constructType(PcdPojo.class));
pojo = pojo.setPCDInfo(pojoIn);
pcdPojo = mapper.readValue(new File(jsonPath), mapper.getTypeFactory().constructType(PcdPojo.class));
// 调用你的方法
int result = PointToImageMapper.getLongitudinalType(points, pojo, pcdPojo.getWidth(), pcdPojo.getLength(), pcdPojo.getHigh(), pcdPojo.getArrangeType());
return result;
} catch (Exception e) {
// System.err.println("处理失败: " + folderPath + ",错误信息: " + e.getMessage());
e.printStackTrace();
}
return 0;
}

@ -1,4 +1,7 @@
package com.zhehekeji.web.service.algorithm;
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.springframework.stereotype.Service;
import java.awt.*;
@ -31,7 +34,7 @@ public class PointToImageMapper {
public static int getLongitudinalType(List<double[]> points, PcdPojo pojo, int l, int w, int height,String type){
//pojo里面的floorHeight为地板的值以后所有的height都将根据地板值进行计算地板值减去当前点的z轴值为高度且当为height的倍数的时候认为是有效的点其中1倍的冗余在50mm每高一层冗余增加20mm
// 计算
System.out.println("新方法调用");
// System.out.println("新方法调用");
double baseTolerance = 50; // 初始冗余 50mm
double additionalTolerancePerLevel = 20; // 每层增加 20mm 冗余
Map<Integer, List<double[]>> map = new HashMap<>();
@ -78,21 +81,53 @@ public class PointToImageMapper {
layersCount +=maxL;
}
}
int count = 0;
// for (int h =1; h<=5; h++){
// if (map.containsKey(h) && map.get(h).size()>1000){
// double area = 0;
// try {
// List<double[]> pointsLayers = map.get(h);
// if (map.containsKey(h+1)&& map.get(h+1).size()>1000){
// pointsLayers.addAll(map.get(h+1));
// }
//
// area = drawPointsAndCalculateArea(pointsLayers, String.valueOf(h),pojo,l,w);
//
// } catch (Exception e) {
// throw new RuntimeException(e);
// }
// if (area>0){
// System.out.println("面积:"+area);
// System.out.println("个数:"+area/(double) (l*w));
// int i =(int) Math.min(Math.round(area/(double) (l*w)),layersCount);
// if (i==0|| i>=layersCount) {
// count+=layersCount;
// }else {
// return i +count;
// }
// }
// }else {
//
// count+=layersCount;
// }
// }
for (int h =5; h>0; h--){
if (map.containsKey(h) && map.get(h).size()>1000){
double area = 0;
try {
area = drawPointsAndCalculateArea(map.get(h), String.valueOf(h),pojo);
area = drawPointsAndCalculateArea(map.get(h), String.valueOf(h),pojo,l,w);
} catch (Exception e) {
throw new RuntimeException(e);
}
if (area>0){
System.out.println("面积:"+area);
System.out.println("个数:"+area/(double) (l*w));
int i =(layersCount*(h-1))+(int) Math.min(Math.round(area/(double) (l*w)),layersCount);
return i;
// System.out.println("面积:"+area);
// System.out.println("个数:"+area/(double) (l*w));
int i =(int) Math.min(Math.round(area/(double) (l*w)),layersCount);
if (i>0) {
return (layersCount * (h - 1)) + i;
}
}
}
}
@ -104,10 +139,11 @@ public class PointToImageMapper {
*
*/
public static Double drawPointsAndCalculateArea(
List<double[]> points,String taskId,PcdPojo pojo
List<double[]> points,String taskId,PcdPojo pojo,
int l,int w
) throws Exception {
int imageWidth = 600;
int imageHeight = 600;
int imageWidth = 1200;
int imageHeight = 1200;
String drawMode= "point";
if (points == null || points.isEmpty()) {
@ -142,7 +178,7 @@ public class PointToImageMapper {
g.setBackground(Color.WHITE);
g.clearRect(0, 0, imageWidth, imageHeight);
// Step 5: 绘制点或连线
// Step 5: 绘制点
List<PointColorMapping> mappedPoints = new ArrayList<>();
for (double[] point : points) {
@ -203,8 +239,120 @@ public class PointToImageMapper {
// 可选:保存图像
ImageIO.write(image, "PNG", generateImageFilePath().toFile());
// int targetWidth = (int) (scaleX*l); // 替换为你想放置的矩形宽度(像素)
// int targetHeight = (int) (scaleY*w); // 替换为你想放置的矩形高度(像素)
//
// // 调用纯 Java 实现的矩形检测方法
// int maxRectangles = detectMaxRectanglesWithRotationJavaOnly(image, targetWidth, targetHeight);
// System.out.println("最大可容纳矩形数量:" + maxRectangles);
// 可选:删除临时文件
// tempFile.delete();
return area;
}
/**
* 使 Java
*
* @param bufferedImage BufferedImage
* @param targetWidth
* @param targetHeight
* @return
*/
public static int detectMaxRectanglesWithRotationJavaOnly(BufferedImage bufferedImage, int targetWidth, int targetHeight) {
int width = bufferedImage.getWidth();
int height = bufferedImage.getHeight();
// Step 1: 提取红色区域RGB > 200, G/B < 50
boolean[][] redMask = new boolean[width][height];
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int rgb = bufferedImage.getRGB(x, y);
int r = (rgb >> 16) & 0xFF;
int g = (rgb >> 8) & 0xFF;
int b = rgb & 0xFF;
redMask[x][y] = (r > 200 && g < 50 && b < 50);
}
}
// Step 2: 连通区域标记8邻域
int[][] labels = new int[width][height];
int labelCount = 0;
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (redMask[x][y] && labels[x][y] == 0) {
labelCount++;
floodFillJavaOnly(redMask, labels, x, y, labelCount);
}
}
}
// Step 3: 收集每个区域的边界框
Map<Integer, int[]> regionBounds = new HashMap<>();
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
int label = labels[x][y];
if (label > 0) {
int finalX = x;
int finalY = y;
regionBounds.computeIfAbsent(label, k -> new int[]{finalX, finalY, finalX, finalY});
int[] bounds = regionBounds.get(label);
bounds[0] = Math.min(bounds[0], x);
bounds[1] = Math.min(bounds[1], bounds[1]);
bounds[2] = Math.max(bounds[2], x);
bounds[3] = Math.max(bounds[3], y);
}
}
}
// Step 4: 判断每个区域是否能容纳目标矩形
int count = 0;
for (int[] bounds : regionBounds.values()) {
int regionWidth = bounds[2] - bounds[0];
int regionHeight = bounds[3] - bounds[1];
double margin = 0.90;
if ((regionWidth >= targetWidth * margin && regionHeight >= targetHeight * margin) ||
(regionHeight >= targetWidth * margin && regionWidth >= targetHeight * margin)) {
// 引入 margin 控制可用空间(比如留出 5% 边距)
int usableWidth = (int) (Math.min(regionWidth, regionHeight) * margin);
int usableHeight = (int) (Math.max(regionWidth, regionHeight) * margin);
int numWidth = usableWidth / Math.min(targetWidth, targetHeight);
int numHeight = usableHeight / Math.max(targetWidth, targetHeight);
count += numWidth * numHeight;
}
}
return count;
}
/**
*
*/
private static void floodFillJavaOnly(boolean[][] redMask, int[][] labels, int startX, int startY, int label) {
Queue<int[]> queue = new LinkedList<>();
queue.offer(new int[]{startX, startY});
labels[startX][startY] = label;
while (!queue.isEmpty()) {
int[] point = queue.poll();
int x = point[0];
int y = point[1];
for (int dy = -1; dy <= 1; dy++) {
for (int dx = -1; dx <= 1; dx++) {
int nx = x + dx;
int ny = y + dy;
if (nx >= 0 && nx < redMask.length &&
ny >= 0 && ny < redMask[0].length &&
redMask[nx][ny] && labels[nx][ny] == 0) {
labels[nx][ny] = label;
queue.offer(new int[]{nx, ny});
}
}
}
}
}
/**
* E:/data/pcdImage/yyyy-MM-dd/HHmmssSSS.png
*

Loading…
Cancel
Save