直方图是根据灰度图像绘制的,而不是彩色图像。直方图的左边区域像是了暗一点的像素数量右侧显示了亮一点的像素的数量。从这幅图上你可以看到灰暗的区域比两的区域要大,而处于中间部分的像素点很少。
一、术语
BINS :上面的直方图显示了每个灰度值对应的像素数。如果像素值为 0到 255,你就需要 256 个数来显示上面的直方图。 但是,如果你不需要知道每一个像素值的像素点数目的,而只希望知道两个像素值之间的像素点数目怎么办呢?只需要把原来的 256 个值等分成 16 小组,取每组的总和。而这里的每一个小组就被成为 BIN。在 OpenCV 的文档中用 histSize 表示 BINS。
DIMS :表示我们收集数据的参数数目。在本例中,我们对收集到的数据只考虑一件事:灰度值。所以这里就是 1 。
RANGE :就是要统计的灰度值范围,一般来说为 [0 , 256] ,也就是说所有的灰度值。
二、cv2中获取直方图的方法
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
images: 原图像(图像格式为 uint8 或 flfloat32 )。当传入函数时应该
用中括号 [] 括起来,例如: [img] 。
channels: 同样需要用中括号括起来,它会告诉函数我们要统计那幅图
像的直方图。如果输入图像是灰度图,它的值就是 [0] ;如果是彩色图像的话,传入的参数可以是 [0] , [1] , [2] 它们分别对应着通道 B , G , R 。
mask: 掩模图像。要统计整幅图像的直方图就把它设为 None 。但是如
果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并
使用它。(后边有例子)
histSize: BIN 的数目。也应该用中括号括起来,例如: [256] 。
ranges: 像素值范围,通常为 [0 , 256]
三、利用直方图计算图像相似性
更多的图片相似度算法:https://blog.csdn.net/xian0710830114/article/details/118786385?spm=1001.2014.3001.5501
import numpy as np import cv2 def normalize(data): return data / np.sum(data) def hist_similarity(img1, img2, hist_size=256): imghistb1 = cv2.calcHist([img1], [0], None, [hist_size], [0, 256]) imghistg1 = cv2.calcHist([img1], [1], None, [hist_size], [0, 256]) imghistr1 = cv2.calcHist([img1], [2], None, [hist_size], [0, 256]) imghistb2 = cv2.calcHist([img2], [0], None, [hist_size], [0, 256]) imghistg2 = cv2.calcHist([img2], [1], None, [hist_size], [0, 256]) imghistr2 = cv2.calcHist([img2], [2], None, [hist_size], [0, 256]) distanceb = cv2.compareHist(normalize(imghistb1), normalize(imghistb2), cv2.HISTCMP_CORREL) distanceg = cv2.compareHist(normalize(imghistg1), normalize(imghistg2), cv2.HISTCMP_CORREL) distancer = cv2.compareHist(normalize(imghistr1), normalize(imghistr2), cv2.HISTCMP_CORREL) meandistance = np.mean([distanceb, distanceg, distancer]) return meandistance if __name__ == '__main__': img1 = cv2.imread('1.png') img2 = cv2.imread('2.jpg') print(hist_similarity(img1, img2))