将两张图片的不同标记出来

  1. 差异过于细微,阈值设置不当:您的差异可能是颜色或位置的微小变化,当前的阈值和处理方式可能不足以检测到这些细微差异。

  2. 图像配准不够精确:由于两张图片内容高度相似,特征点匹配可能存在误差,导致图像对齐不准确,影响差异检测。

  3. 灰度处理损失了颜色信息:如果差异体现在颜色上,转换为灰度图后,颜色变化可能被忽略。

  4. 形态学操作和面积过滤参数不合适:形态学处理和面积过滤的参数可能导致小的差异区域被过滤掉。


解决方案

1. 降低阈值,提高敏感度
  • 降低阈值:在阈值处理步骤中,将阈值从30降低到更小的值,如510,使得对细微差异更加敏感。

    _, thresh = cv2.threshold(diff, 5, 255, cv2.THRESH_BINARY)
    
2. 使用彩色图像进行差异检测
  • 直接计算彩色图像的差异:由于差异可能体现在颜色上,使用彩色图像的差异计算会更有效。

    # 计算彩色图像的差异
    diff_color = cv2.absdiff(img1_aligned, img2_color)
    # 转换为灰度图
    diff_gray = cv2.cvtColor(diff_color, cv2.COLOR_BGR2GRAY)
    # 阈值处理
    _, thresh = cv2.threshold(diff_gray, 5, 255, cv2.THRESH_BINARY)
    
3. 使用结构相似性(SSIM)
  • SSIM对细微差异更敏感:使用SSIM可以检测到亮度、对比度和结构上的微小变化。

    from skimage.metrics import structural_similarity as ssim# 计算SSIM
    score, diff = ssim(img1_aligned_gray, img2_gray, full=True)
    diff = (diff * 255).astype("uint8")
    diff = cv2.bitwise_not(diff)  # 反转图像
    # 阈值处理
    _, thresh = cv2.threshold(diff, 5, 255, cv2.THRESH_BINARY)
    

    注意:需要安装scikit-image库:

    pip install scikit-image
    
4. 调整形态学操作和面积阈值
  • 形态学操作:调整迭代次数和核大小,以保留更多细节。

    kernel = np.ones((3, 3), np.uint8)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)
    thresh = cv2.dilate(thresh, kernel, iterations=1)
    
  • 降低面积过滤阈值:减少cv2.contourArea()的阈值,确保小的差异区域也能被标记。

    if area > 5:  # 从50降低到5
    
