书本中接下来介绍了一些基本更加高级概念和操作: 直方图,归一化,平滑化,模糊化,边缘检测等.
4.Histogram(直方图):
直方图:描述了在图像中像素值大小的分布状态.
计算函数:cv2.calcHist(images,channels,mask,histSize,ranges)
channels:是一个列表,表示通道索引.如要计算灰度图的直方图,则该参数为[0],如果要计算三个通道的则为[0,1,2]
mask:若给定了mask,则计算在mask中的直方图,若为None则计算全图的
histSize:也是一个列表,表示每一个通道我们需要使用的区间大小,比如灰度图的,可以使用[32],则以32以及倍数划分了256.
ranges:像素值大小的范围,如RGB的为[0,255]
灰度图像的直方图
image = cv2.imread(args["image"])
image_gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([image], [0], None, [256], [0,255])
plt.figure()
plt.title("the histogram of gray image")
plt.xlabel("the bins")
plt.ylabel("number of Pixels")
plt.xlim([0,256])
plt.plot(hist)
plt.show()
颜色图的直方图
channels = cv2.split(image)
colors = ("b", "g", "r")
for (channel, color) in zip(channels, colors):
hist = cv2.calcHist([channel], [0], None, [256], [0, 256])
plt.plot(hist, color = color)
plt.xlim([0, 256])
plt.show()
同时计算多通道的直方图,举个例子说明一下它的意义,我们需要知道一张图里面有多少个像素点是B=20,G=30,这个时候就需要计算B和G通道的直方图.
channels = cv2.split(image)
fig = plt.figure()
ax = fig.add_subplot(131)
hist = cv2.calcHist((channels[1], channels[0]), (0, 1), None,
[32, 32], [0, 256, 0, 256])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for G and B")
plt.colorbar(p)
ax = fig.add_subplot(132)
hist = cv2.calcHist((channels[1], channels[2]), [0, 1], None,
[32, 32], [0, 256, 0, 256])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for G and R")
plt.colorbar(p)
ax = fig.add_subplot(133)
hist = cv2.calcHist((channels[0], channels[2]), [0, 1], None,
[32, 32], [0, 256, 0, 256])
p = ax.imshow(hist, interpolation = "nearest")
ax.set_title("2D Color Histogram for B and R")
plt.colorbar(p)
对于计算三通道的直方图也是类似的,意义也是类似于计算二通道的.
直方图均衡化:提高全图的对比度,直方图均衡化用于在灰度图之中,
实现该过程使用cv2.equalizeHist(image)
image = cv2.imread(args["image"])
image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
eq = cv2.equalizeHist(image)
cv2.imshow("Histogram Equalization", np.hstack([image, eq]))
可以看出均衡化之后,亮的更加亮了,暗的更加暗了.
直方图加掩模:计算在感兴趣的mask之中的直方图
#define a function to draw the histogram graph
def plot_histogram(image, title, mask = None):
chans = cv2.split(image)
colors = ("b", "g", "r")
plt.figure()
plt.title(title)
plt.xlabel("Bins")
plt.ylabel("# of Pixels")
for (chan, color) in zip(chans, colors):
hist = cv2.calcHist([chan], [0], mask, [256], [0, 256])
plt.plot(hist, color = color)
plt.xlim([0, 256])
mask = np.zeros(image.shape[0:2], dtype = "uint8")
cv2.rectangle(mask, (15, 15), (130, 100), 255, -1)
cv2.imshow("Mask", mask)
masked = cv2.bitwise_and(image, image, mask = mask)
cv2.imshow("Applying the Mask", masked)
cv2.waitKey(0)
plot_histogram(image, "Histogram for Masked Image", mask = mask)
这是天空部分的三个通道的直方图