天天看点

Opencv之直方图

Opencv之直方图

如上图所示,直方图统计的是一张图片中所含不同像素值的个数,横坐标为像素值,纵坐标为此像素值在图中的个数。如像素值为0的像素点在图中有100个,则在直方图中的第一列对应的纵坐标为100。(如果第一列对应的是0像素值的话)

在Opencv中,有专门的函数用来计算每个像素值对应多少像素点:

cv2.calcHist(images,channels,mask,histSize,ranges)

  • images: 原图像图像格式为 uint8 或 float32。当传入函数时应用中括号 [] 括来例如[img]
  • channels: 同样用中括号括来它会告函数我们统幅图像的直方图。如果输入图像是灰度图它的值就是[0];如果是彩色图像 的传入的参数可以是[0]、[1]、[2] 它们分别对应着 B、G、R。
  • mask: 掩模图像。统整幅图像的直方图就把它为 None。但是如果你想统图像某一分的直方图的你就制作一个掩模图像并使用它。
  • histSize:BIN 的数目。也应用中括号括起来。
  • ranges: 像素值范围常为 [0, 256]。
img = cv2.imread('cat.jpg',0) #0表示灰度图
hist = calcHist([img], [0], None, [256], [0, 256])
hist.shape
           

可以直接用plt.hist()函数绘制直方图:

plt.hist(img.ravel(), 256)
plt.show()
           

也可以利用得到的hist绘制直方图:

plt.plot(hist)
plt.show()
           

如果输入图像是彩色的,可以绘制不同通道的直方图:

img = cv2.imread('cat.jpg') 
color = ('b','g','r')
for i, col in enumerate(color):
	histr = cv2.calcHist([img], [i], None, [256], [0, 256])
	plt.plot(histr, color=col)
	plt.xlim([0, 256])
           

如果只需要对一张图片中的某个区域绘制直方图,则可以使用掩膜操作:

# 创建mask
mask = np.zeros(img.shape[:, 2], np.uint8)
print(mask.shape)
mask[100: 300, 100: 400] = 255
# 导入原始图片
img = cv2.imread('cat.jpg', 0)
# 执行“与”操作,完成掩膜
masked_img = cv2.bitwise_and(img, img, mask=mask)
# 统计直方图
hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_full = 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之直方图

可见映射后像素值之间的差距变小了。

Opencv中,有专门的函数cv2.equalizeHist()来实现均衡化。

# 原始图像直方图
img = cv2.imread('clahe.jpg',0) #0表示灰度图 #clahe
plt.hist(img.ravel(),256); 
plt.show()
# 均衡化后的直方图
equ = cv2.equalizeHist(img) 
plt.hist(equ.ravel(),256)
plt.show()
           

但有时,直方图均衡化会分散图中某些部分的信息,如下图:

Opencv之直方图

经过均衡化之后,图片中雕塑的轮廓不易被看清了。

所以,我们需要使用自适应直方图均衡化,将整张图片分成几个部分来分别均衡化,然后再组合在一起。用于生成自适应均衡化图像的函数为:

cv2.createCLAHA(clipLimit, titleGridSize)

  • clipLimit颜色对比度的阈值。
  • titleGridSize进行像素均衡化的网格大小,即在多少网格下进行直方图的均衡化操作。
# 实例化自适应直方图均衡化函数
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
# 进行自适应直方图均衡化
res_clahe = clahe.apply(img)
# 进行图像的展示
res = np.hstack((img, equ, res_clahe))
cv2.imshow('res',res)
cv2.waitKey()
cv2.destroyAllWindows()
           

继续阅读