OpenCV书签 #互信息的原理与相似图片搜索实验

1. 介绍

互信息(Mutual Information) 是信息论中的一个概念,用于衡量两个随机变量之间的关联程度。在图像处理和计算机视觉中,互信息常被用来度量两幅图像之间的相似性。

互信息可以看成是一个随机变量中包含的关于另一个随机变量的信息量,或者说是一个随机变量由于已知另一个随机变量而减少的不肯定性对任意随机变量。比如,不会由于你知道了一个事件,反而使另一个事件的不确定度增加。

1.1 助记

这里引用知乎神贴 - 什么是互信息 中的比喻:

比如说有一天你的女神突然问你:“你猜猜我的爱豆是TFboys里的谁?”
唉,这要是猜不到,女神的心岂不是很完蛋,追求女神的路从此就凉了。
正当你非常不确定的时候,女神又说:“给你个提示吧,名字是四个字。”
此时你特别开心,因为对于答案的不确定性一下子就减少了(当然这个例子比较极端,不确定性直接降为0)

所以,互信息的意思就是,通过了知道一个变量减少了对另一个变量的不确定性。

这个不确定性减少的量也就是互信息的大小。

 

2. 魔法

使用互信息来度量两幅图像之间的相似性,只需要三步核心操作:

  1. 图像配准: Image Registration,在使用互信息进行相似性度量之前,通常需要对图像进行配准,确保它们对齐。这可以通过一些配准算法来实现,确保图像的空间位置相匹配。
  2. 计算互信息: 使用配准后的图像,计算它们之间的互信息。可以使用一些图像处理库,如 Scikit-ImageOpenCV,来实现互信息的计算。
  3. 相似性度量: 可以根据具体的需求和任务,设定一个阈值,选择互信息值高于该阈值的图像作为相似图像。

 

3. 实验

3.1 魔法拆解

第一步:图像配准

图像配准(Image Registration),在使用互信息进行相似性度量之前,通常需要对图像进行配准,确保它们对齐。这可以通过一些配准算法来实现,确保图像的空间位置相匹配。

# 读取图像
img1 = cv2.imread(img1_path)
img2 = cv2.imread(img2_path)# 检查图像形状,保证两个图像必须具有相同的尺寸,即相同的高度和宽度
if img1.shape != img2.shape:# 调整图像大小,使它们具有相同的形状img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))

第二步:计算互信息

使用配准后的图像,计算它们之间的互信息。可以使用一些图像处理库,如 Scikit-ImageOpenCV,来实现互信息的计算。

这里我们先使用灰度直方图来计算互信息:

# 将直方图归一化
# 即将直方图中的每个元素除以直方图的总和,以确保它们的和为1
# 这样做的目的是为了消除不同图像的像素数量差异,使得直方图的形状更具可比性
hist1 /= hist1.sum()
hist2 /= hist2.sum()# 计算两个归一化直方图的互信息
mutual_score = np.sum(np.minimum(hist1, hist2))
print(f"图像2:{os.path.basename(img2_path)} 与 图像1:{img1_path} 的相似性指数:{mutual_score}")

这里首先使用 np.minimum 函数计算 hist1 和 hist2 中每个对应位置的元素的较小值,然后使用 np.sum 计算这些较小值的总和。这个总和即为互信息的计算结果,即互信息的大小。

第三步:相似性度量

根据具体的需求和任务,设定一个阈值,选择互信息值高于该阈值的图像作为相似图像。

# 在实际应用中,可以根据互信息的阈值来判断两幅图像是否相似
if mutual_score > 0.7:print("两图相似")
else:print("两图不相似")

 

3.2 小实验

实验场景

计算两幅灰度图像的直方图,然后通过归一化的直方图计算它们的互信息。最后,根据设定的阈值判断两幅图像是否相似。

实验代码

"""
以图搜图:互信息(Mutual Information)查找相似图像的原理与实现
实验环境:Win10 | python 3.12.1 | OpenCV 4.9.0 | numpy 1.26.3 | Matplotlib 3.8.2
实验时间:2024-01-24
实验目的:计算两幅灰度图像的直方图,然后通过归一化的直方图计算它们的互信息。最后,根据设定的阈值判断两幅图像是否相似
实例名称:mutualInformation_v1.0.py
"""import os
import cv2
import time
import numpy as nptime_start = time.time()# 目标图像素材库文件夹路径
database_dir = '../../P0_Doc/img_data/'# 读取查询图像和数据库中的图像
img1_path = database_dir + 'car-101.jpg'
img2_path = database_dir + 'car-102.jpg'
img2_path = database_dir + 'car-103.jpg'# 读取两幅图像
img1 = cv2.imread(img1_path, cv2.IMREAD_GRAYSCALE)
img2 = cv2.imread(img2_path, cv2.IMREAD_GRAYSCALE)# 检查图像形状,保证两个图像必须具有相同的尺寸,即相同的高度和宽度
if img1.shape != img2.shape:# 调整图像大小,使它们具有相同的形状img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))# 使用 OpenCV 中的 calcHist 函数计算直方图
hist1 = cv2.calcHist([img1], [0], None, [256], [0, 256])
hist2 = cv2.calcHist([img2], [0], None, [256], [0, 256])# 将直方图归一化
# 即将直方图中的每个元素除以直方图的总和,以确保它们的和为1
# 这样做的目的是为了消除不同图像的像素数量差异,使得直方图的形状更具可比性
hist1 /= hist1.sum()
hist2 /= hist2.sum()# 计算两个归一化直方图的互信息
# 首先,使用 np.minimum 函数计算了 hist1 和 hist2 中每个对应位置的元素的较小值,然后使用 np.sum 计算了这些较小值的总和。这个总和即为互信息的计算结果
mutual_score = np.sum(np.minimum(hist1, hist2))
print(f"图像2:{os.path.basename(img2_path)} 与 图像1:{img1_path} 的相似性指数:{mutual_score}")# 在实际应用中,可以根据互信息的阈值来判断两幅图像是否相似
if mutual_score > 0.7:print("两图相似")
else:print("两图不相似")time_end = time.time()
print(f"耗时:{time_end - time_start}")

