工业相机拍照

库口信息保存查询
深货位拍照识别
3D未完全实现
泸州-视觉+扫码-昆船
LAPTOP-S9HJSOEB\昊天 1 year ago
parent 29b826657c
commit ec77871c28

@ -37,6 +37,22 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>MvCameraControlWrapper</groupId>
<artifactId>MvCameraControlWrapper</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/libs/MvCameraControlWrapper.jar</systemPath>
</dependency>
<!-- opencv-->
<dependency>
<groupId>org</groupId>
<artifactId>opencv</artifactId>
<scope>system</scope>
<version>1.0</version>
<systemPath>${project.basedir}/src/main/resources/libs/opencv-480.jar</systemPath>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
@ -102,6 +118,14 @@
<includeSystemScope>true</includeSystemScope>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>9</source>
<target>9</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

@ -1,5 +1,6 @@
package com.zhehekeji.web.config;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@ -88,6 +89,10 @@ public class ConfigProperties {
private Long delayDownloadMp4;
public Integer verticalAdjustmentTime = 2;
private String industrialCamera;
private String camera3D;
}
@Data

@ -0,0 +1,165 @@
package com.zhehekeji.web.controller;
import com.zhehekeji.core.pojo.Result;
import com.zhehekeji.web.config.ConfigProperties;
import com.zhehekeji.web.entity.Street;
import com.zhehekeji.web.pojo.IndustrialCameraVO;
import com.zhehekeji.web.pojo.stock.CheckLogSearch;
import com.zhehekeji.web.service.IndustrialCamera.HikSaveImage;
import com.zhehekeji.web.service.IndustrialCamera.LxPointCloudSaveImage;
import com.zhehekeji.web.service.PlcService;
import com.zhehekeji.web.service.StreetService;
import com.zhehekeji.web.service.algorithm.FeatureMatchingExample;
import com.zhehekeji.web.service.algorithm.InventoryService;
import com.zhehekeji.web.service.algorithm.PcdPojo;
import com.zhehekeji.web.service.algorithm.PointCloudProcessor;
import com.zhehekeji.web.service.client.TransmissionPojo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
import static com.zhehekeji.web.service.algorithm.FeatureMatchingExample.base642Mat;
@Slf4j
@Api(tags = "工业相机")
@RequestMapping("/industrialCamera")
@RestController
public class IndustrialCameraController {
@Resource
HikSaveImage hikSaveImage;
@Resource
StreetService streetService;
@Resource
PlcService plcService;
@Resource
ConfigProperties configProperties;
@ApiOperation("拍照")
@PostMapping("pic")
public Result<String> pic(@RequestBody CheckLogSearch checkLogSearch){
Street street = streetService.streetById(checkLogSearch.getStreetId());
if(configProperties.getCameraConfig().getIndustrialCamera()!=null) {
String path = "industrialCamera/" + UUID.randomUUID() + ".jpeg";
hikSaveImage.saveImage(configProperties.getCameraConfig().getIndustrialCamera(), configProperties.getSavePath().getMediaPath() + path, "sn");
return new Result<>(path);
}else {
return new Result<>("");
}
}
@ApiOperation("识别")
@PostMapping("Macth")
public Result<String> Macth(@RequestBody IndustrialCameraVO industrialCameraVo){
String srcImg = configProperties.getSavePath().getMediaPath() + industrialCameraVo.getPicImg();
String srcImgRest = configProperties.getSavePath().getMediaPath() + industrialCameraVo.getPicImg();
//识别结果
boolean re = FeatureMatchingExample.matchTemplate(
InventoryService.readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + industrialCameraVo.getTypeMacth()),
srcImg);
if (re){
return new Result<>(industrialCameraVo.getPicImg()+".jpg");
}else {
return new Result<>("");
}
}
@ApiOperation("识别3D")
@PostMapping("Macth3D")
public Result<Integer> Macth3D(@RequestBody IndustrialCameraVO industrialCameraVo){
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//路径
String pathPcd = configProperties.getSavePath().getMediaPath()
+"camera3D/"
+currentDate.format(formatter)+"/" +UUID.randomUUID()+"-";
Integer count = inventoryService.match3D(industrialCameraVo.getName(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd");
return Result.success(count);
}
@Resource
InventoryService inventoryService;
//
// @ApiOperation("匹配所有")
// @PostMapping("matchFeatures")
// public Boolean matchFeatures(@RequestBody TransmissionPojo transmissionPojo) {
// //return true;
//
// return null;
// }
//
// @ApiOperation("随行")
// @PostMapping("actionType")
// public void action(@RequestBody TransmissionPojo transmissionPojo) {
//
// Street street = streetService.getStreetByPlcId(transmissionPojo.getStreetNumber());
//
//
// //随行地址
// String pcdPath1 =configProperties.getSavePath().getMediaPath() + street.getLeft3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-L"+".pcd";
//
// String pcdPath2 =configProperties.getSavePath().getMediaPath() + street.getRight3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-R"+".pcd";
// //拍照
// System.out.println(street.getLeft3D()+" 111211 "+ pcdPath1);
// LxPointCloudSaveImage lxPointCloudSaveImage = new LxPointCloudSaveImage();
// lxPointCloudSaveImage.saveImage(street.getLeft3D(), pcdPath1,1);
//
// LxPointCloudSaveImage lxPointCloudSaveImage1 = new LxPointCloudSaveImage();
// lxPointCloudSaveImage1.saveImage(street.getRight3D(), pcdPath2,2);
// }
// @ApiOperation("模板建立")
// @PostMapping("MacthCreate")
// public Result<Boolean> MacthCreate(@RequestBody IndustrialCameraVO industrialCameraVo){
// Path folder = Paths.get(configProperties.getSavePath().getMediaPath()+"template/"+industrialCameraVo.getTypeMacth());
// try {
// Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
// @Override
// public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
// Files.delete(file);
// return FileVisitResult.CONTINUE;
// }
//
// @Override
// public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
// Files.delete(dir);
// return FileVisitResult.CONTINUE;
// }
// });
// } catch (IOException e) {
// e.printStackTrace();
// }
// for (int i = 0; i < industrialCameraVo.getFileList().size(); i++){
// try {
// Mat template = base642Mat(industrialCameraVo.getFileList().get(i).getThumbUrl()
// .replace("data:image/jpeg;base64,","").replace("data:image/png;base64,",""));
//
// Imgcodecs.imwrite(configProperties.getSavePath().getMediaPath()+"template/"+industrialCameraVo.getTypeMacth()+"/"+i+".jpg", template);
// } catch (IOException e) {
// throw new RuntimeException(e);
// }
// }
// return new Result<>(true);
// }
}

@ -1,11 +1,45 @@
package com.zhehekeji.web.controller;
import com.github.pagehelper.PageInfo;
import com.zhehekeji.core.pojo.Result;
import com.zhehekeji.web.entity.KuKou;
import com.zhehekeji.web.pojo.OrderSearch;
import com.zhehekeji.web.pojo.OrderVO;
import com.zhehekeji.web.service.KuKouService;
import com.zhehekeji.web.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
@Api(tags = "盘点统计")
@RequestMapping("/KuKouController")
@RestController
public class KuKouController {
@Resource
private KuKouService kuKouService;
@Resource
private OrderService orderService;
@PostMapping("/list")
@ApiOperation(value = "查询")
//@SessionHandler
public Result<PageInfo<KuKou>> list(@RequestBody OrderSearch orderSearch) {
//validatorUtil.validate(orderSearch);
return Result.success(kuKouService.pageInfo(orderSearch));
}
@PostMapping("/latest")
@ApiOperation(value = "最新数据")
//@SessionHandler
public Result<KuKou> latest() {
//validatorUtil.validate(orderSearch);
return Result.success(kuKouService.latest());
}
}

@ -1,5 +1,7 @@
package com.zhehekeji.web.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
@ -9,10 +11,13 @@ import java.time.LocalDateTime;
@TableName("kukou")
@Data
public class KuKou {
@TableId(type = IdType.UUID)
private int id;
private int count;
private String code;
private String path;
private int flag;
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss")
private LocalDateTime createTime;

@ -57,4 +57,6 @@ public class Street {
private Integer videoStyleRow;
private Integer videoStyleColumn;
}

@ -0,0 +1,8 @@
package com.zhehekeji.web.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.zhehekeji.web.entity.EmptyCheckPic;
import com.zhehekeji.web.entity.KuKou;
public interface KukouMapper extends BaseMapper<KuKou> {
}

@ -0,0 +1,17 @@
package com.zhehekeji.web.pojo;
import lombok.Data;
import java.util.List;
@Data
public class IndustrialCameraVO {
private String name;
private String picImg;
private String typeMacth;
//private List<ImgFile> fileList;
private String pcdPath;
private String streetId;
}

@ -0,0 +1,12 @@
package com.zhehekeji.web.service.IndustrialCamera;
public interface CameraSaveUtil {
/**
*
* @param sn sn
* @param path
* @param type sn ip
* @return
*/
boolean saveImage(String sn,String path,String type);
}

@ -0,0 +1,50 @@
package com.zhehekeji.web.service.IndustrialCamera;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.Structure;
import com.sun.jna.ptr.PointerByReference;
import java.util.Arrays;
import java.util.List;
public interface DcLibrary extends Library {
DcLibrary INSTANCE = (DcLibrary) Native.load((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApiR.dll", DcLibrary.class);
// 创建一个新的实例
// 设备详细信息结构体
class LxDeviceInfo extends Structure {
public long handle; // 使用 long 类型表示 DcHandle
public short dev_type;
public byte[] id = new byte[32];
public byte[] ip = new byte[32];
public byte[] sn = new byte[32];
public byte[] mac = new byte[32];
public byte[] firmware_ver = new byte[32];
public byte[] algor_ver = new byte[32];
public byte[] name = new byte[32];
public byte[] reserve = new byte[32];
public byte[] reserve2 = new byte[32];
public byte[] reserve3 = new byte[64];
public byte[] reserve4 = new byte[128];
@Override
protected List<String> getFieldOrder() {
return Arrays.asList("handle", "dev_type", "id", "ip", "sn", "mac", "firmware_ver", "algor_ver", "name", "reserve", "reserve2", "reserve3", "reserve4");
}
}
// 设备打开函数
int DcOpenDevice(int open_mode, String param, PointerByReference handle, LxDeviceInfo info);
String DcGetDeviceList(PointerByReference devlist, int devnum);
int DcCloseDevice(Pointer handle);
int DcStartStream(Pointer handle);
int DcStopStream(Pointer handle);
int DcSaveXYZ(Pointer handle, String filename);
int DcSetCmd(Pointer handle, int cmd);
}
// Define LX_OPEN_MODE as an enum or int based on your C definition

@ -0,0 +1,321 @@
package com.zhehekeji.web.service.IndustrialCamera; /***************************************************************************************************
* @file SaveImage.java
* @breif Use functions provided in MvCameraControlWrapper.jar to save image as JPEG
* @author zhanglei72
* @date 2020/02/10
*
* @warning
* @version V1.0.0 2020/02/10 Create this file
* @since 2020/02/10
**************************************************************************************************/
import MvCameraControlWrapper.*;
import org.springframework.stereotype.Service;
import javax.annotation.PreDestroy;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import static MvCameraControlWrapper.MvCameraControl.*;
import static MvCameraControlWrapper.MvCameraControlDefines.*;
@Service
public class HikSaveImage implements CameraSaveUtil{
// 设备句柄保存
static Map<String,Handle> handleMap = new ConcurrentHashMap<>();
private static void printDeviceInfo(MV_CC_DEVICE_INFO stDeviceInfo)
{
if (null == stDeviceInfo) {
System.out.println("stDeviceInfo is null");
return;
}
if (stDeviceInfo.transportLayerType == MV_GIGE_DEVICE) {
System.out.println("\tCurrentIp: " + stDeviceInfo.gigEInfo.currentIp);
System.out.println("\tserialNumber: " + stDeviceInfo.gigEInfo.serialNumber);
System.out.println("\tModel: " + stDeviceInfo.gigEInfo.modelName);
System.out.println("\tUserDefinedName: " + stDeviceInfo.gigEInfo.userDefinedName);
} else if (stDeviceInfo.transportLayerType == MV_USB_DEVICE) {
System.out.println("\tUserDefinedName: " + stDeviceInfo.usb3VInfo.userDefinedName);
System.out.println("\tSerial Number: " + stDeviceInfo.usb3VInfo.serialNumber);
System.out.println("\tDevice Number: " + stDeviceInfo.usb3VInfo.deviceNumber);
} else {
System.err.print("Device is not supported! \n");
}
System.out.println("\tAccessible: "
+ MvCameraControl.MV_CC_IsDeviceAccessible(stDeviceInfo, MV_ACCESS_Exclusive));
System.out.println("");
}
private static void printFrameInfo(MV_FRAME_OUT_INFO stFrameInfo)
{
if (null == stFrameInfo)
{
System.err.println("stFrameInfo is null");
return;
}
StringBuilder frameInfo = new StringBuilder("");
frameInfo.append(("\tFrameNum[" + stFrameInfo.frameNum + "]"));
frameInfo.append("\tWidth[" + stFrameInfo.width + "]");
frameInfo.append("\tHeight[" + stFrameInfo.height + "]");
frameInfo.append(String.format("\tPixelType[%#x]", stFrameInfo.pixelType.getnValue()));
System.out.println(frameInfo.toString());
}
public static void saveDataToFile(byte[] dataToSave, int dataSize, String fileName)
{
OutputStream os = null;
try
{
Path path = Paths.get(fileName);
// 检查文件是否存在
if (!Files.exists(path)) {
try {
// 创建所有父目录
Files.createDirectories(path.getParent());
} catch (IOException e) {
System.err.println("Failed to create file: " + e.getMessage());
}
} else {
System.out.println("File already exists: " + path);
}
// 创建文件
os = new FileOutputStream( fileName);
os.write(dataToSave, 0, dataSize);
System.out.println("SaveImage succeed.");
// Create directory
}
catch (IOException e)
{
e.printStackTrace();
}
finally
{
// Close file stream
try
{
os.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
}
public static int chooseCamera(ArrayList<MV_CC_DEVICE_INFO> stDeviceList,String sn ,String type)
{
if (null == stDeviceList)
{
return -1;
}
for(int i = 0; i < stDeviceList.size(); i++){
if(type.equals("sn") && sn.equals(stDeviceList.get(i).gigEInfo.serialNumber)){
return i;
}else if(type.equals("ip") && sn.equals(stDeviceList.get(i).gigEInfo.currentIp)){
return i;
}
}
return -1;
}
public static void main(String[] args)
{
HikSaveImage hikSaveImage = new HikSaveImage();
hikSaveImage.saveImage("00J51775660", "E:\\m\\55.bpm","sn");
}
@PreDestroy
void clean(){
for (Handle h :handleMap.values()){
// Stop grabbing
int nRet = MvCameraControl.MV_CC_StopGrabbing(h);
if (MV_OK != nRet)
{
System.err.printf("StopGrabbing fail, errcode: [%#x]\n", nRet);
break;
}
nRet = MvCameraControl.MV_CC_DestroyHandle(h);
if (MV_OK != nRet) {
System.err.printf("DestroyHandle failed, errcode: [%#x]\n", nRet);
}
}
}
@Override
public boolean saveImage(String sn, String path,String type) {
int nRet = MV_OK;
ArrayList<MV_CC_DEVICE_INFO> stDeviceList;
do
{
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!");
break;
}
}
catch (CameraControlException e)
{
System.err.println("Enumrate devices failed!" + e.toString());
e.printStackTrace();
break;
}
// choose camera
Handle hCamera = init(sn,stDeviceList,type);
// Create handle
// Get payload size
MVCC_INTVALUE stParam = new MVCC_INTVALUE();
nRet = MvCameraControl.MV_CC_GetIntValue(hCamera, "PayloadSize", stParam);
if (MV_OK != nRet)
{
System.err.printf("Get PayloadSize fail, errcode: [%#x]\n", nRet);
break;
}
// Get one frame
MV_FRAME_OUT_INFO stImageInfo = new MV_FRAME_OUT_INFO();
byte[] pData = new byte[(int)stParam.curValue];
nRet = MvCameraControl.MV_CC_GetOneFrameTimeout(hCamera, pData, stImageInfo, 1000);
while(true){
if(stImageInfo.height >0 && stImageInfo.width >0){
break;
}
}
if (MV_OK != nRet)
{
System.err.printf("GetOneFrameTimeout fail, errcode:[%#x]\n", nRet);
break;
}
System.out.println("GetOneFrame: ");
printFrameInfo(stImageInfo);
int imageLen = stImageInfo.width * stImageInfo.height * 3; // Every RGB pixel takes 3 bytes
byte[] imageBuffer = new byte[imageLen];
// Call MV_CC_SaveImage to save image as JPEG
MV_SAVE_IMAGE_PARAM stSaveParam = new MV_SAVE_IMAGE_PARAM();
stSaveParam.width = stImageInfo.width; // image width
stSaveParam.height = stImageInfo.height; // image height
stSaveParam.data = pData; // image data
stSaveParam.dataLen = stImageInfo.frameLen; // image data length
stSaveParam.pixelType = stImageInfo.pixelType; // image pixel format
stSaveParam.imageBuffer = imageBuffer; // output image buffer
stSaveParam.imageType = MV_SAVE_IAMGE_TYPE.MV_Image_Jpeg; // output image pixel format
stSaveParam.methodValue = 0; // Interpolation method that converts Bayer format to RGB24. 0-Neareast 1-double linear 2-Hamilton
stSaveParam.jpgQuality = 99; // JPG endoding quality(50-99]
nRet = MvCameraControl.MV_CC_SaveImage(hCamera, stSaveParam);
if (MV_OK != nRet)
{
System.err.printf("SaveImage fail, errcode: [%#x]\n", nRet);
break;
}
// Save buffer content to file
saveDataToFile(imageBuffer, imageLen, path);
} while (false);
return false;
}
Handle init(String sn, ArrayList<MV_CC_DEVICE_INFO> stDeviceList,String type){
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("未找到摄像头");
return null;
}
//未获得句柄并初始化
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);
return null;
}
// 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);
return null;
}
// 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);
return null;
}
}
}
catch (CameraControlException e)
{
System.err.println("Create handle failed!" + e.toString());
e.printStackTrace();
return null;
}
System.out.println(hCamera);
return hCamera;
}
}

