【Python中图像相似性度量方法全面总结】

news2025/1/24 8:40:15

文章目录

    • 概要
    • 图像相似性概念
    • 基于直方图的相似性度量
    • 基于SSIM的相似性度量
    • 基于特征相似性的度量
    • 基于深度学习的方法
    • 小结

概要

在当今充斥着图像的世界中,衡量和量化图像之间的相似性已经成为一项至关重要的任务。不论是在图像检索、内容推荐还是视觉搜索等现代计算机视觉应用中,图像相似性方法都扮演着关键角色。

幸运的是,Python为开发者和研究者提供了丰富的工具和库,使得他们能够快速深入探讨这些技术,并加以实现。本文将深入探讨各种图像相似性技术,并演示如何在Python环境中灵活应用它们。通过本文,读者将了解到不同的图像相似性度量方法,以及如何在实际项目中运用这些方法,从而更好地理解和解决现实世界中的图像相似性问题。

图像相似性概念

`
像相似性是指两幅图像之间在视觉内容方面的相似程度。这个概念在计算机视觉、图像处理和模式识别等领域被广泛应用。理解图像相似性对于图像搜索、图像检索、图像匹配、目标识别等任务至关重要。

图像相似性可以在多个方面进行分析和计算:

颜色相似性: 这是指两幅图像中颜色分布的相似程度。颜色直方图是常用的颜色表示方法,通过比较两幅图像的颜色直方图,可以量化它们之间的颜色相似性。

形状相似性: 形状相似性描述了两幅图像中物体或者轮廓的形状相似程度。在形状分析中,常用的方法包括边缘检测和轮廓匹配等技术。

纹理相似性: 纹理是指图像中重复出现的纹理单元,纹理相似性衡量了两幅图像中纹理的相似度。常用的纹理特征包括灰度共生矩阵、小波变换等。

结构相似性: 结构相似性考虑了图像中物体或者场景的布局和空间关系,比如两幅图像中物体的相对位置、大小等。

为了量化这些相似性,研究者们提出了各种数学模型和计算方法。其中一种常用的方法是计算相似性分数,这个分数通常在0到1之间,表示两幅图像的相似程度。当分数接近1时,表示两幅图像非常相似,而当分数接近0时,表示两幅图像差异很大。

基于直方图的相似性度量

在这里插入图片描述

们使用了Python的OpenCV库来比较两幅图像的直方图,并计算它们之间的相似性分数。下面是代码的详细解释:

导入OpenCV库: 首先,我们导入了OpenCV库,这是一个用于计算机视觉任务的流行库。
import cv2

加载图像: 我们使用cv2.imread()函数加载两幅图像。

image1 = cv2.imread(image1)
image2 = cv2.imread(image2)

计算直方图: 我们使用cv2.calcHist()函数计算图像的直方图。这里我们计算了3D直方图,涵盖了图像的三个颜色通道(蓝色、绿色、红色),每个通道256个灰度级。

hist_img1 = cv2.calcHist([image1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
hist_img2 = cv2.calcHist([image2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])

归一化直方图: 归一化操作将直方图的值范围限制在0到1之间,使得直方图可以用来比较不同尺度和分辨率的图像。

cv2.normalize(hist_img1, hist_img1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
cv2.normalize(hist_img2, hist_img2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)

比较直方图相似性: 我们使用cv2.compareHist()函数比较两幅图像的直方图。这里使用了cv2.HISTCMP_CORREL作为比较方法,该方法计算两个直方图的相关性,得分范围在-1到1之间。得分越接近1,表示两幅图像的相似性越高。

metric_val = cv2.compareHist(hist_img1, hist_img2, cv2.HISTCMP_CORREL)

输出相似性分数: 最后,我们将计算得到的相似性分数进行输出。

print(f"Similarity Score: ", round(metric_val, 2))

在这个例子中,输出的Similarity Score是两幅图像的相似性分数,值为0.94,表示这两幅图像在颜色分布上非常相似。你可以根据不同的比较方法(比如cv2.HISTCMP_CHISQR或cv2.HISTCMP_BHATTACHARYYA等)来得到不同类型的相似性分数,具体选择哪种方法取决于你。
全部代码:

import cv2
# Load images
image1 = cv2.imread(image1)
image2 = cv2.imread(image2)
hist_img1 = cv2.calcHist([image1], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
hist_img1[255, 255, 255] = 0 #ignore all white pixels
cv2.normalize(hist_img1, hist_img1, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
hist_img2 = cv2.calcHist([image2], [0, 1, 2], None, [256, 256, 256], [0, 256, 0, 256, 0, 256])
hist_img2[255, 255, 255] = 0  #ignore all white pixels
cv2.normalize(hist_img2, hist_img2, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX)
# Find the metric value
metric_val = cv2.compareHist(hist_img1, hist_img2, cv2.HISTCMP_CORREL)
print(f"Similarity Score: ", round(metric_val, 2))

结果

Similarity Score: 0.94

基于SSIM的相似性度量

结构相似性指数(SSIM)是一种广泛用于图像质量评估的指标,它不仅仅考虑了图像的亮度、对比度和结构,还模拟了人眼对图像的感知。SSIM的取值范围在-1到1之间,其中1表示两幅图像完全相同,-1表示两幅图像完全不同。

在Python中,你可以使用scikit-image库来计算两幅图像的SSIM。以下是一个简单的示例:
导入库:

import cv2
from skimage import metrics

首先,我们导入了OpenCV和scikit-image库,分别用于图像处理和SSIM计算。

加载图像:

image1 = cv2.imread(image1)
image2 = cv2.imread(image2)

这里我们加载了两幅图像。

调整图像尺寸:

image2 = cv2.resize(image2, (image1.shape[1], image1.shape[0]), interpolation=cv2.INTER_AREA)

如果两幅图像的尺寸不同,我们通过cv2.resize()函数将它们的尺寸调整为相同,以便进行比较。

将图像转换为灰度图:

image1_gray = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
image2_gray = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

我们将彩色图像转换为灰度图像,因为SSIM通常在灰度图上进行计算。

计算SSIM:

ssim_score = metrics.structural_similarity(image1_gray, image2_gray, full=True)

使用skimage.metrics.structural_similarity()函数计算两幅灰度图像的SSIM。这个函数返回一个包含SSIM分数的元组。在这个示例中,我们用ssim_score[0]获取了SSIM分数。

输出SSIM分数:

print(f"SSIM Score: ", round(ssim_score[0], 2))

最后,我们将计算得到的SSIM分数输出。SSIM分数的范围是-1到1,值越接近1,表示两幅图像的结构相似性越高。

完整代码:

from skimage.metrics import structural_similarity as ssim
import cv2

# 加载图像
image1 = cv2.imread(image1)
image2 = cv2.imread(image2)

# 将图像转换为灰度图
gray_image1 = cv2.cvtColor(image1, cv2.COLOR_BGR2GRAY)
gray_image2 = cv2.cvtColor(image2, cv2.COLOR_BGR2GRAY)

# 计算SSIM
ssim_score, _ = ssim(gray_image1, gray_image2, full=True)

# 输出相似性分数
print(f"SSIM Score: {ssim_score:.2f}")

在这个示例中,我们首先使用OpenCV将两幅图像转换为灰度图,因为SSIM通常在灰度图上计算。然后,我们使用skimage.metrics.structural_similarity函数来计算两幅灰度图像的SSIM分数。ssim()函数的第三个参数full为True表示返回完整的SSIM图像,但在这个示例中我们只关心SSIM分数,因此用下划线将其忽略。

SSIM分数越接近1,表示两幅图像的结构相似性越高。使用SSIM指标,你可以更全面地了解图像之间的相似性,因为它不仅仅考虑了像素值的相似性,还考虑了图像的结构信息,使得评估更加准确。

基于特征相似性的度量

基于特征相似性的度量方法是一种常用于图像处理和计算机视觉领域的技术。这些方法通常涉及从图像中提取出关键特征,然后比较这些特征之间的相似性或差异性。在这个过程中,尺度不变特征变换(SIFT)和加速鲁棒特征(SURF)是两种常用的特征提取算法。
使用OpenCV提取图像的SIFT和SURF特征

首先,确保你已经安装了OpenCV库。如果没有安装,你可以使用以下命令进行安装:

pip install opencv-python

然后,你可以使用以下代码示例来提取两幅图像的SIFT和SURF特征:

import cv2

# 读取两张图像
image1 = cv2.imread('image1.jpg', cv2.IMREAD_GRAYSCALE)
image2 = cv2.imread('image2.jpg', cv2.IMREAD_GRAYSCALE)

# 创建SIFT对象
sift = cv2.SIFT_create()

# 在图像上检测SIFT关键点和描述符
keypoints1, descriptors1 = sift.detectAndCompute(image1, None)
keypoints2, descriptors2 = sift.detectAndCompute(image2, None)

# 创建SURF对象
surf = cv2.xfeatures2d.SURF_create()

# 在图像上检测SURF关键点和描述符
keypoints_surf1, descriptors_surf1 = surf.detectAndCompute(image1, None)
keypoints_surf2, descriptors_surf2 = surf.detectAndCompute(image2, None)

# 进行特征匹配
# 在实际应用中,你可能需要使用更复杂的算法(如FLANN匹配器)来提高匹配的准确性
bf = cv2.BFMatcher()
matches_sift = bf.knnMatch(descriptors1, descriptors2, k=2)
matches_surf = bf.knnMatch(descriptors_surf1, descriptors_surf2, k=2)

# 应用比率测试,以获得较好的匹配结果
good_matches_sift = []
good_matches_surf = []
for m, n in matches_sift:
    if m.distance < 0.75 * n.distance:
        good_matches_sift.append([m])
for m, n in matches_surf:
    if m.distance < 0.75 * n.distance:
        good_matches_surf.append([m])

# 绘制匹配结果
img_matches_sift = cv2.drawMatchesKnn(image1, keypoints1, image2, keypoints2, good_matches_sift, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)
img_matches_surf = cv2.drawMatchesKnn(image1, keypoints_surf1, image2, keypoints_surf2, good_matches_surf, None, flags=cv2.DrawMatchesFlags_NOT_DRAW_SINGLE_POINTS)

# 显示匹配结果图像
cv2.imshow('SIFT Matches', img_matches_sift)
cv2.imshow('SURF Matches', img_matches_surf)
cv2.waitKey(0)
cv2.destroyAllWindows()

请确保将image1.jpg和image2.jpg替换为你要比较的两幅图像的文件路径。

在上述示例中,我们使用了SIFT和SURF特征提取算法,并进行了特征匹配。匹配结果被画在了两幅图像上。在实际应用中,你可能需要根据你的需求调整特征提取和匹配的参数,以获得最好的匹配结果。

基于深度学习的方法

基于深度学习的方法已经在图像相似性任务中取得了显著的成果。使用预训练的卷积神经网络(CNNs),例如ResNet、VGG和Inception,可以轻松地从图像中提取深层特征,这种特征提取的方法彻底改变了图像相似性任务的处理方式。

其中,来自OpenAI的Contrastive Language-Image Pre-Training(CLIP)是一种多模式零样本图像分类器,它在广泛的领域中取得了卓越的效果,而且可以在没有微调的情况下使用。我们可以使用开源的训练代码在自己的图像和文本数据集上对CLIP模型进行微调,以更好地适应特定任务。

下面是一个简单的示例,演示了如何使用基于CLIP的预训练模型以及torch、open_clip和sentence_transformers库来比较两幅图像的相似性:

首先,确保你已经安装了CLIP以及所需的依赖库。如果没有安装,你可以使用以下命令进行安装:

!pip install git+https://github.com/openai/CLIP.git
!pip install open_clip_torch
!pip install sentence_transformers

然后,导入必要的库并进行初始化设置:

import torch
import open_clip
import cv2
from sentence_transformers import util
from PIL import Image

# 初始化CLIP模型和预处理步骤
device = "cuda" if torch.cuda.is_available() else "cpu"
model, _, preprocess = open_clip.create_model_and_transforms('ViT-B-16-plus-240', pretrained="laion400m_e32")
model.to(device)

# 定义图像编码函数
def imageEncoder(img):
    img1 = Image.fromarray(img).convert('RGB')
    img1 = preprocess(img1).unsqueeze(0).to(device)
    img1 = model.encode_image(img1)
    return img1

# 定义计算相似性分数的函数
def generateScore(image1, image2):
    test_img = cv2.imread(image1, cv2.IMREAD_UNCHANGED)
    data_img = cv2.imread(image2, cv2.IMREAD_UNCHANGED)
    img1 = imageEncoder(test_img)
    img2 = imageEncoder(data_img)
    cos_scores = util.pytorch_cos_sim(img1, img2)
    score = round(float(cos_scores[0][0])*100, 2)
    return score

# 输入两幅图像的文件路径,并计算它们之间的相似性分数
image1 = 'path/to/your/image1.jpg'
image2 = 'path/to/your/image2.jpg'
print(f"Similarity Score: {generateScore(image1, image2)}")

在这个示例中,generateScore函数接受两个图像的文件路径作为输入,并返回它们之间的相似性分数。这个分数是通过计算两幅图像中特征向量的余弦相似性来得出的。在实际应用中,你可以将这个方法扩展到处理大量图像,并用于图像检索、相似性匹配等任务

小结

图像相似性度量在计算机视觉领域中具有重要意义,用于衡量图像之间的相似度或差异度。在Python中,有多种方法可用于图像相似性度量,其中包括基于特征相似性的度量和基于深度学习的方法。

基于特征相似性的度量方法通常包括特征提取和特征匹配两个步骤。常用的特征提取算法包括尺度不变特征变换(SIFT)和加速鲁棒特征(SURF),这些算法能够识别图像中的关键点,并提取描述这些关键点的特征向量。通过特征匹配,可以计算两幅图像之间的相似性分数。Python中的OpenCV库提供了便捷的接口,可以用于实现这些特征提取和匹配的操作。

另一种常用的方法是基于深度学习的图像相似性度量。使用预训练的卷积神经网络(CNNs)如ResNet、VGG和Inception,以及特定任务的预训练模型如Contrastive Language-Image Pre-Training(CLIP),可以从图像中提取深层特征。这些特征可以用于计算图像之间的相似性。借助Python中的深度学习框架如PyTorch,我们能够轻松地实现这些方法,并在自定义数据集上进行训练和评估。

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

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

相关文章

【LeetCode】148. 排序链表

148. 排序链表&#xff08;中等&#xff09; 方法一&#xff1a;归并排序&#xff08;递归法&#xff09; 思路 题目要求时间空间复杂度分别为 O(nlogn) 和 O(1) &#xff0c;根据时间复杂度我们自然想到二分法&#xff0c;从而联想到归并排序&#xff1b; 对数组做归并排序的…

毫米波雷达在环境监测中的关键作用

随着环境问题的日益凸显&#xff0c;精确、实时的环境监测成为了保护地球的关键一环。在这个背景下&#xff0c;毫米波雷达技术逐渐崭露头角&#xff0c;以其在环境监测中的独特优势成为不可或缺的工具。本文将探讨毫米波雷达在环境监测中的关键作用&#xff0c;以及它是如何应…

Unity3D 基础——使用 Vector3.Lerp 实现缓动效果

让一个物体从当前位置移动到另一个位置 Vector3-Lerp - Unity 脚本 APIhttps://docs.unity.cn/cn/current/ScriptReference/Vector3.Lerp.html 1.在场景中新建两个 Cube 立方体&#xff0c;在 Scene 视图中将两个 Cude的位置错开。 2.新建 C# 脚本 MoveToTarget.cs&#xff08…

MS5542数模转换器可pin对pin兼容DAC8831

MS5541/MS5542 是一款单通道、16 位、串行输入、电压输出的数模转换器&#xff0c;采用 2.7V 至 5.5V 单电源供电&#xff0c;输出范围为 0V 至 VREF。在输出范围内保证单调性&#xff0c;在温度范围为-40C至85C 能够提供 1LSB INL 的 14 位精度。MS5541/MS5542 提供无缓冲输出…

如何绕过api的防重放做安全测试

一、问题引入&#xff1a;api接口测试&#xff0c;会检测请求头中的nonce参数的值&#xff0c;每次请求的值必须不同&#xff0c;否则发包失败 笔者在进行api接口的测试时&#xff08;因为菜没有工具&#xff0c;只能另辟蹊跷&#xff09;&#xff0c;使用postmanxray进行安全测…

【LeetCode】《LeetCode 101》第十三章:链表

文章目录 13.1 数据结构介绍13.2 链表的基本操作206. 反转链表&#xff08;简单&#xff09;21. 合并两个有序链表&#xff08;简单&#xff09;24.两两交换链表中的节点&#xff08;中等&#xff09; 13.3 其它链表技巧160. 相交链表&#xff08;简单&#xff09;234. 回文链表…

Typora +Picgo 搭建个人笔记

文章目录 Typora Picgo 搭建个人笔记一、Picgo Github 搭建图床1.基础设置2. 将配置导出&#xff0c;方便下次使用 二、Typora&#xff1a;设置 &#xff1a;1. 基本设置2. 导出自动提交3. 备份图片 Typora Picgo 搭建个人笔记 typora 下载地址&#xff1a; https://zahui.fan…

使用UniApp实现视频数组自动下载与播放功能:一步步指导

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

阶段性总结

uart协议&#xff1a; 通用异步收发器 UART&#xff08;Universal Asynchronous Receiver/Transmitter)&#xff0c;是一种串行、异步、全双工的通信协议&#xff0c;将所需传输的数据一位接一位地传输&#xff0c;在UART通讯协议中信号线上的状态位高电平代表’1’&#xff0…

Java应用性能问题诊断技巧

作者&#xff1a;张彦东 参考&#xff1a;https://developer.aliyun.com/ebook/450?spma2c6h.20345107.ebook-index.28.6eb21f54J7SUYc 文章目录 &#xff08;一&#xff09;内存1.内存2.内存-JMX3.内存-Jmap4.内存-结合代码确认问题 &#xff08;二&#xff09;CPU1.CPU-JMX或…

短视频矩阵系统源码开发

短视频剪辑矩阵系统开发源码----源头搭建 一、源码技术构建源码部署搭建交付之---- 1.需要协助系统完成部署、接口全部正常接入、系统正常运行多久&#xff1f;7个工作日 2.需要准备好服务器以及备案域名 3.短视频SEO模块一年项目带宽&#xff0c;带宽最低要求10M&#xff0c;…

如何将电脑上的“小电影”隐藏为一张图片?这波操作绝了!!

大家好&#xff0c;我是冰河~~ 最近&#xff0c;有很多小伙伴想跟我学渗透。平时时间确实太忙了&#xff0c;除了要研发公司项目外&#xff0c;写公号&#xff0c;写博客&#xff0c;录视频&#xff0c;写书稿&#xff0c;维护开源项目&#xff0c;几乎占据了我全部的业余时间…

【性能测试】使用JMeter对code论坛进行压力测试

1.项目介绍 项目简介 code 论坛是一个技术交流社区。主要功能有发布帖子&#xff0c;查看帖子&#xff0c;评价帖子&#xff0c;删除帖子&#xff0c;点赞帖子&#xff0c;站内信&#xff0c;个人中心&#xff0c;修改个人信息等。是一个基于 Spring 的前后端分离项目。 项目链…

vue3自定义指令批量注册

第一步、在src目录下新建directives文件文件夹 用来存放不同的指令&#xff0c;以dbounce指令为例&#xff1a; 第二步、在directives目录下创建debounce.js文件&#xff0c;文件内容如下&#xff1a; // 防抖 const debounceClick {mounted(el, binding) {let timerel.addE…

点云处理【三】(点云降采样)

点云降采样 第一章 点云数据采集 第二章 点云滤波 第二章 点云降采样 1. 为什么要降采样&#xff1f; 我们获得的数据量大&#xff0c;特别是几十万个以上的点云&#xff0c;里面有很多冗余数据&#xff0c;会导致处理起来比较耗时。 降采样是一种有效的减少数据、缩减计算量…

喜报 | 擎创科技实力亮相2023科创会并荣获科技创新奖

近日&#xff0c;由国家互联网数据中心产业技术创新战略联盟&#xff08;NIISA&#xff09;主办的“2023第二届国际互联网产业科技创新大会暨互联网创新产品展览会”于北京圆满落幕。 擎创科技副总裁冯陈湧受邀出席本次论坛&#xff0c;并发表了“银行分布式核心智能运维体系思…

毫米波雷达模块技术革新:在自动驾驶汽车中的前沿应用

随着自动驾驶技术的快速发展&#xff0c;毫米波雷达模块的技术革新成为推动这一领域的关键因素之一。本文将深入研究毫米波雷达模块技术的最新进展&#xff0c;并探讨其在自动驾驶汽车中的前沿应用。 毫米波雷达模块的基本原理 解释毫米波雷达模块的基本工作原理&#xff0c;强…

Goby 漏洞发布|Honeywell PM43 loadfile.lp 文件命令执行漏洞(CVE-2023-3710)

漏洞名称&#xff1a;Honeywell PM43 loadfile.lp 文件命令执行漏洞&#xff08;CVE-2023-3710&#xff09; English Name&#xff1a;Honeywell PM43 loadfile.lp file command execution vulnerability (CVE-2023-3710) CVSS core: 9.8 影响资产数&#xff1a; 96 漏洞描…

等保三级测评(MySQL)

mysql版本号:5.7.x 进入Mysql 通过mysql -u root -p 进入MySQL命令行,开展数据库配置核查; a)应对登录的用户进行身份标识和鉴别,身份标识具有唯一性,身份鉴别信息具有复杂度要求并定期更换; SELECT Host,User,authentication_string,plugin FROM mysql.user;b)被测…

软件测试(一)概念

软件测试 软件测试的生命周期&#xff1a; 需求分析→测试计划→ 测试设计、测试开发→ 测试执行→ 测试评估 需求分析&#xff1a;需求是非完整&#xff0c;需求是否正确测试计划&#xff1a;确定软件由谁测试&#xff0c;什么时候开始&#xff0c;什么时候结束&#xff0c;…