输出打印:

图像2:car-103.jpg 与 图像1../../P0_Doc/img_data/car-101.jpg 的相似性指数:0.6439836025238037
两图不相似
耗时:0.0687875747680664

示例中的互信息计算,利用了灰度直方图比较方法,通过比较两幅图像的灰度直方图,评估它们的相似性。
注意: 如果这里不进行图像配准,不保证等高等宽,互信息的相似度也会产生差异。

插播: 直方图是一种统计图像中像素值分布的方法,它可以描述图像中不同灰度级别的像素数量。关于直方图的原理与实验,可详见:OpenCV书签 #直方图算法的原理与相似图片搜索实验

 

为什么要用灰度直方图呢?有什么关联和区别?

互信息和灰度直方图算法是两个不同的概念,虽然在图像处理中它们有时候会交叉使用,但是还是需要注意:

互信息(Mutual Information):

  • 互信息是一种信息论中的概念,用于衡量两个随机变量之间的关联程度。
  • 在图像处理中,互信息通常用于度量两幅图像之间的相似性。它考虑的是两个变量的联合概率分布与各自边缘概率分布之间的关系。
  • 互信息越高,表示两个随机变量之间的关联越强。

灰度直方图算法(Image Histogram):

  • 灰度直方图是一种统计图像中像素值分布的方法,它描述了图像中不同灰度级别的像素数量。
  • 在灰度直方图算法中,图像的直方图表示了图像中每个灰度级别的像素数量。
  • 直方图比较是通过比较两幅图像的灰度直方图来评估它们的相似性。常见的比较方法包括交叉相关性、巴氏距离等。

虽然互信息的计算可以涉及到灰度直方图,但两者并不等同。互信息是一种更广泛的概念,而灰度直方图算法是一种具体的图像表示和相似性度量方法。

 

4. 测试

4.1 实验素材

MutualInformation-001

4.2 实验过程

纵向比较

通过 sklearn.metrics 提供的各类互信息比较算法,纵向比较两图的相似性。