5. 验证图像配准效果
  • 可视化匹配的特征点:检查特征点匹配是否准确。

    # 绘制前50个匹配点
    img_matches = cv2.drawMatches(img1_color, keypoints1, img2_color, keypoints2, good_matches[:50], None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
    cv2.imshow('Matches', img_matches)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    
  • 尝试其他特征检测器:如SIFTSURF,但需注意它们的许可证要求。


修改后的完整代码

import cv2
import numpy as np
from skimage.metrics import structural_similarity as ssim# 读取两张图片
img1_color = cv2.imread('find_difference_image1.png')  # 待配准的原始图像1
img2_color = cv2.imread('find_difference_image2.png')  # 基准的原始图像2# 检查图片是否成功读取
if img1_color is None or img2_color is None:print("错误:无法读取图片。请检查文件路径。")exit()# 将图片转换为灰度图
img1_gray = cv2.cvtColor(img1_color, cv2.COLOR_BGR2GRAY)
img2_gray = cv2.cvtColor(img2_color, cv2.COLOR_BGR2GRAY)# 创建ORB特征检测器
orb = cv2.ORB_create(10000)  # 增加特征点数量# 检测并计算特征点和描述子
keypoints1, descriptors1 = orb.detectAndCompute(img1_gray, None)
keypoints2, descriptors2 = orb.detectAndCompute(img2_gray, None)# 创建BFMatcher对象
bf = cv2.BFMatcher(cv2.NORM_HAMMING)# KNN匹配,k=2
matches = bf.knnMatch(descriptors1, descriptors2, k=2)# 过滤匹配结果,应用比值测试(Lowe's ratio test)
good_matches = []
for m, n in matches:if m.distance < 0.75 * n.distance:good_matches.append(m)# 检查是否有足够的匹配点
if len(good_matches) > 10:# 提取匹配的关键点坐标src_pts = np.float32([keypoints1[m.queryIdx].pt for m in good_matches]).reshape(-1, 1, 2)dst_pts = np.float32([keypoints2[m.trainIdx].pt for m in good_matches]).reshape(-1, 1, 2)# 计算Homography矩阵M, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0)# 将img1变换到img2的坐标系h, w = img2_gray.shapeimg1_aligned = cv2.warpPerspective(img1_color, M, (w, h))# 使用SSIM计算差异img1_aligned_gray = cv2.cvtColor(img1_aligned, cv2.COLOR_BGR2GRAY)score, diff = ssim(img1_aligned_gray, img2_gray, full=True)diff = (diff * 255).astype("uint8")diff = cv2.bitwise_not(diff)  # 反转图像# 阈值处理_, thresh = cv2.threshold(diff, 5, 255, cv2.THRESH_BINARY)# 使用形态学操作去除噪声和小的差异kernel = np.ones((3, 3), np.uint8)thresh = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=1)thresh = cv2.dilate(thresh, kernel, iterations=1)# 查找差异区域的轮廓contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)# 计算逆变换矩阵M_inv = np.linalg.inv(M)# 在原始的img1_color上绘制差异区域for contour in contours:area = cv2.contourArea(contour)if area > 5:# 将轮廓坐标转换为浮点型contour = contour.astype(np.float32)# 使用逆变换矩阵将坐标变换回img1的坐标系contour_transformed = cv2.perspectiveTransform(contour, M_inv)# 将坐标转换为整数contour_transformed = contour_transformed.astype(np.int32)# 绘制轮廓cv2.drawContours(img1_color, [contour_transformed], -1, (0, 0, 255), 2)# 在原始图像2上绘制差异区域for contour in contours:area = cv2.contourArea(contour)if area > 5:cv2.drawContours(img2_color, [contour], -1, (0, 0, 255), 2)# 调整图片大小以便显示img1_original_resized = cv2.resize(cv2.imread('find_difference_image1.png'), (400, 300))img2_original_resized = cv2.resize(cv2.imread('find_difference_image2.png'), (400, 300))img1_diff_resized = cv2.resize(img1_color, (400, 300))img2_diff_resized = cv2.resize(img2_color, (400, 300))# 将四张图片拼接成一张图片top_row = np.hstack((img1_original_resized, img2_original_resized))bottom_row = np.hstack((img1_diff_resized, img2_diff_resized))combined_image = np.vstack((top_row, bottom_row))# 显示组合后的图片cv2.imshow('Original and Difference Images', combined_image)cv2.waitKey(0)cv2.destroyAllWindows()
else:print("匹配点不足,无法计算Homography矩阵。")exit()

进一步的建议

  • 检查配准质量:使用cv2.drawMatches()可视化特征点匹配,确保配准准确。

  • 调整SSIM参数ssim()函数的参数可以调整,如gaussian_weightssigma等,以提高对细微差异的检测能力。

  • 尝试其他差异检测方法:如计算颜色直方图的差异,或者使用更高级的图像差异算法。

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

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

相关文章

如何区分不同类型的光源

" 声明&#xff1a;此文档中的大部分内容来源于网络&#xff0c;经校对和整理后分享给大家&#xff0c;仅供学习参考使用。" 1、问题背景 之前调试的项目中&#xff0c;客户提供的客观验收标准中要求用到TL83光源&#xff0c;用来测试图像的颜色误差及白平衡。 TL83光…

用Java爬虫API,轻松获取taobao商品SKU信息

在电子商务的世界里&#xff0c;SKU&#xff08;Stock Keeping Unit&#xff0c;库存单位&#xff09;是商品管理的基础。对于商家来说&#xff0c;SKU的详细信息对于库存管理、价格策略制定、市场分析等都有着重要作用。taobao作为中国最大的电子商务平台之一&#xff0c;提供…

windows下载配置CAS单点登录

下载 github下载 云盘瞎子啊 版本对应jdk&#xff0c;根据自身环境下载对应版本的cas。 安装 下载完成之后解压 按照.md文档执行打包命令 build.bat package配置 如果不用https&#xff0c;需要进行以下配置&#xff1a; 修改配置文件application.properties 在最后一行…

SAP推出AI支出管理解决方案

SAP公司近日宣布&#xff0c;已将其生成式人工智能助手Joule整合至SAP Ariba和SAP Fieldglass的支出管理解决方案中&#xff0c;以增强企业在战略协作、生产力、合规性和业务洞察等方面的能力。这一消息是在10月15日于拉斯维加斯举行的SAP Spend Connect Live大会上发布的。嵌入…

【远程监控新体验】OpenObserve结合内网穿透无公网IP远程访问全攻略

文章目录 前言1. 安装Docker2. Docker镜像源添加方法3. 创建并启动OpenObserve容器4. 本地访问测试5. 公网访问本地部署的OpenObserve5.1 内网穿透工具安装5.2 创建公网地址6. 配置固定公网地址前言 本文主要介绍如何在Linux系统使用Docker快速本地化部署OpenObserve云原生可观…

Ajax处理错误信息(处理响应报文)

<!DOCTYPE html> <html><head><meta charset"utf-8" /><title></title></head><body><form action""><div>用户名<input type"text" class"username"></div>…

时间序列神器Prophet教程2-饱和预测

公众号&#xff1a;尤而小屋编辑&#xff1a;Peter作者&#xff1a;Peter 大家好&#xff0c;我是Peter~ 本文是时间序列预测神器Prophet的第二篇&#xff1a;使用Prophet如何实现饱和预测 饱和预测增长-Saturating Forecasts 默认情况下&#xff0c;Prophet 使用线性模型来…

单点登录(Single Sign-On, SSO)

单点登录&#xff08;Single Sign-On, SSO&#xff09;是一种身份验证机制&#xff0c;允许用户使用一组凭据&#xff08;如用户名和密码&#xff09;登录一次&#xff0c;即可访问多个相关但独立的软件系统。SSO 的主要目的是简化用户的登录过程&#xff0c;提高用户体验&…

【C++】string类(2)

&#x1f973;个人主页: 起名字真南 &#x1f973;个人专栏:【数据结构初阶】 【C语言】 【C】 目录 引言1 模拟实现string类基本框架2 实现string类中的主要成员函数2.1 Push_Back 函数2.2 reserve 函数2.3 append 函数2.4 c_str 函数2.5 begin ,end 函数2.5 operator 函数2.6…

基于STM32设计的实验室安全预警系统(OneNet)(246)

文章目录 一、前言1.1 项目介绍【1】开发背景【2】项目实现的功能【3】项目硬件模块组成【4】ESP8266工作模式配置1.2 设计思路【1】整体设计思路【2】整体构架1.3 项目开发背景【1】选题的意义【2】可行性分析【3】参考文献【4】摘要1.4 开发工具的选择【1】设备端开发【2】上…

除了 Python,还有哪些语言适合做爬虫?

以下几种语言也适合做爬虫&#xff1a; 一、Java* 优势&#xff1a; 强大的性能和稳定性&#xff1a;Java 运行在 Java 虚拟机&#xff08;JVM&#xff09;上&#xff0c;具有良好的跨平台性和出色的内存管理机制&#xff0c;能够处理大规模的并发请求和数据抓取任务&#x…

VScode写Java项目的教程

VScode写Java项目的教程 1.首先必选先安装Java解释器2.安装插件Java Extension Pack3.创建项目创建项目结构选择项目类型 4.测试结果源码内容 今天用一台老式笔记本写代码&#xff0c;IDEA跑不动就准备用VScode突然间就蒙了&#xff0c;怎么创建项目啊&#xff1f;于是就有了这…

自动驾驶系列—加速自动驾驶系统开发:多型号SoC快速适配的最佳实践

&#x1f31f;&#x1f31f; 欢迎来到我的技术小筑&#xff0c;一个专为技术探索者打造的交流空间。在这里&#xff0c;我们不仅分享代码的智慧&#xff0c;还探讨技术的深度与广度。无论您是资深开发者还是技术新手&#xff0c;这里都有一片属于您的天空。让我们在知识的海洋中…

Python编程探索:从基础语法到循环结构实践(下)

文章目录 前言&#x1f377;四、 字符串拼接&#xff1a;连接多个字符串&#x1f378;4.1 使用 操作符进行字符串拼接&#x1f378;4.2 使用 join() 方法进行字符串拼接&#x1f378;4.3 使用 format() 方法进行格式化拼接&#x1f378;4.4 使用 f-string&#xff08;格式化字…

闭包导致内存泄漏是个伪命题?

什么是闭包&#xff1f; 在JavaScript中&#xff0c;闭包是一个函数与其外部词法环境的组合。闭包允许函数访问其外部作用域的变量&#xff0c;即使在外部函数已经返回之后。这是JavaScript中一个强大的特性&#xff0c;常用于数据封装、模块化等。 什么是内存泄漏&#xff1…

OpenWRT 和 Padavan 路由器配置网络打印机 实现远程打印

本文首发于只抄博客&#xff0c;欢迎点击原文链接了解更多内容。 前言 之前有给大家介绍过 Armbian 安装 CUPS 作为打印服务器&#xff0c;像是 N1 盒子、玩客云&#xff0c;甚至是随身 WiFi 都可以通过 CUPS 来进行打印。但是有些朋友不想专门为打印机添置一个设备&#xff0…

每天5分钟玩转C#/.NET之C#语言详细介绍

C#语言介绍 C# 语言是适用于 .NET 平台&#xff08;免费的跨平台开源开发环境&#xff09;的最流行语言。 C# 程序可以在许多不同的设备上运行&#xff0c;从物联网 (IoT) 设备到云以及介于两者之间的任何设备。 可为手机、台式机、笔记本电脑和服务器编写应用。C# 是一种跨平…

周末总结(2024/10/19)

工作 人际关系核心实践&#xff1a; 要学会随时回应别人的善意&#xff0c;执行时间控制在5分钟以内 坚持每天早会打招呼 遇到接不住的话题时拉低自己&#xff0c;抬高别人(无阴阳气息) 朋友圈点赞控制在5min以内&#xff0c;职场社交不要放在5min以外 职场的人际关系在面对利…

iba Data Export 导出面板选项

时间线选择真实时间“Absolute date / time” 时间间隔选择0.5Sec.&#xff08;最小为0.01Sec.&#xff09; 右侧数据根据需要选择

数学建模算法与应用 第15章 预测方法

目录 15.1 微分方程模型 Matlab代码示例&#xff1a;求解简单的微分方程 15.2 灰色预测模型&#xff08;GM&#xff09; Matlab代码示例&#xff1a;灰色预测模型 15.3 自回归模型&#xff08;AR&#xff09; Matlab代码示例&#xff1a;AR模型的预测 15.4 指数平滑法 M…