1,去官网下载opencv,下载的时候需要注册一个 Oracle 账户,分分钟就能注册。然后安装。我下的是4.7的。

2,找到jar包放进项目里

3,项目结构,比较简单

4,把下载的文件放进C盘
5,主类代码
import org.opencv.core.Core;
/**
* @author lake
* @date 2023/6/26
*/
public class TestMain {
static {
//在使用OpenCV前必须加载Core.NATIVE_LIBRARY_NAME类,否则会报错
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
}
public static void main(String[] args) {
String imagePath1 = "C:\\Users\\lake45\\Desktop\\yuan.jpg";
String imagePath2 = "C:\\Users\\lake45\\Desktop\\fuben.jpg";
ImageCompare imageCompare = new ImageCompare();
imageCompare.CompareAndMarkDiff(imagePath1, imagePath2);
}
}
6,工具类
import org.opencv.core.*;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.utils.Converters;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
/**
* @author lake
* @date 2023/6/26
*/
public class ImageCompare {
private boolean compareResult = false;
private String mark = "_compareResult";
/**
* 比较两张图片,如不同则将不同处标记并输出到新的图片中
*
* @param imagePath1 图片1的路径
* @param imagePath2 图片2的路径
*/
public void CompareAndMarkDiff(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;
}
if (mat1.cols() != mat2.cols() || mat1.rows() != mat2.rows()) {
System.out.println("两张图片大小不同,无法比较");
return;
}
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;
}
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());
for (MatOfPoint matOfPoint : mat2_list) {
Rect rect = Imgproc.boundingRect(matOfPoint);
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);
}
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 + ".");
//图片一的带标记的输出文件;
writeImage(mat_result1, targetPath1);
//图片二的带标记的输出文件;
writeImage(mat_result2, targetPath2);
}
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;
}
}
7,效果图。如果是一张彩色和一张黑白的图片,效果就不太理想了。

资源文件刚刚提交,审核通过后会上地址。



















