网站菜单

OpenCV学习笔记(8)——直方图与掩膜

1. 直方图的概念

  • 横坐标:图像中各个像素点的灰度级
  • 纵坐标:具有该灰度级的像素个数

直方图是根据灰度图像绘制的,而不是彩色图像。直方图的左边区域像是了暗一点的像素数量,右侧显示了亮一点的像素的数量。从这幅图上你可以看到灰暗的区域比两的区域要大,而处于中间部分的像素点很少。

在归一化直方图中:

横坐标代表图中个个像素点的灰度级;纵坐标代表出现这个灰度级的概率。

2. Matplotlib绘制直方图

Python中主要使用matplotlib库来绘制直方图。

import matplotlib.pyplot as plt

#hist(数据源,像素集)
#数据源:图像,必须是1维数组。(将图像转化为一维数组)。使用b = a.ravel() 将二维转化为一维。
#像素集:一般是256,指[0, 255]

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

3. OpenCV统计直方图

#hist = cv2.calcHist(img1, channels, mask, histSize, ranges[,accumulate])

hist = cv2.calcHist([img], [0], None, [256], [0, 255])

print(type(hist))
 #<class 'numpy.ndarray'>
print(hist.size)
 #256
print(hist.shape) #(256, 1)
print(hist) #每一个灰度级对应的灰度点数量
  • hist:返回的直方图,是一个二维数组。
  • channels:指定通道。灰度图的值为[0],彩色图像[0], [1], [2]对应BGR
  • mask: 掩码图像。统计整个直方图时设为None,只计算一部分时需要掩码图像。
  • histSize: BINS的数量,如[256]
  • ranges: 像素值的范围。一般是[0, 255]
  • accumulate: 累计默认值为false, 如果为true,则在开始分配时不清零。该参数允许从多个对象中计算单个直方图,或者实时更新直方图。多个直方图的累计结果,用于对一组图像计算直方图。

4. 绘制OpenCV统计直方图

使用Matplotlib调用第三节中OpenCV生成的数据,作为y值绘制。

#灰度图
hist = cv2.calcHist([img1], [0], None, [256], [0, 255])
plt.plot(hist, color = 'b')
plt.show()

#BGR图
histb = cv2.calcHist([img1], [0], None, [256], [0, 255])
histg = cv2.calcHist([img1], [1], None, [256], [0, 255])
histr = cv2.calcHist([img1], [2], None, [256], [0, 255])
plt.plot(histb, color = 'b')
plt.plot(histg, color = 'g')
plt.plot(histr, color = 'r')
plt.show()

5. 掩膜原理

OpenCV中很多函数都带有一个mask参数,mask被称为掩模。图像掩模一般用来对处理的图像(全部或者局部)进行遮挡,来控制图像处理的区域或处理过程。

掩膜黑色部分为不透明,白色部分为透明。将掩膜放在原始图像上,黑色部分被覆盖掉,白色部分映衬原始图像。结果图像只有白色部分,黑色被覆盖。

因此在OpenCV中,掩模一般是小于等于源图像的单通道矩阵,掩模中的值分为两种0和非0。以当mask的值不为0,则将源图像拷贝到目标图像,当mask为0,则不进行拷贝,目标图像保持不变。

通过使用OpenCV中的bitwise_and进行与操作,生成掩膜图像:

mask = np.zeros(img1.shape, np.uint8)
mask[100:200, 100:200] = 255
img2 = cv2.bitwise_and(img1, mask)

6. 使用掩膜构建直方图

#第一步,创建一个全0数组,大小为img大小
mask = np.zeros(img1.shape, np.uint8)

#第二部,在图像中创建透明部分。(其实就是将数组中部分值修改为255)
mask[200:400, 200:400] = 255

#第三步,使用第3步的统计直方图函数使用掩膜
hist = cv2.calcHist([img1], [0], mask, [256], [0, 255])

注意:

  1. 掩膜的维度应该与图像相同,若是BGR图像则应该使用cv2.IMREAD_GRAYSCALE读取为灰度图。
  2. 掩膜截取大小不能超过掩膜数组大小。(听起来很幼稚但就是犯了这种低级错误。。)

7. 直方图均衡化

7.1 直方图均衡化原理

直方图均衡化(Histogram Equalization)是一种增强图像对比度(Image Contrast)的方法,其主要思想是将一副图像的直方图分布变成近似均匀分布,从而增强图像的对比度。直方图均衡化虽然只是数字图像处理(Digital Image Processing)里面的基本方法,但是其作用很强大,是一种很经典的算法。

均衡化的过程主要分为三步:

  1. 计算累计直方图
  2. 将累计直方图进行区间转换
  3. 在累计直方图中,概率相近的原始值会被处理为相同的值。(因为肉眼很难区分)

假设有图像:

得图像的统计信息如下图所示,并根据统计信息获得累计直方图:

根据统计信息完成灰度值映射(0-255最大值255,所以乘以255):

映射后的像素分布如下所示:

虽然两者相似,但是右侧的分布更均衡。相邻像素级概率与高概率近似相等(因为肉眼很难分辨)。

应用场合:

  • 医疗图像处理
  • 车牌识别
  • 人脸识别

7.2 直方图均衡化函数

img2 = cv2.equalizeHist(img1)

效果:

8. Matplotlib小技巧

8.1 图像分屏

在一个图像里显示多个窗口

#subplot(nrows, ncols, plot_number)
#当每一个参数都小于10时,可以省略逗号

plt.subplot(221),plt.hist(img1.ravel(), 256)
plt.subplot(222),plt.hist(img2.ravel(), 256)
plt.subplot(223),plt.imshow(img1)
plt.subplot(224),plt.imshow(img2)

效果:

可以发现,排版正确了但是读取的图像发绿。具体解决方法在下一节介绍。

8.2 显示图像

#imshow(X, cmap = None)
#X:要绘制的图像
#colormap:颜色图谱,默认为RGB(A)

#显示灰色图像
#第一步,载入灰度图像
img1 = cv2.imread("Lenna.jpg", cv2.IMREAD_GRAYSCALE)
#或先载入彩色然后转换
img1 = cv2.imread("Lenna.jpg")
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
#第二步,显示灰度图像,使用plt.axis('off')关闭坐标轴
plt.imshow(img1, cmap = plt.cm.gray),plt.axis('off')

#显示彩色图像
#第一步,载入以后分割通道
b, g, r = cv2.split(img1)
#第二部,按照RGB顺序重组图片
img2 = cv2.merge([r, g, b])
#第三步,显示RGB图像
plt.imshow(img2),plt.axis('off')

灰度图像:cmap = plt.cm.gray

彩色图像:默认为RGB(A), 如果使用OpenCV读取图像,默认空间为BGR,需要调整色彩空间为RGB。

显示评论 (0)

文章评论

相关推荐

Yolov5_Seg输出解析

通过矩阵乘法(在代码中称为“matmul”)来计算分割掩码的原因,主要与实例分割网络(例如 YOLOv5 Segmentation)的实现方式有关。这种方法实际上是一种高效的特征图与目标分割系数组合的…

Ubuntu交叉编译Python

在 Ubuntu 上交叉编译 Python 的流程通常用于为不同平台生成可执行文件(如 ARM、MIPS 等)。以下是一般的操作步骤: 1. 安装必要的依赖工具 首先,确保已经安装了编译所需的工具和依…