直方图 & 直方图均衡化

直方图定义

hist = cv2.calcHist(images, channels, mask, histSize, ranges, …) # hist是一个256*1的矩阵,其中每一个值代表了一个灰度值对应的像素点数目

  • images:原图像格式为uint8或float32;当传入函数时应用中括号括起来,如[img]
  • channels:同样用中括号括起来,它会告诉函数要统计直方图的图像通道;如果传入的是灰度图,它的值就是[0],如果传入的是彩色图像,它的值可以是[0]、[1]、[2],分别对应着BGR
  • mask:掩膜图像,如果统计的是整幅图像,它的值就为None
  • histSize:BIN的数目,也应用中括号括起来
  • ranges:像素值范围,一般为[0, 256],左闭右开

plt.hist(x, bins=None, range=None, …) # 直方图,一种特殊的柱状图

  • x:直方图所需数据,必须是一维数组,多维数组可以先扁平化再作图
  • bins:直方图的柱数,即要分成的组数,默认为10
  • range:tuple or None,如果为None,则默认为(x.min(), x.max()),即x轴的范围
import cv2
import matplotlib.pyplot as plt

img = cv2.imread(r'F:/aixin.jpg', 0)  # 0表示灰度图
plt.hist(img.ravel(), 256)  # 横轴表示数值(这里是像素值),纵轴表示一个数值出现的次数;img.ravel()可以将二维矩阵img展平成一维数组
plt.show()

在这里插入图片描述

import cv2
import matplotlib.pyplot as plt

img = cv2.imread(r'F:/aixin.jpg')
color = ('b', 'g', 'r')

for i, col in enumerate(color):
    hist = cv2.calcHist([img], [i], None, [256], [0, 256])
    plt.plot(hist, col)
    plt.xlim([0, 256])

plt.show()

在这里插入图片描述

mask操作

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

img = cv2.imread(r'F:/aixin.jpg', 0)  # 0表示灰度图
mask = np.zeros(img.shape[:2], np.uint8)  # 创建一个与二维图像shape相同的0值矩阵
mask[350:700, 350:700] = 255  # 将mask的一部分赋值为255,[H, W]
masked_img = cv2.bitwise_and(img, img, mask=mask)  # 与操作

plt.subplot(1, 3, 1)
plt.axis('off')  # 设置无坐标
plt.title('source')
plt.imshow(img, 'gray')  # 以灰度方式呈现

plt.subplot(1, 3, 2)
plt.axis('off')
plt.title('mask')
plt.imshow(mask, 'gray')

plt.subplot(1, 3, 3)
plt.axis('off')
plt.title('masked_img')
plt.imshow(masked_img, 'gray')

plt.show()

在这里插入图片描述

hist_full = cv2.calcHist([img], [0], None, [256], [0, 256])
hist_mask = cv2.calcHist([img], [0], mask, [256], [0, 256])

plt.plot(hist_full, 'b')
plt.plot(hist_mask, 'g')

plt.show()

在这里插入图片描述

直方图均衡化

图像A的像素分布如下所示:

在这里插入图片描述

均衡化过程:

灰度值 像素个数 概率 累积概率 根据函数映射后的灰度值 取整
50 4 0.25 0.25 0.25*(255-0)=63.75 64
128 3 0.1875 0.4375 0.4375*(255-0)=111.5625 112
200 5 0.3125 0.75 0.75*(255-0)=191.25 191
255 4 0.25 1 1*(255-0)=255 255

均衡化后得到的图像B的像素分布如下所示:

在这里插入图片描述

均衡化效果

import cv2
import matplotlib.pyplot as plt

img = cv2.imread(r'F:/aixin.jpg', 0)  # 0表示灰度图
equ = cv2.equalizeHist(img)  # 均衡化

plt.subplot(1, 2, 1)
plt.title('source')
plt.hist(img.ravel(), 256)

plt.subplot(1, 2, 2)
plt.title('equalized')
plt.hist(equ.ravel(), 256)

plt.show()

在这里插入图片描述

res = cv2.hconcat((img, equ))

cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

自适应直方图均衡化

equalizeHist这种全局的均衡化也会存在一些问题,由于整体亮度的提升,可能会使得局部图像的细节变得模糊,因此有时我们需要进行分块的局部均衡化操作,称之为自适应直方图均衡化。

clahe = cv2.createCLAHE(clipLimit=None, tileGridSize=None) # 自适应直方图均衡化
cla = clahe.apply(img)

  • clipLimit:对比度限制阈值
  • tileGridSize:输入图像将被分割成大小相等的矩形块,tileGridSize定义行和列中的块数
img = cv2.imread(r'F:/aixin.jpg', 0)  # 原图
equ = cv2.equalizeHist(img)  # 均衡化(全局均衡化)
clahe = cv2.createCLAHE(clipLimit=2, tileGridSize=(8, 8))  # 自适应均衡化(分块均衡化)
cla = clahe.apply(img)

res = cv2.hconcat((img, equ, cla))

cv2.namedWindow('image', cv2.WINDOW_NORMAL)
cv2.imshow('image', res)
cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_48158964/article/details/131722343