histogram
Histogram definition
hist = cv2.calcHist(images, channels, mask, histSize, ranges, …) # hist is a 256*1 matrix, where each value represents the number of pixels corresponding to a gray value
- images: The original image format is uint8 or float32; when passing in the function, brackets should be used, such as [img]
- channels: Also enclosed in square brackets, it will tell the function to count the image channels of the histogram; if the input is a grayscale image, its value is [0], if the input is a color image, its value can be It is [0], [1], [2], corresponding to BGR respectively
- mask: mask image, if the statistics are the whole image, its value is None
- histSize: The number of BINs, which should also be enclosed in square brackets
- ranges: pixel value range, generally [0, 256], left closed and right open
plt.hist(x, bins=None, range=None, …) # Histogram, a special histogram
- x: The data required for the histogram must be a one-dimensional array. Multi-dimensional arrays can be flattened before drawing
- bins: the number of columns in the histogram, that is, the number of groups to be divided into, the default is 10
- range: tuple or None, if None, the default is (x.min(), x.max()), which is the range of the x-axis
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 operation
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()
Histogram equalization
The pixel distribution of image A is as follows:
Equalization process:
grayscale value | Number of pixels | probability | cumulative probability | The gray value after mapping according to the function | Rounding |
---|---|---|---|---|---|
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 |
The pixel distribution of image B obtained after equalization is as follows:
equalization effect
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()
Adaptive Histogram Equalization
The global equalization of equalizeHist also has some problems. Due to the improvement of the overall brightness, the details of the local image may be blurred. Therefore, sometimes we need to perform a local equalization operation of blocks, which is called an adaptive histogram. equalization.
clahe = cv2.createCLAHE(clipLimit=None, tileGridSize=None) # adaptive histogram equalization
cla = clahe.apply(img)
- clipLimit: contrast limit threshold
- tileGridSize: The input image will be split into rectangular blocks of equal size, tileGridSize defines the number of blocks in rows and columns
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()