实验代码
"""
以图搜图:互信息(Mutual Information)查找相似图像的原理与实现
实验环境:Win10 | python 3.12.1 | OpenCV 4.9.0 | numpy 1.26.3 | Matplotlib 3.8.2
实验时间:2024-01-24
实验目的:通过 sklearn.metrics 提供的各类互信息比较算法,纵向比较两图的相似性
实例名称:mutualInformation_v2.1.py
"""import time
import cv2
from sklearn import metrics as mr
# from sklearn.metrics.cluster import normalized_mutual_info_score
# from sklearn.metrics.cluster import adjusted_mutual_info_scoredef mutual_information_score(img1_reshape, img2_reshape):# mutual_info_score:标准互信息分数。度量两个随机变量之间的互信息,可用于衡量它们之间的关联性m_time_start = time.time()score_info = mr.mutual_info_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 mutual_info_score:标准互信息分数:{score_info},耗时:{m_time_end - m_time_start}")# normalized_mutual_info_score:归一化互信息分数。用于衡量两个聚类结果之间的相似性,考虑到了数据集的随机性。通常被用作聚类性能的评估指标m_time_start = time.time()score_normal = mr.normalized_mutual_info_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 normalized_mutual_info_score:归一化互信息分数:{score_normal},耗时:{m_time_end - m_time_start}")# adjusted_mutual_info_score:调整的归一化互信息分数。该分数考虑到了数据集的随机性,对标准互信息进行了调整,以提供更准确的聚类性能度量m_time_start = time.time()score_adjusted = mr.adjusted_mutual_info_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 adjusted_mutual_info_score:调整的归一化互信息分数:{score_adjusted},耗时:{m_time_end - m_time_start}")# v_measure_score: V-Measure(V值)分数。结合了聚类的均匀性和完整性,提供了一个综合的聚类性能度量m_time_start = time.time()score_measure = mr.v_measure_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 v_measure_score:V-Measure(V值)分数:{score_measure},耗时:{m_time_end - m_time_start}")# homogeneity_score: 均匀性分数。用于度量每个聚类的成员是否都属于同一类别,高均匀性表示每个聚类都很“纯净”m_time_start = time.time()score_homogeneity = mr.homogeneity_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 homogeneity_score:均匀性分数:{score_homogeneity},耗时:{m_time_end - m_time_start}")# completeness_score: 完整性分数。度量每个真实类别的成员是否都被分配到同一聚类中,高完整性表示每个类别都被很好地捕捉m_time_start = time.time()score_completeness = mr.completeness_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 completeness_score:完整性分数:{score_completeness},耗时:{m_time_end - m_time_start}")# adjusted_rand_score: 调整的兰德指数。度量两个聚类结果之间的相似性,考虑了数据集的随机性m_time_start = time.time()score_adjusted_rand = mr.adjusted_rand_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 adjusted_rand_score:调整的兰德指数:{score_adjusted_rand},耗时:{m_time_end - m_time_start}")# fowlkes_mallows: Fowlkes-Mallows指数。度量两个聚类结果之间的精度,考虑了聚类的精确度m_time_start = time.time()score_fowlkes_mallows = mr.fowlkes_mallows_score(img1_reshape, img2_reshape)m_time_end = time.time()print(f"互信息 fowlkes_mallows_score:Fowlkes-Mallows指数:{score_fowlkes_mallows},耗时:{m_time_end - m_time_start}")# silhouette_score: 轮廓系数。度量每个样本在其自己的聚类中的相似性与最近的相邻聚类之间的不相似性# 输入是两张图片,而不是聚类数据,计算轮廓系数就不太适用了,因为轮廓系数通常用于衡量聚类的质量# score_silhouette = mr.silhouette_score(img1.reshape(-1, 1), img2.reshape(-1, 1))if __name__ == "__main__":time_start = time.time()# 目标图像素材库文件夹路径database_dir = '../../P0_Doc/img_data/'# 读取查询图像和数据库中的图像img1_path = database_dir + 'car-101.jpg'img2_path = database_dir + 'car-102.jpg'img1_path = database_dir + 'apple-101.jpg'img2_path = database_dir + 'apple-102.jpg'print(f"互信息相似度比较,图像1:{img1_path},图像2:{img2_path}")# 读取图像img1 = cv2.imread(img1_path)img2 = cv2.imread(img2_path)# 检查图像形状,保证两个图像必须具有相同的尺寸,即相同的高度和宽度if img1.shape != img2.shape:# 调整图像大小,使它们具有相同的形状img2 = cv2.resize(img2, (img1.shape[1], img1.shape[0]))print("------------------------- 原图像 互信息相似度           -------------------------")# 原图应用于常见的互信息相关方法和算法及相似度mutual_information_score(img1.reshape(-1), img2.reshape(-1))# 将图像转换为灰度图像img1_gray = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)img2_gray = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)print("------------------------- 图像转换为灰度图像 互信息相似度 -------------------------")# 原图灰度图像应用于常见的互信息相关方法和算法及相似度mutual_information_score(img1_gray.reshape(-1), img2_gray.reshape(-1))time_end = time.time()print(f"耗时:{time_end - time_start}")

sklearn.metrics.cluster 提供了很多互信息相关的方法和算法,主要用于不同的评估场景,涉及到聚类的性能和相似性的测量:

互信息算法/方法说明
adjusted_mutual_info_score调整的归一化互信息分数。该分数考虑到了数据集的随机性,对标准互信息进行了调整,以提供更准确的聚类性能度量
normalized_mutual_info_score归一化互信息分数。用于衡量两个聚类结果之间的相似性,考虑到了数据集的随机性。通常被用作聚类性能的评估指标
mutual_info_score标准互信息分数。度量两个随机变量之间的互信息,可用于衡量它们之间的关联性
v_measure_scoreV-Measure(V值)分数。结合了聚类的均匀性和完整性,提供了一个综合的聚类性能度量
homogeneity_score均匀性分数。用于度量每个聚类的成员是否都属于同一类别,高均匀性表示每个聚类都很“纯净”
completeness_score完整性分数。度量每个真实类别的成员是否都被分配到同一聚类中,高完整性表示每个类别都被很好地捕捉
adjusted_rand_score调整的兰德指数。度量两个聚类结果之间的相似性,考虑了数据集的随机性
fowlkes_mallows_scoreFowlkes-Mallows指数。度量两个聚类结果之间的精度,考虑了聚类的精确度
silhouette_score轮廓系数。度量每个样本在其自己的聚类中的相似性与最近的相邻聚类之间的不相似性

img1_reshape.reshape(-1)img1_reshape.reshape(-1, 1)NumPy 中用于改变数组形状的方法。
reshape(-1) 用于展平数组,而 reshape(-1, 1) 用于将数组转换为包含单个列的二维数组。区别在于得到的形状不同。

  • img1_reshape.reshape(-1): 这将多维数组 img1_reshape 转换为一个展平的一维数组。NumPy 会根据数组的大小自动计算另一维度的大小,以确保总的元素数量不变。这通常用于将多维数组展平为一维数组,方便某些操作。
  • img1_reshape.reshape(-1, 1): 这将多维数组 img1_reshape 转换为一个包含单个列的二维数组。其中,-1 表示自动计算行数,而 1 表示只有一列。这通常用于确保某些函数接受的输入是二维数组,并且每个样本在单独的列中。

