python+OpenCv笔记(十二):直方图(灰度直方图、掩膜的应用、直方图均衡化、自适应直方图均衡化)

一、灰度直方图

概念:

        图像直方图是表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素个数

        这种直方图中,横坐标的左侧为较暗的区域,而右侧为较亮的区域。因此一张较暗图片的直方图中的数据多集中于左侧和中间部分,而整体明亮、只有少量阴影的图像则相反。如图:

注意:图像直方图是根据灰度图进行绘制的,而不是彩色图像。

图像直方图的术语:

  1. dims:需要统计的特征数目。
               (比如,如果仅统计了灰度值,则dims=1,如果统计了BGR三色,则dims=3)
  2. bins:每个特征空间子区段的数目。
                (如下图的直方图中,每一竖条表示某一值或一区间,则该直方图的bins=16)
  3. range:要统计特征的取值范围。
                (如下图中,我们将[0,255]区间分成了16个子区间,其中range=[0,255])

直方图的意义:

        直方图是图像中像素强度分布的图形表达方式。

        它统计了每一个强度值所具有的像素个数。

        不同的图像的直方图可能是相同的

OpenCv API:

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

参数:

  1. images:原图像。当传入函数时应该用中括号 [] 括起来,例如:[img]
  2. channels:如果输入图像是灰度图,它的值就是[0];如果是彩色图像的话,传入的参数可以是[0],[1],[2]它们分别对应着通道B,G,R。
  3. mask:掩模图像。要统计整幅图像的直方图就把它设为None。但是如果你想统计图像某一部分的直方图的话,你就需要制作一个掩模图像,并使用它。
  4. histSize:bins的数目。也应该用中括号括起来,例如:[256]。
  5. ranges:像素值范围。通常为[0,256]。

代码编写:

import cv2 as cv
import matplotlib.pyplot as plt

src = cv.imread("E:\\view.jpg", 0)  # 直接以灰度图方式读入
img = src.copy()

# 统计灰度图
greyScale_map = cv.calcHist([img], [0], None, [256], [0, 256])

# 绘制灰度图
plt.figure(figsize=(10, 6), dpi=100)
plt.plot(greyScale_map)
plt.grid()
plt.show()

   

 二、掩膜的应用

原理:

        掩膜是用选定的图像、图形或物体,对要处理的图像进行遮挡,来控制图像处理的区域。
        在数字图像处理中,我们通常使用二维矩阵数组进行掩膜。掩膜是由0和1组成一个二进制图像,利用该掩膜图像要处理的图像进行掩膜,其中1值的区域被处理,0值区域被屏蔽,不会处理。

应用:

        掩膜的主要用途是:

  1. 提取感兴趣区域:用预先制作的感兴趣区掩膜与待处理图像进行”与“操作,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
  2. 屏蔽作用︰用掩膜对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
  3. 结构特征提取︰用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。·
  4. 特殊形状图像制作

        掩膜在遥感影像处理中使用较多,当提取道路或者河流,或者房屋时,通过一个掩膜矩阵来对图像进行像素过滤,然后将我们需要的地物或者标志突出显示出来。

代码编写:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

src = cv.imread("E:\\view.jpg", 0)  # 直接以灰度图方式读入
img = src.copy()

# 创建蒙版
mask = np.zeros(img.shape[:2], np.uint8)
mask[700:1000, 100:400] = 1

# 掩膜
masked_img = cv.bitwise_and(img, img, mask=mask)  # 与操作

# 统计掩膜后图像的灰度图
mask_histr = cv.calcHist([img], [0], mask, [256], [0, 256])

# 显示图像
fig, axes = plt.subplots(nrows=2, ncols=2, figsize=(10, 8), dpi=100)
axes[0][0].imshow(img, cmap=plt.cm.gray)
axes[0][0].set_title("原图")
axes[0][1].imshow(mask, cmap=plt.cm.gray)
axes[0][1].set_title("蒙版数据")
axes[1][0].imshow(masked_img, cmap=plt.cm.gray)
axes[1][0].set_title("掩膜后图像")
axes[1][1].plot(mask_histr)
axes[1][1].grid()
axes[1][1].set_title("掩膜后图像的灰度直方图")
plt.show()

三、直方图均衡化

原理:

        想象一下,如果一副图像中的大多数像素点的像素值都集中在某一个小的灰度值值范围之内会怎样呢?如果一幅图像整体很亮,那所有的像素值的取值个数应该都会很高。所以应该把它的直方图做一个横向拉伸(如下图),就可以扩大图像像素值的分布范围,提高图像的对比度,这就是直方图均衡化要做的事情。
 

 “直方图均衡化"是把原始图像的灰度直方图从比较集中的某个灰度区间变成在更广泛灰度范围内的分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。

 应用:

        提高图像整体的对比度。

        特别是有用数据的像素值分布比较接近时,在X光图像中使用广泛,可以提高骨架结构的显示,另外在曝光过度或不足的图像中可以更好的突出细节。
 

 OpenCv API:

cv2.equalizeHist(img)

参数:

        img:输入的灰度图

代码编写:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

src = cv.imread("E:\\qi.png", 0)  # 直接以灰度图方式读入
img = src.copy()

# 均衡化处理
dst = cv.equalizeHist(img)

# 显示图像
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(dst, cmap=plt.cm.gray)
axes[1].set_title("均衡化后的图像")
plt.show()

 四、自适应的直方图均衡化

由来:

        上述的直方图均衡化,我们考虑的是图像的全局对比度。的确在进行完直方图均衡化之后,图片背景的对比度被改变了,但在许多情况下,这样做的效果并不好,因为均衡化之后的图像很有可能发生局部过亮或者局部过暗的情况,从而造成数据信息的丢失。
 

原理:

  1. 将整幅图像分成很多小块,这些小块被称为“tiles”(在 OpenCV中tiles的大小默认是8x8),然后再对每一个小块分别进行直方图均衡化。(所以在每一个的区域中,直方图会集中在某一个小的区域中)。
  2. 如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的 bin超过对比度的上限的话,就把其中的像素点均匀分散到其他bins 中,然后在进行直方图均衡化。

  3. 最后,为了去除每一个小块之间的边界,再使用双线性差值,对每一小块进行拼接。
     

OpenCv API:

clahe = cv.createCLAHE(clipLimit, tileGridSize)
dst = clahe.apply(img)

参数:

  1. clipLimit:对比度限制,默认是40
  2. tileGridSize:分块的大小,默认为8*8

代码编写:

import cv2 as cv
import matplotlib.pyplot as plt
import numpy as np

src = cv.imread("E:\\qi.png", 0)  # 直接以灰度图方式读入
img = src.copy()

# 创建一个自适应均衡化的对象,并应用于图像
clahe = cv.createCLAHE(clipLimit=3.0, tileGridSize=(8, 8))
dst = clahe.apply(img)

# 显示图像
fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(10, 8), dpi=100)
axes[0].imshow(img, cmap=plt.cm.gray)
axes[0].set_title("原图")
axes[1].imshow(dst, cmap=plt.cm.gray)
axes[1].set_title("自适应均衡化后的图像")
plt.show()

猜你喜欢

转载自blog.csdn.net/qq_45832961/article/details/122374068