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,效果图。如果是一张彩色和一张黑白的图片,效果就不太理想了。
资源文件刚刚提交,审核通过后会上地址。