使用 OpenCV 自带函数绘制直方图比较麻烦
直方图的计算,绘制与分析
目标
• 使用 OpenCV 或 Numpy 函数计算直方图
• 使用 Opencv 或者 Matplotlib 函数绘制直方图
• 将要学习的函数有:cv2.calcHist(),np.histogram()
直方图是根据灰度图像绘制的,而不是彩色图像
统计直方图
BINS每个特征空间 子区段 的数目DIMS需要统计的特征的数目, 在上例中, dims = 1 因为我们仅仅统计了灰度值(灰度图像)。RANGE每个特征空间的取值范围,在上例中,
cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
- images: 原图像(图像格式为 uint8 或 float32)。当传入函数时应该用中括号 [] 括起来,例如:[img]。
- channels: 同样需要用中括号括起来,它会告诉函数我们要统计那幅图像的直方图。如果输入图像是灰度图,它的值就是 [0];如果是彩色图像的话,传入的参数可以是 [0],[1],[2] 它们分别对应着通道 B,G,R。
- mask: 掩模图像。要统计整幅图像的直方图就把它设为 None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。
- histSize:BIN 的数目。也应该用中括号括起来,
- ranges: 像素值范围,通常为 [0,256]
img = cv2.imread('a.jpg',cv2.IMREAD_GRAYSCALE)
# 别忘了中括号 [img],[0],None,[256],[0,256],只有 mask 没有中括号
hist_cv = cv2.calcHist([img],[0],None,[256],[0,256])
hist 是一个 256x1 的数组,每一个值代表了与次灰度值对应的像素点数
目
绘制直方图
使用 Matplotlib Matplotlib 中有直方图绘制函数:matplotlib.pyplot.hist()
它可以直接统计并绘制直方图。你应该使用函数 calcHist() 或 np.histogram()
统计直方图。代码如下:
from matplotlib import pyplot as plt
img = cv2.imread('a.jpg',0)
plt.hist(img.ravel(),256,[0,256]);
plt.show()
绘制多通道(BGR)的直方图
img = cv2.imread('Pytorch.png')
color = ('b', 'g', 'r')
# 对一个列表或数组既要遍历索引又要遍历元素时
# 使用内置 enumerrate 函数会有更加直接,优美的做法
# enumerate 会将数组或列表组成一个索引序列。
# 使我们再获取索引和索引内容的时候更加方便
for i, col in enumerate(color):
histr = cv2.calcHist([img], [i], None, [256], [0, 256])
plt.plot(histr, color=col)
plt.xlim([0, 256])
plt.show()
使用掩模
要统计图像某个局部区域的直方图只需要构建一副掩模图像。将要统计的部分设置成白色,其余部分为黑色,就构成了一副掩模图像。然后把这个掩模图像传给函数就可以了.
img = cv2.imread('home.jpg',0)
# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img,img,mask = mask)
# Calculate histogram with mask and without mask
# Check third argument for mask
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])
plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])
plt.show()
直方图的均衡化
直方图的均衡化
- 但是一副高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向拉伸(如下图),这就是直方图均衡化要做的事情。通常情况下这种操作会改善图像的对比度。
- OpenCV 中的直方图均衡化函数为 cv2.equalizeHist()。这个函数的输入图片仅仅是一副
灰度图像,输出结果是直方图均衡化之后的图像
img = cv2.imread('Pytorch.png')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
equ = cv2.equalizeHist(img_gray)
res = np.hstack((img_gray,equ))
cv2.imshow('res.png',res)
plt.hist(img.ravel(),256,[0,256])
plt.figure('img')
plt.hist(img_gray.ravel(),256,[0,256])
plt.figure('img_gray')
plt.show()
cv2.waitKey(0)
自适应的直方图均衡化
img = cv2.imread('tsukuba_l.png',0)
# create a CLAHE object (Arguments are optional).
# 不知道为什么我没好到 createCLAHE 这个模块
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
cl1 = clahe.apply(img)
cv2.imwrite('clahe_2.jpg',cl1)
2D直方图
- 在前面的部分我们介绍了如何绘制一维直方图,之所以称为一维,是因为我们只考虑了图像的一个特征:灰度值。但是在 2D 直方图中我们就要考虑两个图像特征。对于彩色图像的直方图通常情况下我们需要考虑每个的颜色(Hue)和饱和度(Saturation)。根据这两个特征绘制 2D 直方图.
OpenCV 中的 2D 直方图
- 使用函数 cv2.calcHist() 来计算直方图既简单又方便。如果要绘制颜色直方图的话,我们首先需要将图像的颜色空间从 BGR 转换到 HSV。(记住,计算一维直方图,要从 BGR 转换到 HSV)。计算 2D 直方图,函数的参数要做如下修改:
• channels=[0,1] 因为我们需要同时处理 H 和 S 两个通道。
• bins=[180,256]H 通道为 180,S 通道为 256。
• range=[0,180,0,256]H 的取值范围在 0 到 180,S 的取值范围在 0 到 256。
Numpy中2D直方图
- Numpy 同样提供了绘制 2D 直方图的函数:np.histogram2d()。(还记得吗,绘制 1D 直方图时我们使用的是 np.histogram())
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread('home.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist, xbins, ybins = np.histogram2d(h.ravel(),s.ravel(),[180,256],[[0,180],[0,256]])
第一个参数是 H 通道,第二个参数是 S 通道,第三个参数是 bins 的数目,第四个参数是数值范围。现在我们要看看如何绘制颜.
绘制2D直方图
img = cv2.imread('lean.jpg')
hsv = cv2.cvtColor(img,cv2.COLOR_BGR2HSV)
hist = cv2.calcHist([hsv], [0, 1], None, [180, 256], [0, 180, 0, 256])
plt.imshow(hist,interpolation = 'nearest')
plt.show()
cv2.waitKey(0)
直方图中的反向投影
- 会输出与输入图像(待搜索)同样大小的图像,其中的每一个像素值代表了输入图像上对应点属于目标对象的概率。用更简单的话来解释,输出图像中像素值越高(越白)的点就越可能代表我们要搜索的目标(在输入图像所在的位置)。这是一个直观的解释。直方图投影经常与 camshift算法等一起使用。
本文介绍了如何使用OpenCV和Numpy计算及绘制直方图,包括单通道和多通道图像的直方图、掩模应用、直方图均衡化以及2D直方图。此外,还提到了反向投影在图像搜索中的应用。
2万+

被折叠的 条评论
为什么被折叠?



