java + opencv对比图片不同

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,效果图。如果是一张彩色和一张黑白的图片,效果就不太理想了。

资源文件地址,我设置了0积分下载:

https://download.csdn.net/download/qq_30299243/87950327?spm=1001.2014.3001.5503

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/2041.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GitLab无法提交大文件的问题

GitLab无法提交大文件的问题 问题描述 GitLab 当提交大文件时遇到如下报错 MYOPS001MYOPS001 MINGW64 /e/work/GitLab/system-deploy (main) $ git push Enumerating objects: 91, done. Counting objects: 100% (91/91), done. Delta compression using up to 16 threads C…

西安石油大学期末考试C++真题解析

1、一、类型、返回值类型 二、参数表、函数重载 2、一、实例化 二、实例化的类型或类类是对象的蓝图&#xff0c;对象是类的实例化 3、const 4、一个 两个 5、一、公有继承 二、私有继承、保护继承 6、抽象类、实例化对象 7、函数模板、类模板 8、try、catch、throw 9、…

selenium之鼠标操作

首先导入ActionChains类&#xff0c;该类可以完成鼠标移动&#xff0c;鼠标点击事件&#xff0c;键盘输入、内容菜单交互等交互行为。 from selenium.webdriver.common.action_chains import ActionChains 操作语法&#xff1a; 第一步&#xff1a;初始化ActionChains类&…

python【爬虫】【批量下载】年报抓取

python年报爬取更新 本人测试发现&#xff0c;ju chao网的年报爬取距离我上一篇博客并没有啥变化&#xff0c;逻辑没变&#xff0c;应好多朋友的需要&#xff0c;这里补充代码 import json import osimport requestsweb_url 改成网站的域名&#xff0c;因为csdn屏蔽 def load…

HOT20-旋转图像

leetcode原题链接&#xff1a;旋转图像 题目描述 给定一个 n n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。 你必须在 原地 旋转图像&#xff0c;这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。 示例 1&#xff1a; 输入&am…

Android JetPack 深入分析ViewModel源码

文章目录 前言源码分析ViewModel是如何创建的&#xff1f;ViewModelProvider(this)做了什么&#xff1f;小结 get(MyViewModel::class.java)做了什么&#xff1f;小结 ViewModel是如何实现配置更改后数据恢复的&#xff1f;整体时序图 结语 前言 本文主要分析ViewModel相关源码…

JUC之LockSupport和中断

文章目录 1 线程中断机制1.1 什么是线程中断机制1.2 三大中断方法1.3 如何中断运行中的线程1.3.1 通过volatile变量实现1.3.1 通过AtomicBoolean实现1.3.1 通过interrupt和isInterrupted api实现 2 LockSupport2.1 为什么会出现LockSupport2.2 两道面试题 参考材料 1 线程中断机…

移动隔断屏风墙,无地轨设计,空间灵活应用

移动隔断屏风墙是一种非常适合办公室的设计选择&#xff0c;它可以提供灵活的办公空间布局&#xff0c;并且无地轨设计可以避免地面安装轨道&#xff0c;给空间带来更大的自由度。以下是一些关于移动隔断屏风墙的特点和设计建议&#xff1a; 1. 灵活应用&#xff1a;移动隔断屏…

JavaScript进阶----《getter 和 setter 是什么》

前言&#xff1a; 这两个属性在学习前端的时候看到过&#xff0c;但是由于项目中没有用到过&#xff0c;所以一直没有细致的了解。今天 review 同事代码的时候&#xff0c;遇到了这个写法&#xff0c;看了半天也不知道如何处理。再不学习真的以后连别人的代码都不知道什么意思了…

百度智驾,与车路协同说「再见」

作者 | 魏启扬 来源 | 洞见新研社 在经历了裁员&#xff0c;全员停发年终奖之后&#xff0c;百度对智能交通事业部&#xff08;ACE&#xff09;的治理还在继续。 不久前&#xff0c;有媒体爆料称&#xff0c;百度已经将智能交通事业部&#xff08;ACE&#xff09;从原来的智能…

微信小程序——分页组件的创建与使用

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

C++类与对象(默认成员函数之拷贝构造函数)

接前几次的类与对象的默认函数的知识点&#xff0c;下来面是默认成员函数中的拷贝构造函数。是的&#xff0c;它的名字是拷贝构造函数&#xff0c;他其实也是一种构造函数&#xff0c;为什么呢&#xff1f;接下来你就知道了&#xff0c;我们直接看看代码&#xff0c;如下&#…