今天学习图像直方图和图像均衡化
一:图像直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 图像的直方图,就是统计哪些像素点,或者那一段像素区间的像素的个数
# 在opencv中使用的是 calcHist(images, channels, mask, histSzie, ranges)
# 参数解析:
# images: 一次性可以传入多个图像。传入图像时候是一个list, 用[]括起来,数据类型是 uint8/float32
# channels: 统计的是哪个通道,如果是灰度图传入[0],如果是彩色图像,传入[0]、[1]、[2],代表的是 BGR通道
# mask: 给图像做个掩码,如果想统计这个图像,则是传入None, 如果想只统计一部分,则需要做个掩码传入
# histSzie: BIN的数量,平均划分成几个范围,如果是一个像素点一个范围的话,就是256.
# ranges: 像素的范围,通常为[0, 256]
# 展示图像,封装成函数
def cv_show_image(name, img):
cv2.imshow(name, img)
cv2.waitKey(0) # 等待时间,单位是毫秒,0代表任意键终止
cv2.destroyAllWindows()
img = cv2.imread('images/saoge2.jpg')
print(img.shape)
plt.hist(img.ravel(), 256)
plt.title('src_img_hist')
plt.show()
# 计算各个通道的直方图
hist_b = cv2.calcHist([img], [0], None, [256], [0, 256])
print(hist_b.shape) # (256, 1)
hist_g = cv2.calcHist([img], [1], None, [256], [0, 256])
print(hist_g.shape) # (256, 1)
hist_r = cv2.calcHist([img], [2], None, [256], [0, 256])
print(hist_r.shape) # (256, 1)
# 绘这BGR三个通道的直方图
plt.plot(hist_b, 'b')
plt.plot(hist_g, 'g')
plt.plot(hist_r, 'r')
plt.xlim([0, 256])
plt.title('bgr_hist')
plt.show()
# 带有掩码操作,当我们只想取其中部分区域进行直方图统计的时候,就可以用得上掩码
# 掩码是选择的区域是保留,不选择的区域是废弃,因此掩码在选择区域的值是255,丢弃的区域的值是0
# 下面是定义mask掩码的方式
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:540] = 255
masked_img = cv2.bitwise_and(img, img, mask=mask) # 得到亚麻作用后的图像
hist_full_img = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask_img = cv2.calcHist([img], [0], mask, [256], [0, 256])
plt.subplot(2,2,1), plt.imshow(img, 'gray')
plt.subplot(2,2,2), plt.imshow(mask, 'gray')
plt.subplot(2,2,3), plt.imshow(masked_img, 'gray')
plt.subplot(2,2,4), plt.plot(hist_full_img, 'b'), plt.plot(hist_mask_img, 'g')
plt.xlim([0, 256])
plt.title('mask_hist')
plt.show()
原始图像的灰度直方图是:
原始图像的BGR三通道各自的直方图
原始图像的B带有掩码的B通道直方图
二:直方图均衡化
# 直方图的均衡化
# 得到直方图后,有一些直方图的像素分布不均匀,导致颜色很偏,因此需要均衡化调节
# 图像均衡化得目的是为了提高图像的对比度。对于灰度分布比较集中的图(整体太暗或者太亮),可以起到均衡作用(有明有暗)。
# 方法就是:
# 读入图像
# 对每个通道分别统计像素值[0,255]出现的次数。
# 对每个通道分别求像素值[0,255]出现的概率,得到概率直方图。
# 对每个通道分别求像素值[0,255]概率的累计和,得到累计概率直方图。
# 对每个通道根据累计概率直方图分别求像素映射函数。对每个通道完成每个像素点的映射。
# 举个例子,像素值为56的累计概率是0.2,那么像素值为56的新的映射像素值是 256*0.2=51
# 举个例子,像素值为255的累计概率一定是1,么像素值为255的新的映射像素值是 256*01=255
# 输出直方图均衡化的图像。
# 在opencv中的操作
# 读取原始图像
img = cv2.imread('images/saoge2.jpg', cv2.IMREAD_GRAYSCALE) # 读取灰度图像
plt.hist(img.ravel(), 256)
plt.title('src_img_hist')
plt.show()
# 图像直方图均衡化,整个图像都会进行均衡化
equ = cv2.equalizeHist(img)
plt.hist(equ.ravel(), 256)
plt.title('equalizeHist_img')
plt.show()
# 自适应均衡化
# 把图像分成一些小格子,各自做各自的均衡化
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8,8))
res_clahe = clahe.apply(img)
res = np.hstack((img, equ, res_clahe))
cv_show_image('equalizeHist', res)