|
@@ -0,0 +1,296 @@
|
|
|
+package com.management.platform.util;
|
|
|
+
|
|
|
+import java.awt.HeadlessException;
|
|
|
+import java.awt.image.BufferedImage;
|
|
|
+import java.io.ByteArrayInputStream;
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileInputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.io.InputStream;
|
|
|
+import java.io.UnsupportedEncodingException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import javax.imageio.ImageIO;
|
|
|
+
|
|
|
+import org.opencv.core.*;
|
|
|
+import org.opencv.imgcodecs.Imgcodecs;
|
|
|
+import org.opencv.imgproc.Imgproc;
|
|
|
+import org.opencv.utils.Converters;
|
|
|
+
|
|
|
+public class ImageCompare {
|
|
|
+ static {
|
|
|
+ System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
|
|
|
+ //注意程序运行的时候需要在VM option添加该行 指明opencv的dll文件所在路径
|
|
|
+ //-Djava.library.path=$PROJECT_DIR$\opencv\x64
|
|
|
+ }
|
|
|
+ private boolean compareResult = false;
|
|
|
+ private String mark = "_compareResult";
|
|
|
+ /**
|
|
|
+ * 通过两张图对比,判断是否是游戏电影类型
|
|
|
+ * @param imagePath1 图片1的路径
|
|
|
+ * @param imagePath2 图片2的路径
|
|
|
+ */
|
|
|
+ public boolean isMoviePlay(String imagePath1, String imagePath2)
|
|
|
+ {
|
|
|
+ Mat mat1 = readMat(imagePath1);
|
|
|
+ Mat mat2 = readMat(imagePath2);
|
|
|
+ mat1 = Imgcodecs.imdecode(mat1, Imgcodecs.IMREAD_UNCHANGED);
|
|
|
+ mat2 = Imgcodecs.imdecode(mat2, Imgcodecs.IMREAD_UNCHANGED);
|
|
|
+ if(mat1.cols() == 0 || mat2.cols() == 0 || mat1.rows() == 0 || mat2.rows() == 0)
|
|
|
+ {
|
|
|
+ System.out.println("图片文件路径异常,获取的图片大小为0,无法读取");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(mat1.cols() != mat2.cols() || mat1.rows() != mat2.rows())
|
|
|
+ {
|
|
|
+ System.out.println("两张图片大小不同,无法比较");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ mat1.convertTo(mat1, CvType.CV_8UC1);
|
|
|
+ mat2.convertTo(mat2, CvType.CV_8UC1);
|
|
|
+ Mat mat1_gray = new Mat();
|
|
|
+ Imgproc.cvtColor(mat1, mat1_gray, Imgproc.COLOR_BGR2GRAY);
|
|
|
+ Mat mat2_gray = new Mat();
|
|
|
+ Imgproc.cvtColor(mat2, mat2_gray, Imgproc.COLOR_BGR2GRAY);
|
|
|
+ mat1_gray.convertTo(mat1_gray, CvType.CV_32F);
|
|
|
+ mat2_gray.convertTo(mat2_gray, CvType.CV_32F);
|
|
|
+ double result = Imgproc.compareHist(mat1_gray, mat2_gray, Imgproc.CV_COMP_CORREL);
|
|
|
+ if(result == 1)
|
|
|
+ {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+// System.out.println("相似度数值为:"+result);
|
|
|
+ Mat mat_result = new Mat();
|
|
|
+ //计算两个灰度图的绝对差值,并输出到一个Mat对象中
|
|
|
+ Core.absdiff(mat1_gray, mat2_gray, mat_result);
|
|
|
+ //将灰度图按照阈值进行绝对值化
|
|
|
+ mat_result.convertTo(mat_result, CvType.CV_8UC1);
|
|
|
+ List<MatOfPoint> mat2_list = new ArrayList<MatOfPoint>();
|
|
|
+ Mat mat2_hi = new Mat();
|
|
|
+ //寻找轮廓图
|
|
|
+ Imgproc.findContours(mat_result, mat2_list, mat2_hi, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
|
|
|
+ Mat mat_result1 = mat1;
|
|
|
+ Mat mat_result2 = mat2;
|
|
|
+ //使用红色标记不同点
|
|
|
+ System.out.println(mat2_list.size());
|
|
|
+ List<Point> allPoints = new ArrayList<Point>();
|
|
|
+ //按照目标区域的面积大小, 长宽不低于480*480
|
|
|
+ Point leftTop = null;
|
|
|
+ Point rightTop = null;
|
|
|
+ Point leftBottom = null;
|
|
|
+ Point rightBottom = null;
|
|
|
+ for (MatOfPoint matOfPoint : mat2_list)
|
|
|
+ {
|
|
|
+ Rect rect = Imgproc.boundingRect(matOfPoint);
|
|
|
+ if (rect.width >= 280 && rect.height >= 280) {
|
|
|
+// System.out.println("位置==["+rect.x +","+ rect.y+"], 大小=" +rect.width+"x"+rect.height+", 包含点=" + matOfPoint.toList().size());
|
|
|
+ Imgproc.rectangle(mat_result1, rect.tl(), rect.br(), new Scalar(0, 0, 255),2);
|
|
|
+ Imgproc.rectangle(mat_result2, rect.tl(), rect.br(), new Scalar(0, 0, 255),2);
|
|
|
+ allPoints = matOfPoint.toList();
|
|
|
+ leftTop = new Point(rect.x, rect.y);
|
|
|
+ rightTop = new Point(rect.x + rect.width -1, rect.y);
|
|
|
+ leftBottom = new Point(rect.x, rect.y + rect.height -1);
|
|
|
+ rightBottom = new Point(rect.x + rect.width -1, rect.y + rect.height -1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Point p : allPoints) {
|
|
|
+ Imgproc.drawMarker(mat_result1, p, new Scalar(0, 255, 0),2);
|
|
|
+ }
|
|
|
+ //找到四个顶点
|
|
|
+ System.out.println("allPoints size=="+allPoints.size());
|
|
|
+ if (allPoints.size() == 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ System.out.println(leftTop);
|
|
|
+ System.out.println(rightTop);
|
|
|
+ System.out.println(leftBottom);
|
|
|
+ System.out.println(rightBottom);
|
|
|
+ //统计在矩形边上的点数量
|
|
|
+ int hitCount = 0;
|
|
|
+ for (Point p : allPoints) {
|
|
|
+ if ((Math.abs(p.x - leftTop.x) <= 6 || Math.abs(p.y - leftTop.y) <= 6)
|
|
|
+ || (Math.abs(p.x - rightBottom.x) <= 6 || Math.abs(p.y - rightBottom.y) <= 6)) {
|
|
|
+ hitCount++;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println("hitCount="+hitCount+", percent="+(100*hitCount/allPoints.size())+"%");
|
|
|
+ int percent = (100*hitCount/allPoints.size());
|
|
|
+ //分析占比
|
|
|
+ if (percent > 80) {
|
|
|
+ return true;//
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private void writeImage(Mat mat, String outPutFile)
|
|
|
+ {
|
|
|
+ MatOfByte matOfByte = new MatOfByte();
|
|
|
+ Imgcodecs.imencode(".png", mat, matOfByte);
|
|
|
+ byte[] byteArray = matOfByte.toArray();
|
|
|
+ BufferedImage bufImage = null;
|
|
|
+ try {
|
|
|
+ InputStream in = new ByteArrayInputStream(byteArray);
|
|
|
+ bufImage = ImageIO.read(in);
|
|
|
+ ImageIO.write(bufImage, "png", new File(outPutFile));
|
|
|
+ } catch (IOException | HeadlessException e)
|
|
|
+ {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getFileName(String filePath)
|
|
|
+ {
|
|
|
+ File f = new File(filePath);
|
|
|
+ return f.getName();
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getParentDir(String filePath)
|
|
|
+ {
|
|
|
+ File f = new File(filePath);
|
|
|
+ return f.getParent();
|
|
|
+ }
|
|
|
+
|
|
|
+ private Mat readMat(String filePath)
|
|
|
+ {
|
|
|
+ try {
|
|
|
+ File file = new File(filePath);
|
|
|
+ FileInputStream inputStream = new FileInputStream(filePath);
|
|
|
+ byte[] byt = new byte[(int) file.length()];
|
|
|
+ int read = inputStream.read(byt);
|
|
|
+ List<Byte> bs = convert(byt);
|
|
|
+ Mat mat1 = Converters.vector_char_to_Mat(bs);
|
|
|
+ return mat1;
|
|
|
+ } catch (UnsupportedEncodingException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ return new Mat();
|
|
|
+ }
|
|
|
+
|
|
|
+ private List<Byte> convert(byte[] byt)
|
|
|
+ {
|
|
|
+ List<Byte> bs = new ArrayList<Byte>();
|
|
|
+ for (int i = 0; i < byt.length; i++)
|
|
|
+ {
|
|
|
+ bs.add(i, byt[i]);
|
|
|
+ }
|
|
|
+ return bs;
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean test(String imagePath1, String imagePath2)
|
|
|
+ {
|
|
|
+ Mat mat1 = readMat(imagePath1);
|
|
|
+ Mat mat2 = readMat(imagePath2);
|
|
|
+ mat1 = Imgcodecs.imdecode(mat1, Imgcodecs.IMREAD_UNCHANGED);
|
|
|
+ mat2 = Imgcodecs.imdecode(mat2, Imgcodecs.IMREAD_UNCHANGED);
|
|
|
+ /*Mat mat1 = Imgcodecs.imread(imagePath1, Imgcodecs.IMREAD_UNCHANGED);
|
|
|
+ Mat mat2 = Imgcodecs.imread(imagePath2, Imgcodecs.IMREAD_UNCHANGED);*/
|
|
|
+ if(mat1.cols() == 0 || mat2.cols() == 0 || mat1.rows() == 0 || mat2.rows() == 0)
|
|
|
+ {
|
|
|
+ System.out.println("图片文件路径异常,获取的图片大小为0,无法读取");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ if(mat1.cols() != mat2.cols() || mat1.rows() != mat2.rows())
|
|
|
+ {
|
|
|
+ System.out.println("两张图片大小不同,无法比较");
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ mat1.convertTo(mat1, CvType.CV_8UC1);
|
|
|
+ mat2.convertTo(mat2, CvType.CV_8UC1);
|
|
|
+ Mat mat1_gray = new Mat();
|
|
|
+ Imgproc.cvtColor(mat1, mat1_gray, Imgproc.COLOR_BGR2GRAY);
|
|
|
+ Mat mat2_gray = new Mat();
|
|
|
+ Imgproc.cvtColor(mat2, mat2_gray, Imgproc.COLOR_BGR2GRAY);
|
|
|
+ mat1_gray.convertTo(mat1_gray, CvType.CV_32F);
|
|
|
+ mat2_gray.convertTo(mat2_gray, CvType.CV_32F);
|
|
|
+ double result = Imgproc.compareHist(mat1_gray, mat2_gray, Imgproc.CV_COMP_CORREL);
|
|
|
+ if(result == 1)
|
|
|
+ {
|
|
|
+ compareResult = true;//此处结果为1则为完全相同
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ System.out.println("相似度数值为:"+result);
|
|
|
+ Mat mat_result = new Mat();
|
|
|
+ //计算两个灰度图的绝对差值,并输出到一个Mat对象中
|
|
|
+ Core.absdiff(mat1_gray, mat2_gray, mat_result);
|
|
|
+ //将灰度图按照阈值进行绝对值化
|
|
|
+ mat_result.convertTo(mat_result, CvType.CV_8UC1);
|
|
|
+ List<MatOfPoint> mat2_list = new ArrayList<MatOfPoint>();
|
|
|
+ Mat mat2_hi = new Mat();
|
|
|
+ //寻找轮廓图
|
|
|
+ Imgproc.findContours(mat_result, mat2_list, mat2_hi, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);
|
|
|
+ Mat mat_result1 = mat1;
|
|
|
+ Mat mat_result2 = mat2;
|
|
|
+ //使用红色标记不同点
|
|
|
+ System.out.println(mat2_list.size());
|
|
|
+ List<Point> allPoints = new ArrayList<Point>();
|
|
|
+ //按照目标区域的面积大小, 长宽不低于480*480
|
|
|
+ Point leftTop = null;
|
|
|
+ Point rightTop = null;
|
|
|
+ Point leftBottom = null;
|
|
|
+ Point rightBottom = null;
|
|
|
+ for (MatOfPoint matOfPoint : mat2_list)
|
|
|
+ {
|
|
|
+ Rect rect = Imgproc.boundingRect(matOfPoint);
|
|
|
+ if (rect.width >= 280 && rect.height >= 280) {
|
|
|
+ System.out.println("位置==["+rect.x +","+ rect.y+"], 大小=" +rect.width+"x"+rect.height+", 包含点=" + matOfPoint.toList().size());
|
|
|
+ Imgproc.rectangle(mat_result1, rect.tl(), rect.br(), new Scalar(0, 0, 255),2);
|
|
|
+ Imgproc.rectangle(mat_result2, rect.tl(), rect.br(), new Scalar(0, 0, 255),2);
|
|
|
+ allPoints = matOfPoint.toList();
|
|
|
+ leftTop = new Point(rect.x, rect.y);
|
|
|
+ rightTop = new Point(rect.x + rect.width -1, rect.y);
|
|
|
+ leftBottom = new Point(rect.x, rect.y + rect.height -1);
|
|
|
+ rightBottom = new Point(rect.x + rect.width -1, rect.y + rect.height -1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (Point p : allPoints) {
|
|
|
+ Imgproc.drawMarker(mat_result1, p, new Scalar(0, 255, 0),2);
|
|
|
+ }
|
|
|
+ String fileName1 = getFileName(imagePath1);
|
|
|
+ String targetPath1 = getParentDir(imagePath2)+File.separator+fileName1.replace(".", mark+".");
|
|
|
+ String fileName2 = getFileName(imagePath2);
|
|
|
+ String targetPath2 = getParentDir(imagePath2)+File.separator+fileName2.replace(".", mark+".");
|
|
|
+ System.out.println(targetPath1);
|
|
|
+ System.out.println(targetPath2);
|
|
|
+ writeImage(mat_result1, targetPath1);
|
|
|
+ writeImage(mat_result2, targetPath2);
|
|
|
+ //找到四个顶点
|
|
|
+ System.out.println("allPoints size=="+allPoints.size());
|
|
|
+ System.out.println(leftTop);
|
|
|
+ System.out.println(rightTop);
|
|
|
+ System.out.println(leftBottom);
|
|
|
+ System.out.println(rightBottom);
|
|
|
+ //检测其他点,是否都在矩形边上
|
|
|
+ int hitCount = 0;
|
|
|
+ for (Point p : allPoints) {
|
|
|
+ if ((Math.abs(p.x - leftTop.x) <= 6 || Math.abs(p.y - leftTop.y) <= 6)
|
|
|
+ || (Math.abs(p.x - rightBottom.x) <= 6 || Math.abs(p.y - rightBottom.y) <= 6)) {
|
|
|
+ hitCount++;
|
|
|
+ } else {
|
|
|
+// System.out.println("失效点:"+p.x + "," + p.y);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ System.out.println("hitCount="+hitCount+", percent="+(100*hitCount/allPoints.size())+"%");
|
|
|
+ int percent = (100*hitCount/allPoints.size());
|
|
|
+
|
|
|
+
|
|
|
+ if (percent > 80) {
|
|
|
+ return true;//
|
|
|
+ } else {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ public static void main(String[] args) {
|
|
|
+ String img1 = "C:\\Users\\seya\\Desktop\\m1.jpg";
|
|
|
+ String img2 = "C:\\Users\\seya\\Desktop\\m2.jpg";
|
|
|
+ ImageCompare ip = new ImageCompare();
|
|
|
+ System.out.println("是电影娱乐吗?"+ip.test(img1, img2));
|
|
|
+ }
|
|
|
+}
|
|
|
+
|