关于这些算法/方法,源码提供了使用 Demo,可以通过源码了解更多,比如:

    Examples--------Perfect labelings are both homogeneous and complete, hence havescore 1.0::>>> from sklearn.metrics.cluster import normalized_mutual_info_score>>> normalized_mutual_info_score([0, 0, 1, 1], [0, 0, 1, 1])... # doctest: +SKIP1.0>>> normalized_mutual_info_score([0, 0, 1, 1], [1, 1, 0, 0])... # doctest: +SKIP1.0If classes members are completely split across different clusters,the assignment is totally in-complete, hence the NMI is null::>>> normalized_mutual_info_score([0, 0, 0, 0], [0, 1, 2, 3])... # doctest: +SKIP0.0

实验代码输出打印:

互信息相似度比较,图像1../../P0_Doc/img_data/apple-101.jpg,图像2../../P0_Doc/img_data/apple-102.jpg
------------------------- 原图像 互信息相似度           -------------------------
互信息 mutual_info_score:标准互信息分数:0.3334500090190323,耗时:0.4178807735443115
互信息 normalized_mutual_info_score:归一化互信息分数:0.1442800195961649,耗时:0.704125165939331
互信息 adjusted_mutual_info_score:调整的归一化互信息分数:0.13897879139743463,耗时:27.81876230239868
互信息 v_measure_score:V-Measure(V值)分数:0.14428001959616493,耗时:0.6462442874908447
互信息 homogeneity_score:均匀性分数:0.1393427892877539,耗时:0.6453077793121338
互信息 completeness_score:完整性分数:0.14957997661474184,耗时:0.6043868064880371
互信息 adjusted_rand_score:调整的兰德指数:0.5983897700024668,耗时:0.39893531799316406
互信息 fowlkes_mallows_score:Fowlkes-Mallows指数:0.7874850623258953,耗时:0.3939492702484131
------------------------- 图像转换为灰度图像 互信息相似度 -------------------------
互信息 mutual_info_score:标准互信息分数:0.3114601065499291,耗时:0.12766075134277344
互信息 normalized_mutual_info_score:归一化互信息分数:0.14164731215313434,耗时:0.2203817367553711
互信息 adjusted_mutual_info_score:调整的归一化互信息分数:0.13105360189408213,耗时:6.436821222305298
互信息 v_measure_score:V-Measure(V值)分数:0.14164731215313434,耗时:0.20248985290527344
互信息 homogeneity_score:均匀性分数:0.1361761519096563,耗时:0.25429248809814453
互信息 completeness_score:完整性分数:0.14757650531529792,耗时:0.19750332832336426
互信息 adjusted_rand_score:调整的兰德指数:0.6065766924224203,耗时:0.1396336555480957
互信息 fowlkes_mallows_score:Fowlkes-Mallows指数:0.7932503296629234,耗时:0.13862109184265137
耗时:39.388914585113525

通过简单的测试,从纵向比较两图的相似性结果来看:

原图像

  • 互信息使用 adjusted_mutual_info_score 算法,相似度得分最低,耗时最长。
  • 互信息使用 fowlkes_mallows_score 算法,相似度得分最高,耗时最短。

图像灰度之后,去除了彩色像素处理,速度明显变快很多:

  • 互信息使用 adjusted_mutual_info_score 算法,相似度得分最低,耗时最长。
  • 互信息使用 fowlkes_mallows_score 算法,相似度得分最高。
  • 互信息使用 mutual_info_score 算法,耗时最短。

横向比较

通过使用某一互信息计算方法,配合相似阈值,在测试图片素材库中搜索查找与目标图像相似的图片。

