Python+OpenCV:直方图(Histograms)
理论
什么是直方图?您可以将直方图看作是一种图形或图表,它为您提供关于图像强度分布的总体概念。它是x轴为像素值(范围从0到255,不总是这样),y轴为图像中相应像素个数的图形。
这只是理解图像的另一种方式。通过观察一幅图像的直方图,你可以对该图像的对比度、亮度、强度分布等有直观的认识。现在几乎所有的图像处理工具都提供了直方图的特性。
你可以看到图像和它的直方图。(记住,此直方图是绘制灰度图像,而不是彩色图像)。
直方图的左边区域表示图像中较暗像素的数量,右边区域表示较亮像素的数量。
从直方图中,你可以看到暗区比亮区多,而中间色调(像素值在中间,比如127左右)的数量非常少。
获得直方图
现在我们知道了直方图是什么,我们可以看看如何获得它。
OpenCV和Numpy都内置了这个功能。在使用这些函数之前,我们需要了解与直方图相关的一些术语。
BINS: 上面的直方图显示了每个像素值的像素数量,即从0到255。也就是说,你需要256个值来显示上面的直方图。
但是考虑一下,如果您不需要分别查找所有像素值的像素数量,而是查找像素值区间内的像素数量,那会怎么样呢?例如,你需要找到介于0到15,然后16到31之间的像素数量,……, 240至255。
您将只需要16个值来表示直方图。这就是OpenCV教程中给出的关于直方图的例子。
所以你要做的就是简单地把整个直方图分成16个子部分,每个子部分的值就是其中所有像素计数的总和。
这每一个子部分称为“BIN”。在第一种情况下,BINS的数量为256(每个像素一个箱子),而在第二种情况下,只有16个BINS。在OpenCV文档中,bin由histSize术语表示。
DIMS: 它是我们收集数据的参数的数量。在本例中,我们只收集关于一个东西的数据,即强度值。这里是1。
RANGE: 这是你想要测量的强度值的范围。通常,它是[0,256],即所有强度值。
示例
####################################################################################################
# 图像直方图(Image Histograms)
def lmc_cv_image_histograms():
"""
函数功能: 图像直方图。
"""
# 读取图像
image = lmc_cv.imread('D:/99-Research/Python/Image/Rock.jpg')
# 图像直方图(Image Histograms)
x = range(256)
hist1 = lmc_cv.calcHist([image], [0], None, [256], [0, 256])
hist2, bins2 = np.histogram(image.ravel(), 256, [0, 256])
# 创建窗口
pyplot.figure('Image Display 1')
titles = ['Original Image', 'Histogram in OpenCV', 'Histogram in Numpy']
# 显示原始图像
pyplot.subplot(1, 3, 1)
pyplot.imshow(image, 'gray')
pyplot.title(titles[0])
pyplot.xticks([])
pyplot.yticks([])
# 显示直方图
pyplot.subplot(1, 3, 2)
pyplot.plot(x, hist1)
pyplot.title(titles[1])
# pyplot.xticks([])
# pyplot.yticks([])
pyplot.subplot(1, 3, 3)
pyplot.plot(x, hist2)
pyplot.title(titles[2])
# pyplot.xticks([])
# pyplot.yticks([])
# pyplot.axis('on')
# 显示窗口
pyplot.show()
# 显示彩色图像各个通道的直方图
image = lmc_cv.imread('D:/99-Research/Python/Image/Lena.jpg')
image = lmc_cv.cvtColor(image, lmc_cv.COLOR_BGR2RGB)
# create a mask
mask = np.zeros(image.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_image = lmc_cv.bitwise_and(image, image, mask=mask)
color = ('r', 'g', 'b')
pyplot.figure('Image Display 2')
# 显示原始图像
pyplot.subplot(2, 2, 1)
pyplot.imshow(image, 'gray')
pyplot.title(titles[0])
pyplot.xticks([])
pyplot.yticks([])
# 显示原始图像直方图
pyplot.subplot(2, 2, 2)
for i, col in enumerate(color):
histr = lmc_cv.calcHist([image], [i], None, [256], [0, 256])
pyplot.plot(histr, color=col)
pyplot.xlim([0, 256])
pyplot.title('R/G/B Histogram')
# 显示掩模图像
pyplot.subplot(2, 2, 3)
pyplot.imshow(masked_image, 'gray')
pyplot.title('Mask Image')
pyplot.xticks([])
pyplot.yticks([])
# 显示掩模图像直方图
pyplot.subplot(2, 2, 4)
for i, col in enumerate(color):
histr = lmc_cv.calcHist([image], [i], mask, [256], [0, 256])
pyplot.plot(histr, color=col)
pyplot.xlim([0, 256])
pyplot.title('Mask R/G/B Histogram')
pyplot.show()
# 根据用户输入保存图像
if ord("q") == (lmc_cv.waitKey(0) & 0xFF):
# 销毁窗口
pyplot.close()
return