制作网站软件下载,wordpress演示,一级工程造价师,网站建设灰色关键词1. 介绍 
直方图算法#xff08;Image Histogram Algorithm#xff09; 通过统计图像中各个颜色值的分布情况来提供关于图像颜色特征的信息#xff0c;它可以用来衡量两张图片在颜色分布上的相似度#xff0c;进而可以用来进行图像相似度的比较#xff0c;因此#xff0c…1. 介绍 
直方图算法Image Histogram Algorithm 通过统计图像中各个颜色值的分布情况来提供关于图像颜色特征的信息它可以用来衡量两张图片在颜色分布上的相似度进而可以用来进行图像相似度的比较因此直方图算法是一种常用的图片相似度算法通常是一个一维的数组取决于使用通道的数量其中每个元素表示特定颜色或强度值的像素数量。 
关于直方图算法的一些概念 
直方图的定义 
直方图是一个二维数组通常是一维的取决于使用通道的数量其中每个元素表示特定颜色或强度值的像素数量。对于彩色图像通常有多个通道比如蓝、绿、红BGR因此可能有多个直方图。 
直方图的统计 
直方图的统计是通过扫描图像的每个像素来收集颜色信息的过程。对于灰度图像属于单通道每个像素只有一个强度值因此只有一个通道的直方图。对于彩色图像每个像素有多个通道的值所以需要分别统计每个通道的直方图。关于单通道更详细的详细实验可见下文讨论1#关于单通道 [0] 
直方图的用途 
直方图可以用于多种图像处理任务包括图像增强、颜色校正、图像分割、物体检测和图像相似性比较。通过分析直方图可以获得有关图像的颜色分布、对比度、亮度等信息。 
直方图均衡化 
直方图均衡化是一种用于增强图像对比度的技术它通过重新分配像素的强度值来拉伸或压缩直方图以使其分布更均匀。这可以使图像中的细节更加清晰。 
直方图相似度 
直方图相似度用于比较两幅图像的相似程度。通过计算两个图像的直方图之间的差异可以量化它们的相似性。常见的直方图相似度度量包括交叉相关性cv2.HISTCMP_INTERSECT、卡方距离cv2.HISTCMP_CHISQR、相关性cv2.HISTCMP_CORREL、巴氏距离cv2.HISTCMP_BHATTACHARYYA等。对于直方图比较方法的详细实验可见下文讨论2#直方图相似度函数 
颜色直方图 
对于彩色图像颜色直方图通常分别计算每个通道的直方图。这可以提供关于不同颜色通道的颜色分布信息有助于颜色特征的分析。对于彩色图像直方图的详细实验可见下文讨论3#彩色图像直方图 2. 原理 
直方图算法通过统计图像中不同颜色的像素数量并以直方图的形式呈现进而进行图像相似度的比较。 
关于 bin 
在一个灰度图像中像素值的范围通常从黑色0到白色255之间变换。如果将图像的像素值范围分成 256 个 bin 格子那么每个 bin 格子则代表一个灰度级别其灰度值从 0 到 255。直方图中每个 bin 格子记录了对应灰度级别的像素数量通过统计每个 bin 格子中的像素数量就可以了解图像中不同灰度级别的分布情况。 
即可看作有你 256 张灰色系色度卡每一个灰度卡上都统计了灰度图像中所有该色度的像素数量这样就可以直观看出灰度图像的像素在不同色度卡上的分布然后和其它图像加以对比分析。 3. 魔法 
直方图计算图片相似度的步骤 
图像预处理 将目标图像转换为灰度图像或彩色图像并根据需要进行尺寸调整。计算直方图 对于灰度图像直方图表示不同灰度级别的像素数量。对于彩色图像可以分别计算各个通道如红、绿、蓝的直方图对图像中的每个像素进行像素值的统计以确定每个像素值的频率或数量。这通常包括遍历图像的每个像素并将其像素值归类到相应的像素值区间通常是0到255。最终得到一个表示像素值频率的直方图。直方图比较 对于两张图片的直方图可以使用不同的距离或相似度度量方法来进行比较。常见的度量方法包括相关性、卡方距离、巴氏距离等。相似度评估 根据直方图比较的结果计算出两张图片之间的相似度得分。 4. 实验 
4.1 魔法 
第一步图像预处理 
将目标图像转换为灰度图像或彩色图像并根据需要进行尺寸调整。 1读取原图 首先读取我们要分析的图像。 2图像灰度化 如果需要计算灰度直方图将彩色图像转换为灰度图像。这里我们使用 [0]只考虑图像灰度级别亮度信息结果是一维数组。 
第二步计算直方图 
对于灰度图像直方图表示不同灰度级别的像素数量。 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0 | numpy 1.21.1 | matplotlib 3.7.1
实验时间2023-10-27
实例名称imgHistogram_v1.0.py
import cv2
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties# 目标图像素材库文件夹路径
database_dir  ../../P0_Doc/
# 文件路径
img_path  database_dir  img_data/car-101.jpg
font_path  database_dir  fonts/chinese_cht.ttf# 读取图像
img  cv2.imread(img_path)
# 计算直方图
img_hist  cv2.calcHist([img], [0], None, [256], [0, 256])
print(img_hist)# 设置中文字体
font  FontProperties(fnamefont_path, size14)
# 绘制直方图
plt.plot(img_hist)
plt.title(Histogram直方图, fontpropertiesfont)
plt.xlabel(Pixel Value像素值, fontpropertiesfont)
plt.ylabel(Frequency频率, fontpropertiesfont)
# 像素分布可视化
plt.show()输出打印255个像素亮度 
[[   25.][   13.][   13.][   25.][   39.]......[  798.][  779.][ 2034.]]像素分布可视化效果直方图  对于彩色图像可以分别计算各个通道如红、绿、蓝的直方图。对图像中的每个像素进行像素值的统计以确定每个像素值的频率或数量。这通常包括遍历图像的每个像素并将其像素值归类到相应的像素值区间通常是0到255。最终得到一个表示像素值频率的直方图。 
img_hist  cv2.calcHist([img], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])注彩色直方图我们下后面详说。 
cv2.calcHist 函数用于计算图像的直方图。以下是它的主要参数和说明 
img要计算直方图的图像。它以方括号的形式传递允许计算多个图像的直方图。例如[img] 表示计算单个图像的直方图[img1, img2] 表示计算两个图像的直方图。channels指定要考虑的通道。这是一个通道索引列表用于选择要计算直方图的通道。在 OpenCV 中通常情况下通道 0 对应于蓝色B通道 1 对应于绿色G通道2 对应于红色R。如果要考虑所有通道可以使用 [0, 1, 2]而对于单通道只会考虑图像的灰度信息而不考虑颜色信息。使用 [0] 即可表示灰色通道也可以使用 [1] 或 [2] 表示灰色单通道。B、G、R 单通道的对比效果见下文 讨论1#关于单通道 [0]mask可选参数用于指定一个掩码图像以便只计算掩码中非零元素对应的像素值。如果不需要掩码可以将其设置为 None。 histSize指定直方图的 bin 数量即要计算的直方图的维度。它通常以方括号形式传递例如 [256] 表示每个通道有 256 个 bin256个色卡。ranges指定像素值的范围。通常以方括号形式传递例如 [0, 256] 表示单通道像素值的范围从 0 到 255。对于彩色图像通常设置为 [0, 256, 0, 256, 0, 256]表示三个通道的范围。 讨论1关于单通道 [0]  
因为通道 0 对应的是蓝色B所以 [0] 即使用了蓝色B单通道的灰度图像因为灰度图像中只有一个通道单通道。所以[1]、[2] 都可以表示单通道的灰度图像。同理[0]、[1]、[2] 虽然都可以表示单通道的灰度图像但由于使用的通道分别是 0蓝色Blue、1绿色Green、2红色Red所以灰度图像的亮度略有区别会影响灰度像素亮度分布。 
效果如下分别是BGR、RGB、B、G、R  示图代码 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0 | numpy 1.21.1 | matplotlib 3.7.1
实验时间2023-10-27
实例名称imgHistogram_v1.2_rgb_split.py
import cv2
import matplotlib.pyplot as plt# 目标图像素材库文件夹路径
database_dir  ../../P0_Doc/
# 文件路径
img_path  database_dir  img_data/car-101.jpg# 读取图像默认使用BGR加载图像
img  cv2.imread(img_path)
# 分离通道将彩色图像分离成各个通道R、G、B然后分别绘制它们的直方图
img_b, img_g, img_r  cv2.split(img)# 绘制子图
plt.figure(figsize(15, 5))
# 151表示子图位于一个 1x5 的网格中的第一个位置。如比第2张图的位置152即一行五列第2张图
# 显示各通道的图像
plt.subplot(151)
plt.imshow(img)
plt.title(BGR (Default))plt.subplot(152)
plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
plt.title(BGR TO RGB)plt.subplot(153)
plt.imshow(cv2.cvtColor(img_b, cv2.COLOR_BGR2RGB))
plt.title(Blue Channel)plt.subplot(154)
plt.imshow(cv2.cvtColor(img_g, cv2.COLOR_BGR2RGB))
plt.title(Green Channel)plt.subplot(155)
plt.imshow(cv2.cvtColor(img_r, cv2.COLOR_BGR2RGB))
plt.title(Red Channel)plt.show()代码对目标图像进行 R、G、B 通道分离读取像素然后分别绘制它们的直方图。 
下图中读取目标图像的方式分别是BGR、RGB、B、G、R绘画出来的直方图灰度像素分布效果如下  可以看到BGR 与 Blue第1张与第3张、RGB 与 Red第2张与第5张的灰度像素分布趋势一致。 
示图代码 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0 | numpy 1.21.1 | matplotlib 3.7.1
实验时间2023-10-27
实例名称imgHistogram_v1.3_rgb_split.py
import cv2
import matplotlib.pyplot as plt# 目标图像素材库文件夹路径
database_dir  ../../P0_Doc/
# 文件路径
img_path  database_dir  img_data/car-101.jpg# 读取图像默认使用BGR加载图像
img  cv2.imread(img_path)
img_rgb  cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 分离通道将彩色图像分离成各个通道R、G、B然后分别绘制它们的直方图
img_b, img_g, img_r  cv2.split(img)# 计算各通道的直方图
hist_bgr  cv2.calcHist([img], [0], None, [256], [0, 256])
hist_rgb  cv2.calcHist([img_rgb], [0], None, [256], [0, 256])
hist_b  cv2.calcHist([img_b], [0], None, [256], [0, 256])
hist_g  cv2.calcHist([img_g], [0], None, [256], [0, 256])
hist_r  cv2.calcHist([img_r], [0], None, [256], [0, 256])# 绘制线图子图展示各通道的直方图灰度趋势
plt.subplot(151)
plt.plot(hist_bgr, colororange)
plt.title(BGR Histogram)plt.subplot(152)
plt.plot(hist_rgb, colorpurple)
plt.title(RGB Histogram)plt.subplot(153)
plt.plot(hist_b, colorb)
plt.title(Blue Histogram)plt.subplot(154)
plt.plot(hist_g, colorg)
plt.title(Green Histogram)plt.subplot(155)
plt.plot(hist_r, colorr)
plt.title(Red Histogram)plt.show()如果不好分辨我们再加上 [0]、[1]、[2] 单通道合成一张直方图  可以清楚看到合成后的直方图只剩下 B、G、R 三通道的灰度像素分布趋势。 
示图代码 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0 | numpy 1.21.1 | matplotlib 3.7.1
实验时间2023-10-27
实例名称imgHistogram_v1.4_rgb_one.py
import cv2
import matplotlib.pyplot as plt
from matplotlib.font_manager import FontProperties# 目标图像素材库文件夹路径
database_dir  ../../P0_Doc/
# 文件路径
img_path  database_dir  img_data/car-101.jpg
# 字体路径
font_path  database_dir  fonts/chinese_cht.ttf# 读取图像
img  cv2.imread(img_path)
img_rgb  cv2.cvtColor(img, cv2.COLOR_BGR2RGB)# 分离通道将彩色图像分离成各个通道R、G、B然后分别绘制它们的直方图
img_b, img_g, img_r  cv2.split(img)# 计算各通道的直方图依次为 BGR、RGB、0蓝色通道1绿色通道2红色通道
hist_bgr  cv2.calcHist([img], [0], None, [256], [0, 256])
hist_rgb  cv2.calcHist([img_rgb], [0], None, [256], [0, 256])hist_b  cv2.calcHist([img_b], [0], None, [256], [0, 256])
hist_g  cv2.calcHist([img_g], [0], None, [256], [0, 256])
hist_r  cv2.calcHist([img_r], [0], None, [256], [0, 256])hist_0  cv2.calcHist([img], [0], None, [256], [0, 256])
hist_1  cv2.calcHist([img], [1], None, [256], [0, 256])
hist_2  cv2.calcHist([img], [2], None, [256], [0, 256])# 绘制多线线图展示各通道的直方图灰度趋势
plt.plot(hist_bgr, colororange, labelBGR)
plt.plot(hist_rgb, colorpurple, labelRGB)plt.plot(hist_b, colorblue, labelChannel Blue)
plt.plot(hist_0, colorblue, labelChannel 0)plt.plot(hist_g, colorgreen, labelChannel Green)
plt.plot(hist_1, colorgreen, labelChannel 1)plt.plot(hist_r, colorred, labelChannel Red)
plt.plot(hist_2, colorred, labelChannel 2)# 设置中文字体
font  FontProperties(fnamefont_path, size14)
plt.title(Histogram直方图, fontpropertiesfont)
plt.xlabel(Pixel Value像素值, fontpropertiesfont)
plt.ylabel(Frequency频率, fontpropertiesfont)# 添加图例
plt.legend()
# 显示图像
plt.show()计算各通道的直方图依次为 BGRRGB0蓝色通道1绿色通道2红色通道 
[0] 使用 cv2.imread(img_path) 的 img、cv2.split(img) 中的 img_b、[0] 获得到的灰度像素分布趋势等同[1] 使用 cv2.split(img) 中的 img_g、[1] 获得到的灰度像素分布趋势等同[2] 使用 cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 的 img_rgb、cv2.split(img) 中的 img_r、[2] 获得到的灰度像素分布趋势等同 
所以[0]、[1]、[2] 都可以表示单通道的灰度图像但由于使用的通道分别是 蓝色Blue、绿色Green、红色Red所以灰度图像的亮度略有区别会影响灰度像素亮度分布体现在直方图上则表现为灰度像素的分布趋势略有差异。 
第三步直方图比较 
对于两张图像的直方图比较可以使用不同的距离或相似度度量方法来进行比较。常见的度量方法包括相关性、卡方距离、巴氏距离等。 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0
实验时间2023-10-27
实例名称imgHistogram_v2.1_graySimilarity.py
import cv2def get_calcHist(img1_path, img2_path):# 读取图像img1  cv2.imread(img1_path)img2  cv2.imread(img2_path)# 计算图像灰度单通道直方图img1_hist  cv2.calcHist([img1], [0], None, [256], [0, 256])img2_hist  cv2.calcHist([img2], [0], None, [256], [0, 256])# 计算直方图相似度# cv2.HISTCMP_CORREL: 相关性比较值越接近 1 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_CORREL)print(图像2与图像1的相似度HISTCMP_CORREL/相关性, similarity)# 或者# 计算直方图的重合度degree  0for i in range(len(img1_hist)):if img1_hist[i] ! img2_hist[i]:degree  degree  (1 - abs(img1_hist[i] - img2_hist[i]) / max(img1_hist[i], img2_hist[i]))else:degree  degree  1degree  degree / len(img1_hist)print(图像2与图像1的重合度, degree)return similarity# 目标图像素材库文件夹路径
database_dir  ../../P0_Doc/img_data/
# 文件路径
img1_path  database_dir  car-101.jpg
img2_path  database_dir  car-102.jpgprint(图像1路径, img1_path)
print(图像2路径, img2_path)get_calcHist(img1_path, img2_path)输出打印 
图像1路径 ../../P0_Doc/img_data/car-101.jpg
图像2路径 ../../P0_Doc/img_data/car-102.jpg
图像2与图像1的相似度HISTCMP_CORREL/相关性 1.0
图像2与图像1的重合度 1.0说明图像2是图像1的180度倒置图。 
cv2.compareHist 是 OpenCV 中用于比较直方图相似度的函数。用于计算两个直方图之间的相关性correlation。img1_hist 和 img2_hist 是两个直方图它们分别代表两幅图像的颜色分布。 
直方图的比较方法 
cv2.HISTCMP_CORREL相关性 计算两个直方图之间的相关性。相关性的值越接近1表示两幅图像的颜色分布越相似值越接近-1表示颜色分布越不相似值接近0表示中等相似度。但不太适用于颜色直方图比较。cv2.HISTCMP_CHISQR卡方距离 计算卡方距离用于比较两个直方图之间的差异。值越接近 0 表示颜色分布越相似。cv2.HISTCMP_INTERSECT交集性 计算两个直方图的交集用于度量它们的相似度。该值越大表示相似度越高。cv2.HISTCMP_BHATTACHARYYA巴氏距离 计算两个直方图之间的巴氏距离。值越接近 0 表示颜色分布越相似。 讨论2直方图相似度函数  使用 cv2.compareHist()不同的直方图比较方法对比结果略有差异。这里我们使用 [0] 作为灰度通道进行测试实验。 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0
实验时间2023-10-27
实例名称imgHistogram_v2.3_compareHist.py
import cv2
import osdef get_degreeHist(img1_hist, img2_hist):# 计算直方图的重合度degree  0for i in range(len(img1_hist)):if img1_hist[i] ! img2_hist[i]:degree  degree  (1 - abs(img1_hist[i] - img2_hist[i]) / max(img1_hist[i], img2_hist[i]))else:degree  degree  1degree  degree / len(img1_hist)return degreedef all_compareHist(img1_path, img2_path):img1  cv2.imread(img1_path)img2  cv2.imread(img2_path)img1_hist  cv2.calcHist([img1], [0], None, [256], [0, 256])img2_hist  cv2.calcHist([img2], [0], None, [256], [0, 256])similarity  get_degreeHist(img1_hist, img2_hist)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度, similarity)# 计算直方图相似度# cv2.HISTCMP_BHATTACHARYYA: 巴氏距离比较值越接近 0 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_BHATTACHARYYA)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_BHATTACHARYYA/巴氏距离, similarity)# cv2.HISTCMP_CHISQR: 卡方比较值越接近 0 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_CHISQR)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_CHISQR/卡方比较, similarity)# cv2.HISTCMP_CORREL: 相关性比较值越接近 1 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_CORREL)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_CORREL/相关性, similarity)# cv2.HISTCMP_INTERSECT: 直方图交集比较值越大表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_INTERSECT)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_INTERSECT/交集比较, similarity)return similarity# 目标图像素材库文件夹路径
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.jpgall_compareHist(img1_path, img2_path)输出打印 
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度 1.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_BHATTACHARYYA/巴氏距离 0.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CHISQR/卡方比较 0.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CORREL/相关性 1.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_INTERSECT/交集比较 1232154.0图像 car-103.jpg 与目标图像 car-101.jpg 的相似度 [0.6923658]
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_BHATTACHARYYA/巴氏距离 0.2135487778250319
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CHISQR/卡方比较 11867327.715396598
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CORREL/相关性 0.4266303485505497
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_INTERSECT/交集比较 972986.0讨论3彩色图像直方图  以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0
实验时间2023-10-27
实例名称imgHistogram_v2.4_rgb_compareHist.py
import cv2
import osdef bgr_compareHist(img1_path, img2_path):img1  cv2.imread(img1_path)img2  cv2.imread(img2_path)img1_hist  cv2.calcHist([img1], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])img2_hist  cv2.calcHist([img2], [0, 1, 2], None, [8, 8, 8], [0, 256, 0, 256, 0, 256])# 计算直方图相似度# cv2.HISTCMP_BHATTACHARYYA: 巴氏距离比较值越接近 0 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_BHATTACHARYYA)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_BHATTACHARYYA/巴氏距离, similarity)# cv2.HISTCMP_CHISQR: 卡方比较值越接近 0 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_CHISQR)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_CHISQR/卡方比较, similarity)# cv2.HISTCMP_CORREL: 相关性比较值越接近 1 表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_CORREL)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_CORREL/相关性, similarity)# cv2.HISTCMP_INTERSECT: 直方图交集比较值越大表示颜色分布越相似similarity  cv2.compareHist(img1_hist, img2_hist, cv2.HISTCMP_INTERSECT)print(f图像 {os.path.basename(img2_path)} 与目标图像 {os.path.basename(img1_path)} 的相似度HISTCMP_INTERSECT/交集比较, similarity)return similarity# 目标图像素材库文件夹路径
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.jpgbgr_compareHist(img1_path, img2_path)输出打印 
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_BHATTACHARYYA/巴氏距离 0.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CHISQR/卡方比较 0.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CORREL/相关性 1.0
图像 car-102.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_INTERSECT/交集比较 1232154.0图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_BHATTACHARYYA/巴氏距离 0.25780152883475765
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CHISQR/卡方比较 981578.8189641015
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_CORREL/相关性 0.8933747646918704
图像 car-103.jpg 与目标图像 car-101.jpg 的相似度HISTCMP_INTERSECT/交集比较 911172.0对比 讨论2直方图相似度函数 的输出结果可以看到相同测试图像彩色直方图的相似度 与 灰度直方图的相似度 有一点差异原因就是通过单通道的灰度直方图可以捕捉到图像的整体亮度和对比度信息而不受颜色的影响。在相似图片查找中通常更关注图像的结构和纹理因此灰度信息更具代表性。 
第四步相似度评估 
根据直方图比较的结果似度得分进行目标图像相似度评估。 案例场景图像测试素材库中查找所有图像找出与目标图像相似值小于等于0.5的图像。 ......for similarity in similarities:if (similarity[1]  0.5):print(f图像名称{similarity[0]}与目标图像 {os.path.basename(img_org_path)} 的近似值{similarity[1]})4.2 测试 
实验场景 
通过 opencv使用直方图算法查找目标图像素材库中所有符合期望值的相似图像。 
实验素材 
这里我准备了45张素材图像其中14张图像为水果其余为不同类型的汽车但形态不一。  
实验代码 以图搜图图像直方图Image Histogram查找相似图像的原理与实现
测试环境win10 | python 3.9.13 | OpenCV 4.4.0 | numpy 1.21.1 | matplotlib 3.7.1
实验场景图像测试素材库中查找所有图像找出与目标图像相似值小于等于0.7的图像
实验时间2023-10-27
实例名称imgHistogram_v3.2_gray_show.py
import os
import time
import cv2
import matplotlib.pyplot as pltdef get_calcHist(org_img_hist, img_path):# 读取图像通过OpenCV的imread加载RGB图像img  cv2.imread(img_path)# img  cv2.cvtColor(cv2.imread(img_path), cv2.COLOR_BGR2GRAY)img_hist  cv2.calcHist([img], [0], None, [256], [0, 256])# 计算直方图相似度# cv2.HISTCMP_CORREL: 相关性比较值越接近 1 表示颜色分布越相似# cv2.HISTCMP_CHISQR: 卡方比较值越接近 0 表示颜色分布越相似# cv2.HISTCMP_BHATTACHARYYA: 巴氏距离比较值越接近 0 表示颜色分布越相似# cv2.HISTCMP_INTERSECT: 直方图交集比较值越大表示颜色分布越相似similarity  cv2.compareHist(org_img_hist, img_hist, cv2.HISTCMP_BHATTACHARYYA)return similaritydef show_similar_images(similar_images, images_per_column3):# 计算总共的图片数量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), squeezeFalse)# 遍历每一行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(fSimilar Image: {os.path.basename(image_path)} \n Similar Score: {similarity:.4f})# 关闭坐标轴axes[row, col].axis(off)# 显示整个图plt.show()# ------------------------------------------------ 测试 ------------------------------------------------
if __name__  __main__:time_start  time.time()# 指定测试图像库目录img_dir  ../../P0_Doc/img_data/# 指定测试图像文件扩展名img_suffix  [.jpg, .jpeg, .png, .bmp, .gif]# 获取当前执行脚本所在目录script_dir  os.path.dirname(__file__)# 获取目标测试图像的全路径img_org_path  os.path.join(script_dir, img_dir, apple-101.jpg)# 加载要查询的图像query_image  cv2.imread(img_org_path)# query_image  cv2.cvtColor(cv2.imread(img_org_path), cv2.COLOR_BGR2GRAY)# 计算查询图像的直方图灰度直方图算法img_org_hist  cv2.calcHist([query_image], [0], None, [256], [0, 256])print(f目标图像{os.path.relpath(img_org_path)})# 获取测试图像库中所有文件all_files  os.listdir(os.path.join(script_dir, img_dir))# 筛选出指定后缀的图像文件img_files  [file for file in all_files if any(file.endswith(suffix) for suffix in img_suffix)]# 存储相似度值和对应的图像路径img_search_results  []# 遍历测试图像库中的每张图像for img_file in img_files:# 获取相似图像文件路径img_path  os.path.join(script_dir, img_dir, img_file)# 获取相似图像可识别哈希值图像指纹similarity  get_calcHist(img_org_hist, img_path)# print(f图像名称{img_path}与目标图像 {os.path.basename(img_org_path)} 的近似值{similarity})if (similarity  0.7):# 存储相似度值和对应的图像路径img_search_results.append((os.path.relpath(img_path), similarity))# 按相似度升序排序img_search_results.sort(keylambda item: item[1])for img_similarity in img_search_results:print(f图像名称{img_similarity[0]}与目标图像 {os.path.basename(img_org_path)} 的相似值{img_similarity[1]})time_end  time.time()print(f耗时{time_end - time_start})# 显示目标相似图像show_similar_images(img_search_results)多图相似查找效果显示实验代码使用的是巴氏距离比较值越接近 0 表示颜色分布越相似  
输出打印 
目标图像..\..\P0_Doc\img_data\apple-101.jpg
图像名称..\..\P0_Doc\img_data\apple-101.jpg与目标图像 apple-101.jpg 的相似值0.0
图像名称..\..\P0_Doc\img_data\apple-104.jpg与目标图像 apple-101.jpg 的相似值0.0
图像名称..\..\P0_Doc\img_data\car-109.jpg与目标图像 apple-101.jpg 的相似值0.6158102157213413
图像名称..\..\P0_Doc\img_data\car-103.jpg与目标图像 apple-101.jpg 的相似值0.662176197294615
图像名称..\..\P0_Doc\img_data\car-101.jpg与目标图像 apple-101.jpg 的相似值0.6813075243521007
图像名称..\..\P0_Doc\img_data\car-102.jpg与目标图像 apple-101.jpg 的相似值0.6813075243521007
图像名称..\..\P0_Doc\img_data\Q3-09.jpg与目标图像 apple-101.jpg 的相似值0.6844184531149912
图像名称..\..\P0_Doc\img_data\car-108.jpg与目标图像 apple-101.jpg 的相似值0.6861940450661771
图像名称..\..\P0_Doc\img_data\X3-09.jpg与目标图像 apple-101.jpg 的相似值0.692340714053627
图像名称..\..\P0_Doc\img_data\apple-114.jpg与目标图像 apple-101.jpg 的相似值0.6932278615425139
图像名称..\..\P0_Doc\img_data\apple-112.jpg与目标图像 apple-101.jpg 的相似值0.6959175186621991
图像名称..\..\P0_Doc\img_data\pear-201.jpg与目标图像 apple-101.jpg 的相似值0.6997766670329476
耗时1.03620386123657235. 总结 
总体来说直方图算法属于一种传统外观相似算法适用于一些简单的图像相似性比较问题但直方图反应的是图像灰度值得概率分布并没有图像的空间位置信息在里面因此可能会出现误判。比如纹理结构相同但明暗不同的图像应该相似度很高但实际结果是相似度很低而纹理结构不同但明暗相近的图像相似度却很高。 
优点 
简单直观 直方图是一种简单直观的图像表达方式易于理解和实现。快速计算 直方图的计算相对快速特别是对于小尺寸的图像。颜色不变性 直方图在某种程度上对颜色的变化具有不变性因此可以在一定程度上应对图像的轻微变形。对光照变化有一定的鲁棒性 直方图可以在一定程度上处理图像的光照变化。 
缺点 
不考虑空间信息 直方图方法忽略了图像的空间信息对于图像的排列、结构等方面的变化较为敏感。受噪声影响 如果图像受到噪声的影响直方图会受到一定程度的干扰。灰度信息有限 灰度直方图只考虑了像素的灰度信息对于颜色信息较为有限。无法处理形状变化 直方图方法难以处理图像中物体的形状变化。 6. 系列书签 
OpenCV书签 #均值哈希算法的原理与相似图片搜索实验 OpenCV书签 #感知哈希算法的原理与相似图片搜索实验 OpenCV书签 #差值哈希算法的原理与相似图片搜索实验 OpenCV书签 #直方图算法的原理与相似图片搜索实验