实验代码
"""
以图搜图:互信息(Mutual Information)查找相似图像的原理与实现
实验环境:Win10 | python 3.12.1 | OpenCV 4.9.0 | numpy 1.26.3 | Matplotlib 3.8.2
实验时间:2024-01-24
实验目的:通过使用某一互信息计算方法,配合相似阈值,在测试图片素材库中搜索查找与目标图像相似的图片
实例名称:mutualInformation_v2.2.py
"""import os
import time
import cv2
import matplotlib.pyplot as plt
from sklearn import metrics as mrdef search_mutual_info(img_org_path, database_paths):# 将原图像转换为灰度图像img_original_gray = cv2.cvtColor(cv2.imread(img_org_path), cv2.COLOR_BGR2GRAY)# 遍历数据库图像并比较相似度similaritys = []for img_path in database_paths:# 获取相似图像文件路径img_target_path = os.path.join(script_dir, database_dir_path, img_path)# 将图像转换为灰度图像img_target_gray = cv2.cvtColor(cv2.imread(img_target_path), cv2.COLOR_BGR2GRAY)# 检查图像形状,保证两个图像必须具有相同的尺寸,即相同的高度和宽度if img_original_gray.shape != img_target_gray.shape:# 调整图像大小,使它们具有相同的形状img_target_gray = cv2.resize(img_target_gray, (img_original_gray.shape[1], img_original_gray.shape[0]))# 灰度图像应用于常见的互信息相关方法和算法及相似度score = mr.fowlkes_mallows_score(img_original_gray.reshape(-1), img_target_gray.reshape(-1))# print(f"互信息 fowlkes_mallows_score:{score}")# 将结果保存到列表中(仅保留相似值大于等于 0.7 的图像)if (score >= 0.7):similaritys.append((os.path.relpath(img_target_path), score))# print(f"图像名称:{img_target_path},与目标图像 {os.path.basename(img_resouce)} 的近似值:{ssim[0]}")return similaritysdef show_similar_images(similar_images, images_per_column=4):# 计算总共的图片数量num_images = len(similar_images)# 计算所需的行数num_rows = (num_images + images_per_column - 1) // images_per_column# 创建一个子图,每行显示 images_per_column 张图片fig, axes = plt.subplots(num_rows, images_per_column, figsize=(12, 15), squeeze=False)# 遍历每一行for row in range(num_rows):# 遍历每一列for col in range(images_per_column):# 计算当前图片在列表中的索引index = row * images_per_column + col# 检查索引是否越界if index < num_images:# 获取当前相似图片的路径和相似度image_path = similar_images[index][0]similarity = similar_images[index][1]# 读取图片并转换颜色通道image = cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB)# 在子图中显示图片axes[row, col].imshow(image)# 设置子图标题,包括图片路径和相似度axes[row, col].set_title(f"Similar Image: {os.path.basename(image_path)} \n Similar Score: {similarity}")# 关闭坐标轴axes[row, col].axis('off')# 显示整个图plt.show()if __name__ == "__main__":time_start = time.time()# 获取当前执行脚本所在目录script_dir = os.path.dirname(__file__)# 目标图像素材库文件夹路径database_dir_path = '../../P0_Doc/img_data/'# 指定测试图像文件扩展名img_suffix = ['.jpg', '.jpeg', '.png', '.bmp', '.gif']# 获取测试图像库中所有文件all_files = os.listdir(os.path.join(script_dir, database_dir_path))# 筛选测试图像库中指定后缀的图像文件img_files = [img_file for img_file in all_files if any(img_file.endswith(suffix) for suffix in img_suffix)]# 获取测试图像库中所有图像的路径img_files_path = [os.path.join(database_dir_path, filename) for filename in img_files]# 获取目标测试图像的全路径img_org_path = os.path.join(script_dir, database_dir_path, 'apple-101.jpg')img_org_path = os.path.join(script_dir, database_dir_path, 'iphone15-001.jpg')img_org_path = os.path.join(script_dir, database_dir_path, 'car-101.jpg')# 原图应用于常见的互信息相关方法和算法及相似度img_search_results = search_mutual_info(img_org_path, img_files_path)# 按相似度降序排序img_search_results.sort(key=lambda item: item[1], reverse=True)for similarity in img_search_results:print(f"图像:{similarity[0]},与目标图像 {os.path.basename(img_org_path)} 的相似值:{similarity[1]}")time_end = time.time()print(f"测试素材库图像数量:{len(img_files)},耗时:{time_end - time_start}")# 显示目标相似图像show_similar_images(img_search_results)
第一组测试

测试结果输出打印:

图像:..\..\P0_Doc\img_data\apple-101.jpg,与目标图像 apple-101.jpg 的相似值:1.0
图像:..\..\P0_Doc\img_data\apple-103.jpg,与目标图像 apple-101.jpg 的相似值:0.8185132476782856
图像:..\..\P0_Doc\img_data\apple-105.jpg,与目标图像 apple-101.jpg 的相似值:0.8069378648696433
图像:..\..\P0_Doc\img_data\apple-102.jpg,与目标图像 apple-101.jpg 的相似值:0.7932928654393832
图像:..\..\P0_Doc\img_data\iphone15-001.jpg,与目标图像 apple-101.jpg 的相似值:0.771736183796336
图像:..\..\P0_Doc\img_data\iphone15-002.jpg,与目标图像 apple-101.jpg 的相似值:0.7715952189959523
图像:..\..\P0_Doc\img_data\iphone15-003.jpg,与目标图像 apple-101.jpg 的相似值:0.7707667748546456
图像:..\..\P0_Doc\img_data\apple-109.jpg,与目标图像 apple-101.jpg 的相似值:0.7528870440060801
图像:..\..\P0_Doc\img_data\pear-201.jpg,与目标图像 apple-101.jpg 的相似值:0.7208068021727383
图像:..\..\P0_Doc\img_data\apple-104.jpg,与目标图像 apple-101.jpg 的相似值:0.7066478416742119
测试素材库图像数量:48,耗时:7.807173013687134

互信息相似图片查找效果可视化:
MutualInformation-002