@ -0,0 +1,106 @@
package com.zhehekeji.web.service.IndustrialCamera;
import com.sun.jna.Native;
import com.sun.jna.ptr.PointerByReference;
import lombok.extern.slf4j.Slf4j;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
public class LxPointCloudSaveImage {
static DcLibrary INSTANCER = (DcLibrary) Native.loadLibrary((System.getProperty("user.dir"))+"\\libs\\plc\\LxCameraApi.dll", DcLibrary.class);
static Map<String, PointerByReference> handleMap = new ConcurrentHashMap<>();
public static PointerByReference getHandle(String sn,int type ,DcLibrary INSTANCE){
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 = INSTANCE.DcOpenDevice(1, sn, handleRef, info);
int i = 0;
if(result ==0) {
handleMap.put(sn, handleRef);
}else {
for (int ii=0;i<50;i++ ) {
result = INSTANCE.DcOpenDevice(1, sn, handleRef, info);
System.out.println(i + "次尝试");
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;
int result = 0;
PointerByReference handleRef = getHandle(sn,type,INSTANCE);
result = INSTANCE.DcStartStream(handleRef.getValue());
System.out.println("Result: " + result);
result = INSTANCE.DcSetCmd(handleRef.getValue(),5001);
System.out.println("Result: " + result);
Path path1 = Paths.get(path);
try {
// 如果路径不存在,则创建目录
Files.createDirectories(path1.getParent());
}catch (Exception e){
log.info("路径失败");
}
int i = INSTANCE.DcSaveXYZ(handleRef.getValue(), path);
log.info(sn+" 3dCamera get pcd :"+path +";rest:"+i);
System.out.println(sn+" 3dCamera get pcd :"+path +";rest:"+i);
result = INSTANCE.DcStopStream(handleRef.getValue());
System.out.println("stop Stream Result: " + result);
return true;
}
public static void main(String[] args) {
saveImage("1","E:\\1-8-2-R.pcd",1);
saveImage("2","E:\\12-R.pcd",2);
}
}

@ -0,0 +1,32 @@
package com.zhehekeji.web.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.zhehekeji.web.entity.KuKou;
import com.zhehekeji.web.mapper.KukouMapper;
import com.zhehekeji.web.pojo.OrderSearch;
import com.zhehekeji.web.pojo.OrderVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
@Slf4j
public class KuKouService extends ServiceImpl<KukouMapper,KuKou> implements IService<KuKou> {
public PageInfo<KuKou> pageInfo(OrderSearch orderSearch){
PageHelper.startPage(orderSearch.getPageNum(), orderSearch.getPageSize());
List<KuKou> kuKous = list(new QueryWrapper<>());
return new PageInfo<>(kuKous);
}
public KuKou latest(){
KuKou kuKou = getOne(new QueryWrapper<KuKou>().orderByDesc("createTime").last("limit 1"));
return kuKou;
}
}

@ -15,7 +15,7 @@ public class PlcCmdInfo {
private String taskId;
/**
* 1 2
* 1 2plcCmdInfo
*/
private Integer side1;

@ -12,6 +12,7 @@ import com.zhehekeji.web.pojo.stock.StockStatus;
import com.zhehekeji.web.service.RFID.RFIDMap;
import com.zhehekeji.web.service.RFID.RFIDSocket;
import com.zhehekeji.web.entity.EmptyCheckPic;
import com.zhehekeji.web.service.algorithm.InventoryService;
import com.zhehekeji.web.service.client.ClientChanel;
import com.zhehekeji.web.service.client.TransmissionPojo;
import com.zhehekeji.web.service.ksec.KsecDataInfo;
@ -26,7 +27,9 @@ import org.springframework.util.StringUtils;
import javax.annotation.Resource;
import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
@ -42,6 +45,8 @@ import java.util.stream.Collectors;
@Service
@Slf4j
public class PlcService {
@Resource
KuKouService kuKouService;
@Resource
private OrderMapper orderMapper;
@ -80,6 +85,9 @@ public class PlcService {
@Resource
private CheckStreetSummaryMapper checkStreetSummaryMapper;
@Resource
private InventoryService inventoryService;
private static ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(1,8,200,TimeUnit.MINUTES,new ArrayBlockingQueue<>(100000));
public void setCameraControlModule(CameraControlModule cameraControlModule){
@ -332,6 +340,7 @@ public class PlcService {
}
//update order info after capture
if (path != null && needCapture) {
captureUpdateOrderAndStock(orderInfo, path);
}
//转向原点位
@ -347,7 +356,7 @@ public class PlcService {
@Resource
ReentrantLockExample reentrantLockExample;
String scan(PlcCmdInfo plcCmdInfo,Street street,String path){
String scan(PlcCmdInfo plcCmdInfo,Street street){
Boolean trayCheck = Boolean.FALSE;
String trayCode = "";
log.info("扫码类型:" + configProperties.getScanCodeMode().getTray());
@ -388,8 +397,29 @@ public class PlcService {
}
}
}else {
Integer cameraId;
String code = "E1-DEEP-";
String path = "";
//使用同侧的camera
if(plcCmdInfo.getLeftRight1() ==1){
cameraId = street.getCamera1Id();
code = code+"L";
}else {
cameraId = street.getCamera2Id();
code = code+"R";
}
path = PathUtil.createFileNameByRowColumn("jpg",cameraId,plcCmdInfo.getRow1(),plcCmdInfo.getColumn1());
gyrateCameraByCode(cameraId,code);
try {
Thread.sleep(1500L);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
path = cameraCapture(cameraId,false,0L,path);
trayCode = reentrantLockExample.identify(path,configProperties.getIntelliBink().getIp(),configProperties.getIntelliBink().getPort());
trayCode = reentrantLockExample.identify(path,configProperties.getIntelliBink().getIp(),configProperties.getIntelliBink().getPort());
if(trayCode != null && !"".equals(trayCode)){
if ("".equals(plcCmdInfo.getWmsCode())) {
//托盘码为空,无货物
@ -419,6 +449,31 @@ public class PlcService {
plcCmdInfo.setTrayCode(trayCode);
return trayCode;
}
public boolean checkVision(KsecDataInfo dataInfo){
KuKou kuKou = new KuKou();
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//路径
String path = configProperties.getSavePath().getMediaPath()
+"industrialCamera/"
+currentDate.format(formatter)+"/" +UUID.randomUUID()+"-";
//路径
String pathPcd = configProperties.getSavePath().getMediaPath()
+"camera3D/"
+currentDate.format(formatter)+"/" +UUID.randomUUID()+"-";
boolean flag2D =inventoryService.match2D(dataInfo.getCategoryName(),path+configProperties.getCameraConfig().getIndustrialCamera()+".jpeg");
int count = inventoryService.match3D(dataInfo.getCategoryName(),pathPcd+"-"+configProperties.getCameraConfig().getCamera3D()+".pcd");
kuKou.setCreateTime(LocalDateTime.now());
if (flag2D) {
kuKou.setFlag(1);
}
kuKou.setCode(dataInfo.getCategoryName());
kuKou.setCount(count);
kuKouService.save(kuKou);
return true;
}
public Boolean check(PlcCmdInfo plcCmdInfo,String cmdCode,String wmsCode,String wmsTrayCode,String wmsCatagary){
@ -526,69 +581,6 @@ public class PlcService {
}
Boolean trayGoodCheck = Boolean.TRUE;
//扫货物
if(configProperties.getScanCodeMode().getGoods() == 2) {
log.info("扫码类型:" + configProperties.getScanCodeMode().getTray());
//托盘使用sick扫码枪
SensorGun sensorGun = sensorService.getSensorByPlc(street.getId(), plcCmdInfo.getLeftRight1());
if (sensorGun == null) {
trayCode = "扫码枪识别异常";
trayGoodCheck = Boolean.FALSE;
log.error("no sensor gun config in database ,street id:{},direction:{}", street.getId(), plcCmdInfo.getLeftRight1());
} else {
trayCode = SickSocket.readOCR(sensorGun.getIp(), sensorGun.getPort());
log.info("sensor tray code:{}", trayCode);
if ("".equals(wmsTrayCode)) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
if (StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) {
trayCode = "";
trayGoodCheck = Boolean.TRUE;
} else {
trayCode = "扫码枪识别异常";
trayGoodCheck = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
}
} else {
if ((StringUtils.isEmpty(trayCode) || trayCode.equals("NoRead")) ){
trayCode = "扫码枪识别异常";
trayGoodCheck = Boolean.FALSE;
log.warn("sick ocr error:{}", trayCode);
} else if(trayCode.equals(wmsTrayCode)){
//扫到码
trayGoodCheck = Boolean.TRUE;
}else {
trayGoodCheck = Boolean.FALSE;
}
}
}
}else
if(configProperties.getScanCodeMode().getGoods() == 3){
Set<String> tags = new HashSet<>();
try {
RFIDCheck(plcCmdInfo);
Thread.sleep(1000 * configProperties.getRfid().getScanTime());
} catch (Exception e) {
e.printStackTrace();
} finally {
tags = RFIDStop(plcCmdInfo);
log.info("盘点rfid扫描结果" + tags);
}
if (tags !=null && tags.contains(wmsTrayCode)) {
//托盘码为空,无货物
//只要扫码枪未识别出条码,即认为盘点正确
trayCode = wmsTrayCode;
trayGoodCheck = Boolean.TRUE;
} else {
trayCode = trayCode+ "扫码枪识别异常";
trayGoodCheck = Boolean.FALSE;
log.warn("rfid error:{}", trayCode);
}
}
OrderInfo orderInfo = new OrderInfo(street, plcCmdInfo, 1, cmdCode);
Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(orderInfo.getStreetId(), plcCmdInfo.getLeftRight1(), orderInfo.getSeparation(), orderInfo.getRow(), orderInfo.getColumn());
@ -932,11 +924,7 @@ public class PlcService {
return true;
}
/**
*
* @param scTransmission
* @return
*/
// public Stock checkStart(SCTransmission scTransmission){
// log.info("【开始盘点货位】save stock info ,taskId:{},SRMNumber:{}goodsLocation:{}",scTransmission.getTaskNo(),scTransmission.getSRMNumber(),scTransmission.getGoodsLocation());
// Street street = streetService.getStreetByPlcId(scTransmission.getSRMNumber());

File diff suppressed because one or more lines are too long

@ -0,0 +1,215 @@
package com.zhehekeji.web.service.algorithm;
import com.zhehekeji.web.config.ConfigProperties;
import com.zhehekeji.web.entity.CheckLog;
import com.zhehekeji.web.entity.Stock;
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.LxPointCloudSaveImage;
import com.zhehekeji.web.service.PlcService;
import com.zhehekeji.web.service.StreetService;
import com.zhehekeji.web.service.client.TransmissionPojo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.io.File;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
@Service
@Slf4j
public class InventoryService {
@Resource
StreetService streetService;
@Resource
CameraSaveUtil cameraSaveUtil;
@Resource
ConfigProperties configProperties;
@Resource
CheckLogMapper checkLogMapper;
@Resource
StockMapper stockMapper;
@Resource
PlcService plcService;
public boolean match2D(String category,String path){
boolean flag = false;
//2d拍照并识别
cameraSaveUtil.saveImage(configProperties.getCameraConfig().getIndustrialCamera(),path,"sn");
log.info(configProperties.getCameraConfig().getIndustrialCamera()+" 2d拍照路径"+path);
if(category!=null && !category.equals("")) {
flag = FeatureMatchingExample.matchTemplate(
readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + category),
path );
log.info("2d识别结果"+flag);
}else {
log.info("未识别到任何模板");
}
return flag;
}
public int match3D(String category,String path){
LocalDate currentDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
Boolean flag = false;
//拍照
log.info("3D拍照pcd "+path);
LxPointCloudSaveImage.saveImage(configProperties.getCameraConfig().getCamera3D(), path,1);
return 30;
}
//
//
// public boolean matchFeatures(TransmissionPojo transmissionPojo){
// Street street = streetService.getStreetByPlcId(transmissionPojo.getStreetNumber());
//
// LocalDate currentDate = LocalDate.now();
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
// //路径
// String path = configProperties.getSavePath().getMediaPath()
// +"industrialCamera/"
// +transmissionPojo.getStreetNumber()+"/"
// +currentDate.format(formatter)+"/"
// +transmissionPojo.getRow()+"-"
// +transmissionPojo.getColumn()+"-"
// +transmissionPojo.getDirection()+"-";
// //结果
// transmissionPojo.setResult(1);
// //2d拍照并识别
// if(street != null&& street.getIndustrialCamera()!=null){
// cameraSaveUtil.saveImage(street.getIndustrialCamera(),path+street.getIndustrialCamera()+".jpeg","sn");
// log.info(street.getIndustrialCamera()+" 2d拍照路径"+path+street.getIndustrialCamera()+".jpeg");
// if(transmissionPojo.getCategory()!=null && !transmissionPojo.getCategory().equals("")) {
// boolean re = FeatureMatchingExample.matchTemplate(
// readImagesInFolder(configProperties.getSavePath().getMediaPath() + "template/" + transmissionPojo.getCategory()),
// path + street.getIndustrialCamera() + ".jpeg");
// log.info("2d识别结果"+re);
// if (!re) {
// transmissionPojo.setResult(0);
// }
// }else {
// transmissionPojo.setResult(0);
// log.info("未识别到任何模板");
// }
// }
// //3d拍照盘点
// //盘点地址
// String pcdPath1 =configProperties.getSavePath().getMediaPath() + street.getLeft3D()+ "/"+currentDate.format(formatter)+"/"+transmissionPojo.getCheckId()+".pcd";
// String pcdPath2 =configProperties.getSavePath().getMediaPath() + street.getRight3D()+ "/"+ currentDate.format(formatter)+"/"+transmissionPojo.getCheckId()+".pcd";
// //随行地址
// //随行地址
// String pcdPath3 =configProperties.getSavePath().getMediaPath() + street.getLeft3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-L"+".pcd";
//
// String pcdPath4 =configProperties.getSavePath().getMediaPath() + street.getRight3D()+"\\000\\"
// +transmissionPojo.getRow()+"-"+transmissionPojo.getColumn()+"-"+transmissionPojo.getDirection()+"-R"+".pcd";
//
// //拍照
// log.info("3D拍照 左侧pcd "+pcdPath1+" 右侧pcd: "+pcdPath2);
//
// LxPointCloudSaveImage.saveImage(street.getLeft3D(), pcdPath1,1);
//
// LxPointCloudSaveImage.saveImage(street.getRight3D(), pcdPath2,2);
// //左侧比较
// PcdPojo pojo = new PcdPojo();
// pojo.setPcd1(pcdPath1);
// pojo.setPcd2(pcdPath3);
// pojo.setConfigPath("D://config//3DConfig/"+street.getLeft3D()+".json");
// log.info("对比左侧:"+pojo.toString());
//
// double leftScore = PointCloudProcessor.similarity(pojo,10);
// log.info("3D leftScore"+leftScore);
//
// //右侧比较
// pojo.setPcd1(pcdPath2);
// pojo.setPcd2(pcdPath4);
// pojo.setConfigPath("D://config//3DConfig/"+street.getRight3D()+".json");
// log.info("对比右侧:"+pojo.toString());
//
// double rightScore = PointCloudProcessor.similarity( pojo,10);
//
// log.info("3D rightScore"+rightScore);
// if(leftScore<0.87||rightScore<0.87){
// transmissionPojo.setResult(0);
// }
// log.info("最终结果:"+transmissionPojo.getResult());
// CheckLog checkLog = checkLogMapper.selectById(transmissionPojo.getCheckId());
// plcService.visualCalculationResults(transmissionPojo,checkLog);
//
// Stock stock = stockMapper.getByStreetAndDirectionAndSideAndRowColumn(street.getId(), transmissionPojo.getDirection(),1, transmissionPojo.getRow(), transmissionPojo.getColumn());
//
// checkLogMapper.updateById(checkLog);
// if (stock == null) {
// stock = Stock.builder()
// .streetId(street.getId())
// .row(transmissionPojo.getRow())
// .column(transmissionPojo.getColumn())
// .direction(transmissionPojo.getDirection())
// .side(1)
// .statusVision(checkLog.getStatusVision())
// .count(checkLog.getCount())
// .category(checkLog.getCategory())
// .exportTime(LocalDateTime.now()).build();
// stockMapper.insert(stock);
// } else {
// stock.setStatusVision(checkLog.getStatusVision());
// stock.setCount(checkLog.getCount());
// stock.setCategory(checkLog.getCategory());
// stockMapper.updateById(stock);
// }
// return !(transmissionPojo.getResult()==0);
//
// };
//
//
//
/**
*
* @param folderPath
* @return
*/
public static List<String> readImagesInFolder(String folderPath) {
File folder = new File(folderPath);
List<String> list = new ArrayList<>();
// Check if the folder exists and is a directory
if (!folder.exists() || !folder.isDirectory()) {
log.info(folderPath);
log.info("The specified path is not a valid directory.");
return list;
}
// List all files in the folder that match the image filter
File[] imageFiles = folder.listFiles();
for(File imageFile : imageFiles){
if(!imageFile.isDirectory()) {
list.add(imageFile.getAbsolutePath());
log.info("Found image: " + imageFile.getAbsolutePath());
}
log.info("Found file: " + imageFile.getAbsolutePath());
}
return list;
}
public static void main(String[] args) {
}
}

@ -0,0 +1,77 @@
package com.zhehekeji.web.service.algorithm;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class PCDReader {
public static void main(String[] args) {
String filePath = "path/to/your/file.pcd";
try {
if (isBinaryFormat(filePath)) {
readBinaryPCD(filePath);
} else {
readAsciiPCD(filePath);
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static boolean isBinaryFormat(String filePath) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("DATA")) {
return line.contains("binary");
}
}
}
return false;
}
private static void readAsciiPCD(String filePath) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (!line.startsWith("#") && !line.startsWith("FIELDS") && !line.startsWith("SIZE") &&
!line.startsWith("TYPE") && !line.startsWith("COUNT") && !line.startsWith("WIDTH") &&
!line.startsWith("HEIGHT") && !line.startsWith("VIEWPOINT") && !line.startsWith("POINTS") &&
!line.startsWith("DATA")) {
String[] values = line.split(" ");
for (String value : values) {
System.out.println(value);
}
}
}
}
}
private static void readBinaryPCD(String filePath) throws IOException {
try (FileInputStream fis = new FileInputStream(filePath)) {
ByteBuffer buffer = ByteBuffer.wrap(fis.readAllBytes());
buffer.order(ByteOrder.LITTLE_ENDIAN);
// Skip header (assuming 11 lines of header; adjust if needed)
for (int i = 0; i < 11; i++) {
while (buffer.get() != '\n') {
// Skip header lines
}
}
// Read binary data (assuming float x, y, z and int rgb)
while (buffer.hasRemaining()) {
float x = buffer.getFloat();
float y = buffer.getFloat();
float z = buffer.getFloat();
int rgb = buffer.getInt(); // Read 4 bytes for RGB
System.out.printf("x: %f, y: %f, z: %f, rgb: %d%n", x, y, z, rgb);
}
}
}
}

@ -0,0 +1,42 @@
package com.zhehekeji.web.service.algorithm;
import lombok.Data;
@Data
public class PcdPojo {
double[][] rotationMatrix = {
{0.9982215762138367, 0.057795289903879166, 0.014606773853302002},
{-0.0510917492210865, 0.7032182216644287, 0.7091360092163086},
{0.030712969601154327, -0.7086211442947388, 0.7049204111099243}
}; // 这里使用给定的旋转矩阵
double[] minBounds = {-905.5771484375, 174.71572875976562, 69.14165496826172}; // 裁剪最小值
double[] maxBounds = {321.80609130859375, 1170.4776611328125, 1199.3507080078125}; // 裁剪最大值
private double floorHeight;
private double[] max_pt;
private double[] min_pt;
private double[] rotation;
//路径D://config//3DConfig/"+相机sn+".json"
private String configPath;
//盘点路径 configProperties.getSavePath().getMediaPath() + street.getLeft3D()+ currentDate.format(formatter)+"/"+transmissionPojo.getCheckId()+".pcd";
//随行路径 configProperties.getSavePath().getMediaPath() + street.getLeft3D()+"000/"+ currentDate.format(formatter)+"/"+transmissionPojo.getRow()+".pcd";
private String pcd1;
private String pcd2;
private String cameraSn1;
private String cameraSn2;
private Integer count;
PcdPojo setPCDInfo(PcdPojo pojo) {
this.setMinBounds(pojo.getMin_pt());
this.setMaxBounds(pojo.getMax_pt());
double[] x = {pojo.getRotation()[0], pojo.getRotation()[1], pojo.getRotation()[2]};
double[] y = {pojo.getRotation()[3], pojo.getRotation()[4], pojo.getRotation()[5]};
double[] z = {pojo.getRotation()[6], pojo.getRotation()[7], pojo.getRotation()[8]};
this.setRotationMatrix(new double[][]{x, y, z});
return this;
}
}

@ -0,0 +1,388 @@
package com.zhehekeji.web.service.algorithm;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class PointCloudProcessor {
public static void main(String[] args) {
PcdPojo pojo = new PcdPojo();
pojo.setPcd1("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\8-6-2-L.pcd");
pojo.setPcd2("D:\\WeChet\\WeChat Files\\wxid_ttkf0xgmyihv22\\FileStorage\\File\\2024-09\\369.pcd");
pojo.setConfigPath("E:\\D91FCF1FAB3568DB.json");
double i = similarity(pojo,10);
System.out.println("111 "+i);
}
/**
* pcd
*
* @param pojo pcd
* @return
*/
//计算两个pcd的相似性
public static double similarity(PcdPojo pojo) {
ObjectMapper mapper = new ObjectMapper();
try {
// 读取 JSON 文件并转换为 配置信息
PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class));
// 打印转换后的实体类列表
pojo = pojo.setPCDInfo(pojoIn);
//报错则认为没有配置文件,返回盘点失败
} catch (JsonMappingException e) {
e.printStackTrace();
return 0;
} catch (JsonProcessingException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
System.out.println(pojo.toString());
// 计算pcd1
List<double[]> points = readPCD(pojo.getPcd1());
if (points == null || points.isEmpty()) {
return 0;
}
// 创建一个DecimalFormat对象指定格式
DecimalFormat df = new DecimalFormat("#.#");
//map xyz
PcdPojo finalPojo = pojo;
Map<Double, Map<Double, Double>> clippedPoint = points.stream()
.map(point -> {
//旋转
return rotatePoints(point, finalPojo.getRotationMatrix());
})
.filter(point ->
//截取
clipPoints(point, finalPojo.getMinBounds(), finalPojo.getMaxBounds())
)//z轴截取
.collect(Collectors.groupingBy(point -> point[0], Collectors.toMap(point -> point[1], point -> point[2], (a, b) -> {
return a > b ? a : b;
})));
//计算xy轴平均值
Double xAge = clippedPoint.keySet().stream().collect(Collectors.averagingDouble(v -> v));
Double yAge = clippedPoint.values().stream().flatMap(map -> map.values().stream()).collect(Collectors.averagingDouble(v -> v));
//计算pcd2
List<double[]> points2 = readPCD(pojo.getPcd2());
if (points2 == null || points2.isEmpty()) {
return 0;
}
//map xyz
Map<Double, Map<Double, Double>> clippedPoint2 = points2.stream()
.map(point -> {
//旋转
return rotatePoints(point, finalPojo.getRotationMatrix());
})
.filter(point ->
//截取
clipPoints(point, finalPojo.getMinBounds(), finalPojo.getMaxBounds())
)//z轴截取
.collect(Collectors.groupingBy(point -> point[0], Collectors.toMap(point -> point[1], point -> point[2], (a, b) -> {
return a > b ? a : b;
})));
//计算xy轴平均值
Double xAge2 = clippedPoint2.keySet().stream().collect(Collectors.averagingDouble(v -> v));
Double yAge2 = clippedPoint2.values().stream().flatMap(map -> map.values().stream()).collect(Collectors.averagingDouble(v -> v));
//计算相似度
return (Math.abs(yAge) < Math.abs(yAge2) ? Math.abs(yAge) / Math.abs(yAge2) : Math.abs(yAge2) / Math.abs(yAge));
}
public static double similarity(PcdPojo pojo,int i) {
ObjectMapper mapper = new ObjectMapper();
try {
// 读取 JSON 文件并转换为 配置信息
PcdPojo pojoIn = mapper.readValue(new File(pojo.getConfigPath()), mapper.getTypeFactory().constructType(PcdPojo.class));
// 打印转换后的实体类列表
pojo = pojo.setPCDInfo(pojoIn);
//报错则认为没有配置文件,返回盘点失败
} catch (JsonMappingException e) {
e.printStackTrace();
return 0;
} catch (JsonProcessingException e) {
e.printStackTrace();
return 0;
} catch (IOException e) {
e.printStackTrace();
return 0;
}
System.out.println(pojo.toString());
// 计算pcd1
List<double[]> points = readPCD(pojo.getPcd1());
if (points == null || points.isEmpty()) {
return 0;
}
//计算pcd2
List<double[]> points2 = readPCD(pojo.getPcd2());
if (points2 == null || points2.isEmpty()) {
return 0;
}
//计算相似度
return calculateTruncatedMeans(points,points2,pojo,i,new ArrayList<>());
}
/**
* y
*
* @param pointCloud
* @param divisions
* @return 3 y
*/
public static double calculateTruncatedMeans(List<double[]> pointCloud, List<double[]> pointCloud2,PcdPojo pojo, int divisions,List<double[]> results) {
double width = (pojo.getMaxBounds()[0] - pojo.getMinBounds()[0]) / divisions; // 每个小方块的宽度
double depth = (pojo.getMaxBounds()[2] - pojo.getMinBounds()[2]) / divisions; // 每个小方块的深度
int count = 0;
int countSum = 0;
for (int i = 0; i < divisions; i++) {
for (int j = 0; j < divisions; j++) {
double leftBottomX = pojo.getMinBounds()[0] + i * width; // 左下角 x 坐标
double leftBottomZ = pojo.getMinBounds()[2] + j * depth; // 左下角 z 坐标
double rightTopX = pojo.getMinBounds()[0] + (i + 1) * width; // 右上角 x 坐标
double rightTopZ = pojo.getMinBounds()[2] + (j + 1) * depth; // 右上角 z 坐标
List<Double> yValues = new ArrayList<>();
for (double[] point : pointCloud) {
point = rotatePoints(point, pojo.getRotationMatrix());
if(clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) {
if (point[0] >= leftBottomX && point[0] < rightTopX &&
point[2] >= leftBottomZ && point[2] < rightTopZ) {
yValues.add(point[1]);
}
}
}
List<Double> yValues2 = new ArrayList<>();
for (double[] point : pointCloud2) {
point = rotatePoints(point, pojo.getRotationMatrix());
if(clipPoints(point, pojo.getMinBounds(), pojo.getMaxBounds())) {
if (point[0] >= leftBottomX && point[0] < rightTopX &&
point[2] >= leftBottomZ && point[2] < rightTopZ) {
yValues2.add(point[1]);
}
}
}
double truncatedMean = calculateTruncatedMean(yValues, 0.1); // 截断比例为10%
double truncatedMean2 = calculateTruncatedMean(yValues2, 0.1); // 截断比例为10%
double similarity = (truncatedMean - pojo.getMinBounds()[1])/(pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]);
double similarity2 = (truncatedMean2 - pojo.getMinBounds()[1])/(pojo.getMaxBounds()[1] - pojo.getMinBounds()[1]);
countSum++;
if(Double.isNaN(similarity) && Double.isNaN(similarity2)){
break;
}
System.out.println("similarity:"+similarity+"similarity2:"+similarity2);
double max = Math.max(similarity, similarity2); // 获取较大数
double min = Math.min(similarity, similarity2); // 获取较小数
if(max-min<0.01){
count++;
}
results.add(new double[]{leftBottomX, leftBottomZ, truncatedMean, truncatedMean2});
}
}
System.out.println(count);
pojo.setCount(count);
return (double) count /countSum;
}
/**
*
*
* @param values
* @param trimRatio
* @return
*/
private static double calculateTruncatedMean(List<Double> values, double trimRatio) {
int trimCount = (int) Math.ceil(values.size() * trimRatio);
values.sort(Comparator.naturalOrder());
double sum = 0;
for (int i = trimCount; i < values.size() - trimCount; i++) {
sum += values.get(i);
}
return sum / (values.size() - 2 * trimCount);
}
public static List<double[]> readPCD(String filePath) {
try {
if (isBinaryFormat(filePath)) {
return readBinaryPCD(filePath);
} else {
return readAsciiPCD(filePath);
}
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
private static boolean isBinaryFormat(String filePath) throws IOException {
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("DATA")) {
return line.contains("binary");
}
}
}
return false;
}
private static List<double[]> readAsciiPCD(String filePath) throws IOException {
List<double[]> points = new ArrayList<>();
try (BufferedReader reader = new BufferedReader(new FileReader(filePath))) {
String line;
while ((line = reader.readLine()) != null) {
if (line.startsWith("DATA")) {
break;
}
}
while ((line = reader.readLine()) != null) {
double[] point = new double[3];
String[] values = line.split(" ");
point[0] = Double.parseDouble(values[0]);
point[1] = Double.parseDouble(values[1]);
point[2] = Double.parseDouble(values[2]);
points.add(point);
}
}
return points;
}
private static List<double[]> readBinaryPCD(String filePath) throws IOException {
List<double[]> points = new ArrayList<>();
try (FileInputStream fis = new FileInputStream(filePath)) {
ByteBuffer buffer = ByteBuffer.wrap(fis.readAllBytes());
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
}
}
// 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};
points.add(point);
}
} catch (Exception e) {
return null;
}
return points;
}
static void getPCDArray(String filePath) {
}
static void getPCDArray(Map<Double, Map<Double, Double>> clippedPoint, String filePath) {
// 创建一个DecimalFormat对象指定格式
DecimalFormat df = new DecimalFormat("#.####");
File file = new File(filePath + ".txt");
file.delete();
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath + ".txt"))) {
bw.write("[");
for (Double x : clippedPoint.keySet()) {
for (Double y : clippedPoint.get(x).keySet()) {
double z = clippedPoint.get(x).get(y);
bw.write("[" + df.format(x) + ", " + df.format(y) + ", " + df.format(z) + "],\n");
}
}
bw.write("]");
} catch (IOException e) {
e.printStackTrace();
}
// 读取点云数据
}
public static double[] rotatePoints(double[] point, double[][] rotationMatrix) {
double x = point[0];
double y = point[1];
double z = point[2];
double[] rotatedPoint = new double[3];
rotatedPoint[0] = rotationMatrix[0][0] * x + rotationMatrix[0][1] * y + rotationMatrix[0][2] * z;
rotatedPoint[1] = rotationMatrix[1][0] * x + rotationMatrix[1][1] * y + rotationMatrix[1][2] * z;
rotatedPoint[2] = rotationMatrix[2][0] * x + rotationMatrix[2][1] * y + rotationMatrix[2][2] * z;
return rotatedPoint;
}
public static List<double[]> clipPoints(List<double[]> points, double[] minBounds, double[] maxBounds) {
List<double[]> clippedPoints = new ArrayList<>();
for (double[] point : points) {
if (point[0] >= minBounds[0] && point[0] <= maxBounds[0] &&
point[1] >= minBounds[1] && point[1] <= maxBounds[1] &&
point[2] >= minBounds[2] && point[2] <= maxBounds[2]) {
clippedPoints.add(point);
}
}
return clippedPoints;
}
public static boolean clipPoints(double[] point, double[] minBounds, double[] maxBounds) {
return point[0] >= minBounds[0] && point[0] <= maxBounds[0] && //x轴截取
point[1] >= minBounds[1] && point[1] <= maxBounds[1] && //y轴截取
point[2] >= minBounds[2] && point[2] <= maxBounds[2];
}
public static void writePCD(List<double[]> points, String filePath) {
try (BufferedWriter bw = new BufferedWriter(new FileWriter(filePath))) {
bw.write("# .PCD v0.7 - Point Cloud Data file format\n");
bw.write("VERSION 0.7\n");
bw.write("FIELDS x y z\n");
bw.write("SIZE 4 4 4\n");
bw.write("TYPE F F F\n");
bw.write("COUNT 1 1 1\n");
bw.write("WIDTH " + points.size() + "\n");
bw.write("HEIGHT 1\n");
bw.write("VIEWPOINT 0 0 0 1 0 0 0\n");
bw.write("PIXEL_FORMAT ascii\n");
bw.write("DATA ascii\n");
for (double[] point : points) {
bw.write(point[0] + " " + point[1] + " " + point[2] + "\n");
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

@ -72,6 +72,7 @@ public class TransmissionPojo {
this.checkId = convertNumberToFixedLengthChars(row, 3) + convertNumberToFixedLengthChars(column, 3);
}
//输出
public String toString(TransmissionType type) {
this.header = type.toString();
if (type == TransmissionType.ST) {

@ -214,7 +214,7 @@ public class KsecDecoder extends DelimiterBasedFrameDecoder {
log.info("盘点结束:"+ksecInfo.getData().toString());
}else if (Cmd.SC.name().equals(ksecInfo.getType())) {
//plcService.checkVision();
plcService.checkVision(dataInfo);
}
//找到该货位的最后一张照片与现在的照片比照
//plcService.recordStock(plcCmdInfo, dataInfo.getCode(), 0, 0);

@ -51,6 +51,10 @@ cameraConfig:
# 利珀延迟10s就可
# 单位毫秒
delayDownloadMp4: 10000
#工业相机编码sn
industrialCamera: F223
#camera3D(ip来标注
camera3D: 114
# ------------
# -----图片 mp4下载地址
savePath:
@ -95,7 +99,15 @@ scanCodeMode:
- 14
# 照片 視頻保存多久
deleteFileDays: 30
#灵闪tcp服务地址
intelliBlink:
ip: 127.0.0.1
port: 3002
#模版信息
template:
- id: 1
name: "模板一"
code: "a1123"
-

Loading…
Cancel
Save