java + opencv对比图片不同

news2024/11/17 5:31:37

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

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

 

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

未来独角兽!安全狗入选2023年福建省数字经济核心产业领域创新企业名单

近日&#xff0c;福建省数字福建建设领导小组办公室公布了入选2023年全省数字经济核心产业领域创新企业名单。 作为国内云原生安全领导厂商&#xff0c;安全狗凭借综合安全能力入选名单&#xff0c;荣膺“未来独角兽”称号。 厦门服云信息科技有限公司&#xff08;品牌名&#…

7DGroup性能实施项目日记4

经过了一个十一假期&#xff0c;我们的日记虽然没有更新&#xff0c;但我们的项目并没有停止。 虽然这个项目是一个依托性能培训的项目&#xff0c;但对我来说&#xff0c;这和真实的项目并无二致。我们花了几万&#xff08;根据一期的培训&#xff0c;估计在3万-4万左右&…

高速电路设计系列分享-基本概念

目录 概要 整体架构流程 技术名词解释 1.带宽的理解 2.了解转换器的精度 技术细节 小结 概要 提示&#xff1a;这里可以添加技术概要 本文主要熟悉一些基本概念。随笔&#xff0c;加一些网上用语&#xff0c;只做学习之用&#xff0c;不用深入分析。 整体架构流程 提…

最佳的SCADA软件推荐

前言 发现优化工业运营效率并最大化投资回报率的最佳“监控和数据采集 &#xff08;SCADA&#xff09;、工业物联网 &#xff08;IIoT&#xff09;、人工智能 &#xff08;AI&#xff09; 等”数字化转型技术&#xff0c;使商业组织能够提高运营效率并促进公用事业管理。当配备…

浏览器插件开发(一)入门之自制屏蔽某度广告的插件

一&#xff1a;浏览器扩展介绍&#xff1a; 浏览器扩展是一个小软件定义模块的网页浏览器&#xff0c;通常称为浏览器插件&#xff0c;大部分浏览器允许安装拓展&#xff0c;其作用有用户界面修改&#xff0c;广告拦截和Cookie管理等 包含基本平台信息的应用程序清单JSON文件 …

第十章 总结【编译原理】

第十章 总结【编译原理】 前言推荐第十章 总结10.1 概述10.2 局部优化10.2.1基本块及流图10.2.2基本块的DAG表示及其应用 10.3 循环优化*10.4数据流分析 最后 前言 2023-6-26 18:54:31 以下内容源自《【编译原理】》 仅供学习交流使用 推荐 第九章 总结及作业&#xff08;4…

态路小课堂丨三种实现光模块更高传输速率的技术你知道吗?

TARLUZ态路 随着云计算、大数据的快速兴起&#xff0c;数据中心以及电信运营商对光模块的传输速率要求越来越高。从1998年发展至今&#xff0c;光模块一直朝着更高的速率、更小的封装不断升级。光模块一般采用增加波长数、增加信号传输通道数量和提高单通道速率技术方案实现光模…

公众号内添加投票链接制作投票的软件网络投票器

手机互联网给所有人都带来不同程度的便利&#xff0c;而微信已经成为国民的系统级别的应用。 现在很多人都会在微信群或朋友圈里转发投票&#xff0c;对于运营及推广来说找一个合适的投票小程序能够提高工作效率&#xff0c;提高活动的影响力。 那么微信做投票的小程序哪个比较…

.vm文件发邮件时js未生效,无法控制显示隐藏

需求起因 最近在做一个发邮件的功能&#xff0c;是后端发邮件&#xff0c;不过邮件内容是由前端来写。 邮件内容包括姓名、手机号、邮箱&#xff0c;这三个参数都是不一定有的&#xff0c;如果没有某个参数时&#xff0c;那一行内容就不显示。 写法没错&#xff0c;但就是js…

npm详解

1.npm支持多个源&#xff08;没列全&#xff0c;有兴趣的可以自己去了解一下其他源&#xff09; &#xff08;1&#xff09;官方源&#xff1a;https://registry.npmjs.org &#xff08;2&#xff09;淘宝源&#xff1a;https://registry.npm.taobao.org &#xff08;3&#x…

《Java核心卷1》慢慢啃!读第3,4章 | 第12版