第二组测试

测试结果输出打印:

图像:..\..\P0_Doc\img_data\iphone15-001.jpg,与目标图像 iphone15-001.jpg 的相似值:1.0
图像:..\..\P0_Doc\img_data\iphone15-002.jpg,与目标图像 iphone15-001.jpg 的相似值:0.9985563921236876
图像:..\..\P0_Doc\img_data\iphone15-003.jpg,与目标图像 iphone15-001.jpg 的相似值:0.996718480433257
图像:..\..\P0_Doc\img_data\apple-102.jpg,与目标图像 iphone15-001.jpg 的相似值:0.8165921658980023
图像:..\..\P0_Doc\img_data\apple-104.jpg,与目标图像 iphone15-001.jpg 的相似值:0.7733543220682563
图像:..\..\P0_Doc\img_data\apple-101.jpg,与目标图像 iphone15-001.jpg 的相似值:0.7717483756822613
图像:..\..\P0_Doc\img_data\apple-103.jpg,与目标图像 iphone15-001.jpg 的相似值:0.7579136253684923
图像:..\..\P0_Doc\img_data\apple-105.jpg,与目标图像 iphone15-001.jpg 的相似值:0.7540519846067019
测试素材库图像数量:48,耗时:30.248269081115723

互信息相似图片查找效果可视化:
MutualInformation-003

 

5. 总结

在图像处理中,互信息可以用来衡量两幅图像的相似性,尤其在配准(registration)和图像匹配(image matching)的任务中经常被使用。通过最大化互信息,可以找到两个图像之间的最佳匹配,以便更好地对齐它们。

优点

  1. 对比度不敏感: 互信息对比度不敏感,适用于对比度较大的图像。
  2. 非线性关系: 互信息适用于具有非线性关系的图像数据,因此对于复杂的图像相似性度量具有一定优势。
  3. 不依赖特定颜色空间: 互信息在计算过程中不依赖于特定的颜色空间,因此对于不同颜色表示的图像也能够有效计算相似性。

缺点

  1. 图像配准: 如果两张图片尺寸相同,还是能在一定程度上表征两张图片的相似性的。但是,大部分情况下图片的尺寸不相同,如果把两张图片尺寸调成相同的话,又会让原来很多的信息丢失,所以很难把握。
  2. 计算复杂度: 互信息的计算涉及到直方图的操作,因此在图像尺寸较大、直方图维度较高时计算复杂度较高。
  3. 对噪声敏感: 互信息对噪声敏感,噪声可能对互信息的计算产生一定影响。
  4. 不考虑空间结构: 互信息不考虑像素在图像中的空间结构,可能对图像中物体的空间排列不敏感。

 

6. 问题

异常现象1

    from skimage.feature import mutual_info_score
ImportError: cannot import name 'mutual_info_score' from 'skimage.feature' (D:\Tp_Mylocal\20_Install\python-3.9.13\lib\site-packages\skimage\feature\__init__.py)

可以尝试安装或更新 scikit-image 依赖项:

pip install --upgrade scikit-image
Installing collected packages: pillow, packaging, numpy, networkx, lazy_loader, tifffile, scipy, imageio, scikit-imageWARNING: Failed to write executable - trying to use .deleteme logic
ERROR: Could not install packages due to an OSError: [WinError 2] 系统找不到指定的文件。: 'C:\\Python312\\Scripts\\f2py.exe' -> 'C:\\Python312\\Scripts\\f2py.exe.deleteme'

f2py.exeFortran 到 Python 接口生成器的可执行文件。它用于将 Fortran 代码集成到 Python 中,使得可以在 Python 中调用 Fortran 编写的函数或子程序。

在正常情况下,f2py.exe 应该包含在 NumPy 库中。由于我本地环境没有,可能是之前安装出现的问题。这里重新安装 NumPy,以获取缺失的文件:

pip install --upgrade --force-reinstall numpy

还是不行的话,尝试一下在应用程序中先卸载 Python,再重装最新版的 Python。

以我的案例看,我本地的 Python 版本是 python 3.9.13,卸载后重装了最新版的 Python 3.12.1。
如果重装 python 时,选择了新的路径,这里同样需要确认或调整一下系统环境变量中关于 python 的路径指向。
然后重新安装本地运行 python 脚本缺失的依赖项,包括 scikit-learn。
然后就可以了。也没有类似需要 f2py.exe 的错误提示。
需要注意的是,目前互信息提供的相似算法都在 from sklearn.metrics.cluster 下。

安装 scikit-learn 依赖项:

pip install scikit-learn

 

异常现象2

