diff --git a/yxt-supervise-monitor-biz/pom.xml b/yxt-supervise-monitor-biz/pom.xml
index 18b36a3..a2f7715 100644
--- a/yxt-supervise-monitor-biz/pom.xml
+++ b/yxt-supervise-monitor-biz/pom.xml
@@ -59,6 +59,17 @@
2.2.3
+
+
+ org.bytedeco
+ javacv
+ 1.3.3
+
+
+ org.bytedeco
+ javacv-platform
+ 1.3.3
+
@@ -93,4 +104,4 @@
-
\ No newline at end of file
+
diff --git a/yxt-supervise-monitor-biz/src/main/java/com/yxt/supervise/monitor/biz/util/ImageCompareUtil.java b/yxt-supervise-monitor-biz/src/main/java/com/yxt/supervise/monitor/biz/util/ImageCompareUtil.java
new file mode 100644
index 0000000..1b0ceca
--- /dev/null
+++ b/yxt-supervise-monitor-biz/src/main/java/com/yxt/supervise/monitor/biz/util/ImageCompareUtil.java
@@ -0,0 +1,238 @@
+package com.yxt.supervise.monitor.biz.util;
+
+import org.bytedeco.javacpp.BytePointer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.bytedeco.javacpp.opencv_core.*;
+import static org.bytedeco.javacpp.opencv_imgcodecs.imread;
+import static org.bytedeco.javacpp.opencv_imgcodecs.imwrite;
+import static org.bytedeco.javacpp.opencv_imgproc.*;
+
+
+/**
+ * @Author yzj
+ * @Date 2023-05-31
+ * @Version 1.0
+ */
+public class ImageCompareUtil {
+ private static Logger Log = LoggerFactory.getLogger(ImageCompareUtil.class);
+
+
+ public static void compareImage(String targetImageUrl, String baseImageUrl) {
+
+
+ /**
+ * 读取图片到数组
+ */
+ Mat targetImage = imread(targetImageUrl);
+ Mat baseImage = imread(baseImageUrl);
+ Log.info("read image success");
+
+
+ /**
+ * 首先对比的两个图片宽度要一致,否则不能对比
+ */
+ if (targetImage.size().width() == baseImage.size().width()) {
+
+
+ /**
+ * 基本算法
+ * 1、判断高度是否一致,如果不一致,需要截取到高度一致
+ * 2、截取算法
+ * a、因为图片有通用的顶部bar和底部bar,需要先找到底部bar。
+ * b、截取长图片的部分,然后和底部bar拼接,就完成了图片截取。
+ * c、这里设置一个默认的宽度,然后对比,找到相同部分,就是底部bar。
+ */
+
+ if (targetImage.size().height() != baseImage.size().height()) {
+
+ if (targetImage.size().height() > baseImage.size().height()) {
+ targetImage = dealLongImage(targetImage.clone(), baseImage.clone());
+ } else {
+ baseImage = dealLongImage(baseImage.clone(), targetImage.clone());
+ }
+ }
+
+ /**
+ * 进行图片差异对比
+ */
+ Mat imageDiff = compareImage(targetImage, baseImage);
+
+ double total = 100;
+
+ double nonZeroPercent = 100 * (double) countNonZero(imageDiff) / (imageDiff.size().height() * imageDiff.size().width());
+
+ System.out.println("相似度:" + (total - nonZeroPercent));
+
+ /**
+ * 展示图片,将标准图,对比图,差异图,拼接成一张大图。
+ * 其中差异图会用绿色标出差异的部分。
+ */
+// set3ImageTo1("", targetImage, baseImage, showDiff(imageDiff, baseImage), "xxxx.jpg" );
+
+
+ imageDiff.release();
+ baseImage.release();
+ targetImage.release();
+
+ } else {
+
+ }
+ }
+
+
+ /**
+ * 2、截取算法
+ * a、因为图片有通用的顶部bar和底部bar,需要先找到底部bar。
+ * b、截取长图片的部分,然后和底部bar拼接,就完成了图片截取。
+ * c、这里设置一个默认的宽度,然后对比,找到相同部分,就是底部bar。
+ *
+ * @return bar的高度
+ */
+ public static int interceptBarHeight(Mat longImage, Mat shortImage) {
+
+ /**
+ * 设置的默认高度。
+ */
+ int imageSearchMaxHeight = 400;
+ Mat subImageLong = new Mat(longImage, new Rect(0, longImage.size().height() - imageSearchMaxHeight, longImage.size().width(), imageSearchMaxHeight));
+ Mat subImageShort = new Mat(shortImage, new Rect(0, shortImage.size().height() - imageSearchMaxHeight, shortImage.size().width(), imageSearchMaxHeight));
+
+ Mat imageDiff = compareImage(subImageLong, subImageShort);
+
+ for (int row = imageDiff.size().height() - 1; row > -1; row--) {
+ for (int col = 0; col < imageDiff.size().width(); col++) {
+ BytePointer bytePointer = imageDiff.ptr(row, col);
+ if (bytePointer.get(0) != 0) {
+ imageDiff.release();
+ return imageSearchMaxHeight - row;
+ }
+ }
+ }
+ return imageSearchMaxHeight;
+ }
+
+ /**
+ * 这里将两张图片作为参数传入,
+ * 获取到共同的底部之后。对长图进行截取,
+ * 然后将顶部和底部拼接在一起就ok了。
+ *
+ * @param longImage
+ * @param shortImage
+ * @return
+ */
+ public static Mat dealLongImage(Mat longImage, Mat shortImage) {
+
+ int diffHeight = longImage.size().height() - shortImage.size().height();
+ int barHeight = interceptBarHeight(longImage, shortImage);
+
+ Mat dealedLongImage = new Mat(longImage, new Rect(0, 0, longImage.size().width(), shortImage.size().height() - barHeight));
+
+ Mat imageBar = new Mat(longImage, new Rect(0, longImage.size().height() - barHeight, longImage.size().width(), barHeight));
+
+ Mat dealedLongImageNew = dealedLongImage.clone();
+
+ /**
+ * 将头部和底部bar拼接在一起。
+ */
+ vconcat(dealedLongImage, imageBar, dealedLongImageNew);
+ imageBar.release();
+ dealedLongImage.release();
+ return dealedLongImageNew;
+ }
+
+
+ public static Mat compareImage(Mat targetImage, Mat baseImage) {
+
+ Mat targetImageClone = targetImage.clone();
+ Mat baseImageColne = baseImage.clone();
+ Mat imgDiff1 = targetImage.clone();
+ Mat imgDiff = targetImage.clone();
+
+ /**
+ * 首先将图片转成灰度图,
+ */
+ cvtColor(targetImage, targetImageClone, COLOR_BGR2GRAY);
+ cvtColor(baseImage, baseImageColne, COLOR_BGR2GRAY);
+
+ /**
+ * 两个矩阵相减,获得差异图。
+ */
+ subtract(targetImageClone, baseImageColne, imgDiff1);
+ subtract(baseImageColne, targetImageClone, imgDiff);
+
+ /**
+ * 按比重进行叠加。
+ */
+ addWeighted(imgDiff, 1, imgDiff1, 1, 0, imgDiff);
+
+ /**
+ * 图片二值化,大于24的为1,小于24的为0
+ */
+ threshold(imgDiff, imgDiff, 24, 255, THRESH_BINARY);
+ erode(imgDiff, imgDiff, new Mat());
+ dilate(imgDiff, imgDiff, new Mat());
+ return imgDiff;
+ }
+
+
+ private static void set3ImageTo1(String logTag, Mat imageSrc, Mat imageBaseSrc, Mat imageDest, String mergePicResult) {
+
+ if (imageSrc.size().width() == imageDest.size().width() && imageBaseSrc.size().height() == imageDest.size().height()) {
+ Mat img = imageSrc.clone();
+ Mat imgBase = imageBaseSrc.clone();
+ Mat imgDest = imageDest.clone();
+ Mat imgLine = new Mat(imgBase.size().height(), 1, CV_8UC3, new Scalar(0, 0, 0, 255));
+ Mat largeImg2 = new Mat();
+ Mat largeImg3 = new Mat();
+ Mat largeImg4 = new Mat();
+ Mat largeImg5 = new Mat();
+ /**
+ * 横向拼接。
+ */
+ hconcat(img, imgLine, largeImg2);
+ hconcat(largeImg2, imgBase, largeImg3);
+ hconcat(largeImg3, imgLine, largeImg4);
+ hconcat(largeImg4, imgDest, largeImg5);
+
+ imwrite(mergePicResult, largeImg5);
+
+ img.release();
+ imgBase.release();
+ imgDest.release();
+ imgLine.release();
+ largeImg2.release();
+ largeImg3.release();
+ largeImg4.release();
+ largeImg5.release();
+ } else {
+ Log.info(logTag + " pictures merge failed");
+ imwrite(mergePicResult, imageDest);
+ }
+
+ }
+
+
+ private static Mat showDiff(Mat imgDiff, Mat imgBase) {
+
+ MatVector rgbFrame = new MatVector();
+ Mat imgDest = imgBase.clone();
+ subtract(rgbFrame.get(2), imgDiff, rgbFrame.get(2));
+ subtract(rgbFrame.get(0), imgDiff, rgbFrame.get(0));
+ addWeighted(rgbFrame.get(1), 1, imgDiff, 1, 0, rgbFrame.get(1));
+ merge(rgbFrame, imgDest);
+ return imgDest;
+ }
+
+
+ public static void main(String[] args) {
+
+ String targetImageUrl = "C:\\Users\\Administrator\\Desktop\\5.png";
+ String baseImageUrl = "C:\\Users\\Administrator\\Desktop\\6.png";
+
+ compareImage(targetImageUrl, baseImageUrl);
+// interceptBarHeight(targetImageUrl,baseImageUrl);
+ }
+
+}
diff --git a/yxt-supervise-monitor-biz/src/main/java/com/yxt/supervise/monitor/biz/util/ImageNotWCompareUtil.java b/yxt-supervise-monitor-biz/src/main/java/com/yxt/supervise/monitor/biz/util/ImageNotWCompareUtil.java
new file mode 100644
index 0000000..cfa2573
--- /dev/null
+++ b/yxt-supervise-monitor-biz/src/main/java/com/yxt/supervise/monitor/biz/util/ImageNotWCompareUtil.java
@@ -0,0 +1,130 @@
+package com.yxt.supervise.monitor.biz.util;
+
+import javax.imageio.ImageIO;
+import java.awt.image.BufferedImage;
+import java.io.File;
+
+/**
+ * @Author yzj
+ * @Date 2023-05-31
+ * @Version 1.0
+ */
+
+public class ImageNotWCompareUtil {
+ public static String[][] getPX(String args) {
+ int[] rgb = new int[3];
+
+ File file = new File(args);
+ BufferedImage bi = null;
+ try {
+ bi = ImageIO.read(file);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ int width = bi.getWidth();
+ int height = bi.getHeight();
+ int minx = bi.getMinX();
+ int miny = bi.getMinY();
+ String[][] list = new String[width][height];
+ for (int i = minx; i < width; i++) {
+ for (int j = miny; j < height; j++) {
+ int pixel = bi.getRGB(i, j);
+ rgb[0] = (pixel & 0xff0000) >> 16;
+ rgb[1] = (pixel & 0xff00) >> 8;
+ rgb[2] = (pixel & 0xff);
+ list[i][j] = rgb[0] + "," + rgb[1] + "," + rgb[2];
+
+ }
+ }
+ return list;
+
+ }
+
+ public static void compareImage(String imgPath1, String imgPath2) {
+ String[] images = {imgPath1, imgPath2};
+ if (images.length == 0) {
+ System.out.println("Usage >java BMPLoader ImageFile.bmp");
+ System.exit(0);
+ }
+
+ // 分析图片相似度 begin
+ String[][] list1 = getPX(images[0]);
+ String[][] list2 = getPX(images[1]);
+ int xiangsi = 0;
+ int busi = 0;
+ int i = 0, j = 0;
+ for (String[] strings : list1) {
+ if ((i + 1) == list1.length) {
+ continue;
+ }
+ for (int m = 0; m < strings.length; m++) {
+ try {
+ String[] value1 = list1[i][j].toString().split(",");
+ String[] value2 = list2[i][j].toString().split(",");
+ int k = 0;
+ for (int n = 0; n < value2.length; n++) {
+ if (Math.abs(Integer.parseInt(value1[k]) - Integer.parseInt(value2[k])) < 5) {
+ xiangsi++;
+ } else {
+ busi++;
+ }
+ }
+ } catch (RuntimeException e) {
+ continue;
+ }
+ j++;
+ }
+ i++;
+ }
+
+ list1 = getPX(images[1]);
+ list2 = getPX(images[0]);
+ i = 0;
+ j = 0;
+ for (String[] strings : list1) {
+ if ((i + 1) == list1.length) {
+ continue;
+ }
+ for (int m = 0; m < strings.length; m++) {
+ try {
+ String[] value1 = list1[i][j].toString().split(",");
+ String[] value2 = list2[i][j].toString().split(",");
+ int k = 0;
+ for (int n = 0; n < value2.length; n++) {
+ if (Math.abs(Integer.parseInt(value1[k]) - Integer.parseInt(value2[k])) < 5) {
+ xiangsi++;
+ } else {
+ busi++;
+ }
+ }
+ } catch (RuntimeException e) {
+ continue;
+ }
+ j++;
+ }
+ i++;
+ }
+ String baifen = "";
+ try {
+ baifen = ((Double.parseDouble(xiangsi + "") / Double.parseDouble((busi + xiangsi) + "")) + "");
+ baifen = baifen.substring(baifen.indexOf(".") + 1, baifen.indexOf(".") + 3);
+ } catch (Exception e) {
+ baifen = "0";
+ }
+ if (baifen.length() <= 0) {
+ baifen = "0";
+ }
+ if (busi == 0) {
+ baifen = "100";
+ }
+
+ System.out.println("相似像素数量:" + xiangsi + " 不相似像素数量:" + busi + " 相似率:" + Integer.parseInt(baifen) + "%");
+
+ }
+
+ public static void main(String[] args) {
+ ImageNotWCompareUtil.compareImage("E:\\downLoad\\宇信通\\same\\7.jpg", "E:\\downLoad\\宇信通\\same\\8.jpg");
+// ImageNotWService.compareImage("E:\\downLoad\\宇信通\\same\\3.png", "E:\\downLoad\\宇信通\\same\\1.png");
+ }
+}