增加图片修改

联合利华-拍照
LAPTOP-S9HJSOEB\昊天 1 month ago
parent 3b9aecab69
commit 530b9a2052

@ -36,6 +36,7 @@
<mybatis-plus-generator.version>3.5.5</mybatis-plus-generator.version>
</properties>
<dependencies>
<!-- Spring Boot Web -->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -83,6 +84,14 @@
<systemPath>${project.basedir}/src/main/resources/libs/MvCameraControlWrapper.jar</systemPath>
</dependency>
<dependency>
<groupId>opencv</groupId>
<artifactId>opencv</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/src/main/resources/libs/opencv-453.jar</systemPath>
</dependency>
<!-- Spring 配置处理器 -->
<dependency>
<groupId>org.springframework.boot</groupId>
@ -109,7 +118,6 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!-- Gson JSON -->
<dependency>
<groupId>com.google.code.gson</groupId>

@ -14,6 +14,14 @@ import com.sourceforge.snap7.moka7.S7Client;
import jakarta.annotation.PostConstruct;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.opencv.core.Mat;
import org.opencv.core.MatOfPoint2f;
import org.opencv.core.Point;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.File;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
@ -50,6 +58,37 @@ import java.util.concurrent.*;
@Slf4j
public class S7MultiPlcService {
// 静态加载OpenCV DLL
static {
String[] dllPaths = {
System.getProperty("user.dir") + "/libs/opencv/opencv_java453.dll",
System.getProperty("user.dir") + "/out/opencv_java453.dll"
};
boolean loaded = false;
for (String dllPath : dllPaths) {
File dllFile = new File(dllPath);
if (dllFile.exists()) {
try {
System.load(dllFile.getAbsolutePath());
log.info("OpenCV DLL 加载成功: {}", dllFile.getAbsolutePath());
loaded = true;
break;
} catch (UnsatisfiedLinkError e) {
log.warn("加载失败 {}: {}", dllPath, e.getMessage());
}
}
}
if (!loaded) {
try {
System.loadLibrary("opencv_java453");
log.info("OpenCV DLL 从系统路径加载成功");
loaded = true;
} catch (UnsatisfiedLinkError e) {
log.error("OpenCV DLL 加载失败,所有路径都不存在或加载失败");
}
}
}
// PLC连接池映射: plcNumber -> 连接池
private final Map<String, BlockingQueue<S7Client>> plcConnectionPools = new ConcurrentHashMap<>();
@ -436,96 +475,90 @@ public class S7MultiPlcService {
return null;
}
public static void main(String[] args) {
AppConfig.Camera camera = new AppConfig.Camera();
camera.setCrop(new ArrayList<>());
List<Integer> crop = new ArrayList<>();
crop.add(640);
crop.add(640);
camera.getCrop().add(List.of(800, 1800));
camera.getCrop().add( List.of(800, 550));
camera.getCrop().add(List.of(2100, 550));
camera.getCrop().add(List.of(2100, 1800));
camera.setCropSize(crop);
S7MultiPlcService service = new S7MultiPlcService();
service.cropAndCompressImage("D:\\data\\media\\2026-05-15\\1\\2026-05-15-01-16-18-640.png.jpg",camera);
}
/**
*
* @param imagePath
*/
private void cropAndCompressImage(String imagePath,AppConfig.Camera config) {
private void cropAndCompressImage(String imagePath, AppConfig.Camera config) {
try {
File imageFile = new File(imagePath);
if (!imageFile.exists()) {
log.warn("图片文件不存在: {}", imagePath);
return;
}
BufferedImage originalImage = ImageIO.read(imageFile);
if (originalImage == null) {
log.warn("无法读取图片: {}", imagePath);
return;
}
List<List<Integer>> crop = config.getCrop();
List<Integer> cropSize = config.getCropSize();
int targetWidth = cropSize.get(0);
int targetHeight = cropSize.get(1);
// 源四边形四个顶点 (顺时针: 左上, 右上, 右下, 左下)
double x0 = crop.get(0).get(0), y0 = crop.get(0).get(1);
double x1 = crop.get(1).get(0), y1 = crop.get(1).get(1);
double x2 = crop.get(2).get(0), y2 = crop.get(2).get(1);
double x3 = crop.get(3).get(0), y3 = crop.get(3).get(1);
// 目标矩形四个顶点 (左上, 右上, 右下, 左下)
double u0 = 0, v0 = 0;
double u1 = targetWidth, v1 = 0;
double u2 = targetWidth, v2 = targetHeight;
double u3 = 0, v3 = targetHeight;
// 创建目标图像
BufferedImage croppedImage = new BufferedImage(targetWidth, targetHeight, BufferedImage.TYPE_INT_RGB);
int[] srcPixels = originalImage.getRGB(0, 0, originalImage.getWidth(), originalImage.getHeight(), null, 0, originalImage.getWidth());
int srcWidth = originalImage.getWidth();
int srcHeight = originalImage.getHeight();
// 计算透视变换的逆变换系数 (从目标坐标映射到源坐标)
// 使用双线性插值的透视变换
for (int y = 0; y < targetHeight; y++) {
for (int x = 0; x < targetWidth; x++) {
// 计算相对于目标矩形的归一化坐标
double mu = (double) x / targetWidth;
double mv = (double) y / targetHeight;
// 计算透视变换后的源坐标 (使用双线性插值)
double srcX = bilinearInterpolate(
bilinearInterpolate(x0, x1, mu),
bilinearInterpolate(x3, x2, mu),
mv
);
double srcY = bilinearInterpolate(
bilinearInterpolate(y0, y1, mu),
bilinearInterpolate(y3, y2, mu),
mv
);
// 从源图像采样像素
int srcXInt = (int) Math.round(srcX);
int srcYInt = (int) Math.round(srcY);
if (srcXInt >= 0 && srcXInt < srcWidth && srcYInt >= 0 && srcYInt < srcHeight) {
int pixel = srcPixels[srcYInt * srcWidth + srcXInt];
croppedImage.setRGB(x, y, pixel);
} else {
croppedImage.setRGB(x, y, 0xFFFFFF); // 白色填充
}
}
// crop.get(0) -> 目标左上, crop.get(1) -> 目标右上
// crop.get(2) -> 目标右下, crop.get(3) -> 目标左下
// 源图像中的四个点
Point[] srcArray = new Point[] {
new Point(crop.get(0).get(0), crop.get(0).get(1)),
new Point(crop.get(1).get(0), crop.get(1).get(1)),
new Point(crop.get(2).get(0), crop.get(2).get(1)),
new Point(crop.get(3).get(0), crop.get(3).get(1))
};
MatOfPoint2f srcPoints2f = new MatOfPoint2f(srcArray);
// 目标矩形的四个顶点
Point[] dstArray = new Point[] {
new Point(0, 0),
new Point(targetWidth, 0),
new Point(targetWidth, targetHeight),
new Point(0, targetHeight)
};
MatOfPoint2f dstPoints = new MatOfPoint2f(dstArray);
// 计算透视变换矩阵
Mat transformMatrix = Imgproc.getPerspectiveTransform(srcPoints2f, dstPoints);
// 读取源图像
Mat srcImage = Imgcodecs.imread(imagePath);
if (srcImage.empty()) {
log.warn("无法读取图片: {}", imagePath);
return;
}
// 压缩并保存
compressAndSaveImage(croppedImage, imageFile, config.getCompress());
// 创建目标图像并进行透视变换
Mat dstImage = new Mat();
Imgproc.warpPerspective(srcImage, dstImage, transformMatrix, new Size(targetWidth, targetHeight));
// 保存结果
Imgcodecs.imwrite(imagePath, dstImage);
// 释放资源
srcImage.release();
dstImage.release();
transformMatrix.release();
srcPoints2f.release();
dstPoints.release();
log.info("图片透视裁剪完成: {}, 尺寸: {}x{}", imagePath, targetWidth, targetHeight);
} catch (IOException e) {
} catch (Exception e) {
log.error("图片透视裁剪失败: {}", imagePath, e);
}
}
/**
* 线
*/
private double bilinearInterpolate(double v0, double v1, double t) {
return v0 + (v1 - v0) * t;
}
/**
* JPEG

Loading…
Cancel
Save