Traceback (most recent call last):File "D:\Ct_ iSpace\Wei\Python\iPython\T30_Algorithm\P2_Algo\03_MutualInformation\mutualInformation_v2.1.py", line 119, in <module>mutual_information_score(img1.reshape(-1), img2.reshape(-1))File "D:\Ct_ iSpace\Wei\Python\iPython\T30_Algorithm\P2_Algo\03_MutualInformation\mutualInformation_v2.1.py", line 89, in mutual_information_scorescore_silhouette = mr.silhouette_score(img1_reshape, img2_reshape)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Ct_ iSpace\Wei\Python\iPython\T00_Env\Lib\site-packages\sklearn\utils\_param_validation.py", line 213, in wrapperreturn func(*args, **kwargs)^^^^^^^^^^^^^^^^^^^^^File "D:\Ct_ iSpace\Wei\Python\iPython\T00_Env\Lib\site-packages\sklearn\metrics\cluster\_unsupervised.py", line 140, in silhouette_scorereturn np.mean(silhouette_samples(X, labels, metric=metric, **kwds))^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Ct_ iSpace\Wei\Python\iPython\T00_Env\Lib\site-packages\sklearn\utils\_param_validation.py", line 186, in wrapperreturn func(*args, **kwargs)^^^^^^^^^^^^^^^^^^^^^File "D:\Ct_ iSpace\Wei\Python\iPython\T00_Env\Lib\site-packages\sklearn\metrics\cluster\_unsupervised.py", line 267, in silhouette_samplesX, labels = check_X_y(X, labels, accept_sparse=["csr"])^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "D:\Ct_ iSpace\Wei\Python\iPython\T00_Env\Lib\site-packages\sklearn\utils\validation.py", line 1192, in check_X_yX = check_array(^^^^^^^^^^^^File "D:\Ct_ iSpace\Wei\Python\iPython\T00_Env\Lib\site-packages\sklearn\utils\validation.py", line 989, in check_arrayraise ValueError(msg)
ValueError: Expected 2D array, got 1D array instead:
array=[253 253 253 ... 253 253 253].
Reshape your data either using array.reshape(-1, 1) if your data has a single feature or array.reshape(1, -1) if it contains a single sample.

异常原因: silhouette_score 函数期望接收的数据是一个2D数组,而 Demo 提供的是一个1维数组。因为输入是两张图片,而不是聚类数据,计算轮廓系数就不太适用了,因为轮廓系数通常用于衡量聚类的质量。

解决方案: 使用 array.reshape(-1, 1) 来将数据转换成2D数组。

 

7. 参考资料

互信息 - 百度百科
什么是「互信息」?
互信息是什么?

 

8. 系列书签

均值哈希算法: OpenCV书签 #均值哈希算法的原理与相似图片搜索实验
感知哈希算法: OpenCV书签 #感知哈希算法的原理与相似图片搜索实验
差值哈希算法: OpenCV书签 #差值哈希算法的原理与相似图片搜索实验
直方图算法: OpenCV书签 #直方图算法的原理与相似图片搜索实验
余弦相似度: OpenCV书签 #余弦相似度的原理与相似图片/相似文件搜索实验
SSIM结构相似性: OpenCV书签 #结构相似性SSIM算法的原理与图片相似性实验

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

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

相关文章

HashMap源码阅读;HashMap的put()方法;

当我们使用一个HashMap做插入操作时。put方法内部都做了什么呢&#xff1f; public static void main(String[] args) {HashMap<String, String> map new HashMap<>();map.put("key1", "value1"); }put 方法 源码 public V put(K key, V v…

Apache Jmeter测试websocket连通性

1、在windows电脑下载apache jmeter 下载地址详情Apache-Jemeter-download 2、解压打开文件夹&#xff0c;下载 jmeter-plugins-manager下载地址&#xff0c;下载后存放到lib的ext路径下&#xff0c; 同时也可以更改bin路径下的jmeter.properties对应第三十七行修改为如下&…

Java 设计者模式以及与Spring关系(五) 策略和观察者模式

目录 简介: 23设计者模式以及重点模式 策略模式&#xff08;Strategy Pattern&#xff09; 示例 spring中应用 观察者模式&#xff08;Observer&#xff09; 示例 spring中应用 简介: 本文是个系列一次会出两个设计者模式作用&#xff0c;如果有关联就三个&#xff0c;…

03_web端交互协议之HTTP

本课目标 (Objective) 理解HTTP协议简介掌握常见HTTP请求方式掌握HTTP协议响应状态码理解HTTP协议的交互原理 1. 前后端是如何交互的 通信协议&#xff08;Communication Protocol&#xff09;是指通信双方对数据传送控制的一种约定。 前端与服务端的数据传输是基于HTTP协议…

中仕教育:事业编招考全流程介绍

一、报名阶段 1. 了解查看招聘信息&#xff1a;查看各类事业编岗位的招聘信息&#xff0c;包括岗位职责、招聘条件、报名时间等。 2. 填写报名表&#xff1a;按照要求填写报名表&#xff0c;包括个人信息、教育背景、工作经历等内容。 3. 提交报名材料&#xff1a;将报名表及…

Hive3.1.3基础学习

文章目录 一、Hive入门与安装1、Hive入门1.1 简介1.2 Hive架构原理 2、Hive安装2.1 安装地址2.2 Hive最小化安装(测试用)2.3 MySQL安装2.4 配置Hive元数据存储到MySQL2.5 Hive服务部署2.6 Hive服务启动脚本(了解) 3、Hive使用技巧3.1 Hive常用交互命令3.2 Hive参数配置方式3.3 …

利用sqlmap探测get类型注入

环境准备:构建完善的安全渗透测试环境:推荐工具、资源和下载链接_渗透测试靶机下载-CSDN博客 基础:GET基于报错的sql注入利用-脱库-CSDN博客 sqlmap 工具是kali自带的 例子我都用sql靶场的第一关做演示 1、探测数据库名 sqlmap -u "http://192.168.0.103/sqlilab…

【CANoe使用大全】——Graphics窗口

文章目录 1.Graphics作用2.Graphics窗口打开方式2.1.Analysis—>Graphics2.2.Measurement Setup ------> Graphics 3.变量添加4.Graphics窗口菜单栏介绍4.1. 单个测量光标4.2. 差分测量光标4.3.Y轴的显示方式4.3.1.Show Y-Axis of Selected Signal4.3.2.Show All Y-Axis4…

抽象工厂模式-C#实现

该实例基于WPF实现&#xff0c;直接上代码&#xff0c;下面为三层架构的代码。 一 Model using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks;namespace 设计模式练习.Model.抽象工厂模式 {public abstrac…

[GXYCTF2019]BabyUpload1

尝试各种文件&#xff0c;黑名单过滤后缀ph&#xff0c;content-type限制image/jpeg 内容过滤<?&#xff0c;木马改用<script languagephp>eval($_POST[cmdjs]);</script> 上传.htaccess将上传的文件当作php解析 蚁剑连接得到flag

OPENMV驱动云台实现颜色追踪

前言 本篇文章旨在记录我电赛期间学习OPENMV对颜色识别&#xff0c;以及通过串口通信的方式将坐标数据传给单片机&#xff0c;从而驱动舵机云台进行颜色追踪。 一、OPENMV色块识别追踪代码 # Single Color RGB565 Blob Tracking Example # # This example shows off single co…

C++学习| QT快速入门

QT简单入门 QT Creater创建QT项目选择项目类型——不同项目类型的区别输入项目名字和路径选择合适的构建系统——不同构建系统的却别选择合适的类——QT基本类之间的关系Translation File选择构建套件——MinGW和MSVC的区别 简单案例&#xff1a;加法器设计界面——构建加法器界…

java web 研究生信息管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java Web研究生信息管理系统是一套完善的java web信息管理系统 &#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境 为TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为My…

hdu1195 Open the lock 双向广度优先搜索

D-BFS 双向广度优先搜索 从起点和终点同时开始搜索&#xff0c;直到两个搜索的点相交&#xff0c;得到最短路径 Code: // D-BFS //by:MuQY #include <iostream> #include <algorithm> #include <string.h> #include <queue> #include <string> …

【Vue2 + ElementUI】分页el-pagination 封装成公用组件

效果图 实现 &#xff08;1&#xff09;公共组件 <template><nav class"pagination-nav"><el-pagination class"page-area" size-change"handleSizeChange" current-change"handleCurrentChange":current-page"c…

TarGAN:多模态医学图像转换GAN

TarGAN 核心思想网络结构 核心思想 论文&#xff1a;https://arxiv.org/abs/2105.08993 代码&#xff1a;https://github.com/2165998/TarGAN 解决的问题&#xff1a;传统多模态医学图像转换通常&#xff0c;在生成高质量图像方面存在问题&#xff0c;特别是在关键目标区域或…

NC65中间件能启动,前端客户端启动失败,加载异常,卡住(org.owasp.esapi)

控制台输出错误 ESAPI.properties could not be loaded by any means. Fail.SecurityConfiguration class(org.owasp.esapi.reference.DefaultSecurityConfiguration) CTOR threw exception.效果图&#xff1a; 解决方案 添加如下参数&#xff1a; -Dorg.owasp.esapi.resou…

信创UOS

信创UOS 国产操作系统 文章目录 信创UOS前言一、信创UOS是什么二、信创UOS的特点与局限性1. 信创UOS的特点2. 信创UOS的局限性三、信创UOS常见故障总结前言 信创UOS(Union Operating System)是由中国软件与技术服务股份有限公司(CS&S)开发的一款操作系统。它是中国政府…

用k8s私有化部署docsify做开放API平台

文章目录 1、API开放平台2、实现思路3、用docsify实现4、一些坑坑1&#xff1a;nginx转发实现跳转坑2&#xff1a;点击跳转不能精准跳坑3&#xff1a;md文档页内跳转与跨文档跳转坑4&#xff1a;插件做目录的折叠收起坑5&#xff1a;统一目录 做完了一个API开放平台的需求&…

Higress 开源一周年:新版本,新标准,新工具,新征程

作者&#xff1a;Higress 团队 历程回顾 Higress 开源一年时间&#xff0c;一共发布了 18 个 release 版本&#xff0c;收获了 40 多位社区贡献者和 1800 star&#xff0c;上图是这一年过来达成的一些关键的里程碑。 前面半年通过集成开源生态&#xff0c;打磨开源版本稳定性…