提醒&#xff1a;全文约6000字&#xff0c;是一份比较单纯的学习笔记&#xff0c;知识点基本采用条目的形式列出&#xff0c;起到查漏补缺和备忘录的作用&#xff0c;而对内容之间的逻辑结构并未进行仔细梳理。本文内容包括&#xff1a; Java的基本程序设计结构面向对象程序设计…

jmeter压力测试实战分析详解,一定要看完哦

目录 1.从压力测试说起 2.压力测试到底要关注什么 3.你想要的到底是个什么东西 4.面试总问的jvm调优到底是要干什么 5.常用的压力测试工具及命令 6.性能诊断到底难在哪里&#xff1f; 7.到底是加机器还是优化服务&#xff1f; 总结&#xff1a; 1.从压力测试说起 压力测…

59 KVM Skylark虚拟机混部-概述、架构及特性

文章目录 59 KVM Skylark虚拟机混部-概述、架构及特性59.1 Skylark概述59.1.1 问题背景59.1.2 总体介绍 59.2 架构及特性59.2.1 总体实现框架59.2.2 功耗干扰控制59.2.3 LLC/MB干扰控制59.2.4 CPU干扰控制 59 KVM Skylark虚拟机混部-概述、架构及特性 59.1 Skylark概述 59.1.…

Android SPI

1.SPI SPI全称Service Provider Interface&#xff0c;服务提供方接口&#xff0c;是Java提供的一套用来被第三方实现或者扩展的API&#xff0c;它可以用来启用框架扩展和替换组件。服务通常指一个接口或者一个抽象类&#xff0c;服务提供方是对这个接口或者抽象类的具体实现&…

kafka常见问题

1.为什么要用mq&#xff08;mq的作用&#xff09;&#xff1f; 2.引入mq会多哪些问题&#xff1f; 3. 如何解决这些问题&#xff1f; 1.1实现异步发送 有些复杂的业务系统&#xff0c;一次用户请求可能会同步调用N个系统的接口&#xff0c;需要等待所有的接口都返回了&#…

虹科分享 | 高考大数据可视化志愿填报分析-基于虹科Domo BI工具

高考是中国教育系统中一项极为重要的考试&#xff0c;它不仅是学生完成高中学业的重要标志&#xff0c;也是进入大学的门槛。每年高考都会吸引数百万学生参加&#xff0c;同时也吸引了各地高校和招生部门的关注。高考招生数据是教育研究和政策制定的重要依据&#xff0c;通过对…

技术管理第二板斧建团队-知人善用

1、什么是知人善用 知人善用就是指技术 Leader 怎么用对人&#xff1f;用好人&#xff1f;核心在于怎么给事情安排对的人&#xff1f;怎么给人安排合适的事情&#xff1f;其中&#xff0c;“人”与“事”相辅相成&#xff0c;如果把事情安排给对的人&#xff0c;不光会取得好结…

干货丨如何实现WinApp的UI自动化测试?自动化工具如何选择人?

WinApp&#xff08;WindowsAPP&#xff09;是运行在Windows操作系统上的应用程序&#xff0c;通常会提供一个可视的界面&#xff0c;用于和用户交互。例如运行在Windows系统上的Microsoft Office、PyCharm、Visual Studio Code、Chrome&#xff0c;都属于WinApp。常见的WinApp&…

Arduino IDE 2.1.0 下安装ESP32(2.0.9)

很久没玩Arduino了。新装了一台电脑&#xff0c;想重新捡起ESP32-WROOM-32开发板玩玩。官网上下了Arduino IDE 2.1.0&#xff0c;然后配置ESP32开发环境。 下载及安装Arduino IDE略过不谈。装完后还是老规矩&#xff0c;文件 -> 首选项&#xff0c;先把自定义板管理地址填入…

好程序员:2023年自学Java四阶段学习法,真滴好用麻啦!

同学们&#xff0c;我是好程序员小源&#xff0c;今天给大家整理了自学Java的四个阶段&#xff0c;大家可以按照这四个阶段学习哦~会更加规划系统一点&#xff01; 第一阶段: JavaSE[5周] 本阶段从零基础起步&#xff0c;荃面深入的学系JavaSE课程&#xff0c;主要内容包括Java…