直方图实例详解(颜色直方图、灰度直方图)
直方图实例详解(颜色直方图、灰度直方图)
直方图是图像处理中一种非常重要的工具,它可以从灰度级的角度对图像进行表述,帮助我们了解图像的整体灰度分布。本文将详细介绍颜色直方图和灰度直方图的概念、使用方法以及绘制实例,帮助读者掌握这一重要工具。
直方图的概念
在图像处理中,直方图是一种能快速描述图像整体像素值分布的统计信息图表。它统计的是图像内各个灰度级出现的次数,可以清晰了解图像的整体灰度分布,便于后期依据直方图处理图像。
颜色直方图
颜色直方图定义
颜色直方图是一种能快速描述图像整体像素值分布的统计信息图表。X轴为像素值,Y轴为个数。颜色直方图只能描述颜色的分布,不能描述数据几何上的信息。
颜色直方图使用方法
绘制颜色直方图可以使用numpy的histogram()函数得到直方图的信息,再用matplotlib绘制出图像。其中,hist函数只支持一维的数组,通常需要使用ravel()函数将图像处理为一维数据源。
绘制颜色直方图
绘制普通颜色直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread(r'girl2aa.jpg') #读入图像
hist, bins = np.histogram(img.ravel(), bins=50)
plt.hist(img.ravel(), bins=50);
cv2.imshow('img', img)
cv2.waitKey(0)
plt.show()
绘制灰度图像直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img_gray = cv2.imread(r'girl2aaa.jpg', cv2.IMREAD_GRAYSCALE) #读入灰度图像
hist, bins = np.histogram(img_gray.ravel(), bins=50)
plt.hist(img_gray.ravel(), bins=50);
cv2.waitKey(0)
plt.show()
绘制彩色图像直方图
彩色图像有三个通道,分别绘制。可以看到每个通道上像素的分布情况,分析出原图中哪种颜色比较多。
import cv2
import matplotlib.pyplot as plt
img_bgr_data = cv2.imread(r'girl2aaa.jpg')
plt.figure(figsize=(15, 5)) #设置画布的大小
# B通道 直方图
ax1 = plt.subplot(131)
ax1.hist(img_bgr_data[:, :, 0].ravel(), bins=50, color='b')
# G通道 直方图
ax2 = plt.subplot(132)
ax2.hist(img_bgr_data[:, :, 1].ravel(), bins=50, color='g')
# R通道 直方图
ax3 = plt.subplot(133)
ax3.hist(img_bgr_data[:, :, 2].ravel(), bins=50, color='r')
cv2.waitKey(0)
plt.show()
不同亮度图片直方图对比图
彩色图像直方图(绘制在同一张图)
import cv2
import matplotlib.pyplot as plt
import numpy as np
img = cv2.imread("cat1.jpg")
n_bins = 256
hist_range = [0, 256]
hists = []
channels = {0: "blue", 1:"green", 2: "red"}
for ch in channels:
hist = cv2.calcHist(
[img], channels=[ch], mask=None, histSize=[n_bins], ranges=hist_range
)
hist = hist.squeeze(axis=-1)
hists.append(hist)
def plot_hist(bins, hist, color):
centers = (bins[:-1] + bins[1:]) / 2
widths = np.diff(bins)
ax.bar(centers, hist, width=widths, color=color)
bins = np.linspace(*hist_range, n_bins + 1)
fig, ax = plt.subplots()
ax.set_xticks([0, 256])
ax.set_xlim([0, 256])
ax.set_xlabel("Pixel Value")
for hist, color in zip(hists, channels.values()):
plot_hist(bins, hist, color=color)
plt.show()
灰度直方图
灰度直方图定义
图像的灰度直方图描述了图像中灰度分布情况,能够很直观的展示出图像中各个灰度级所占的多少。很好地体现出图像的亮度和对比度信息:灰度图分布居中说明亮度正常,偏左说明亮度较暗,偏右表明亮度较高;狭窄陡峭表明对比度降低,宽泛平缓表明对比度较高。
灰度直方图函数
OpenCV 提供了函数 cv2.calcHist 可以计算直方图,Numpy 中的函数 np.bincount 也可以实现同样的功能。cv2.calcHist()函数有5个参数:images、channels、mask、histSize、ranges。
灰度直方图实例
绘制普通灰度直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('girl2a.jpg', 0) # 0表示灰度图
hist = cv2.calcHist([img], [0], None, [256], [0, 256])
plt.hist(img.ravel(),256);
cv2.waitKey(0)
plt.show()
绘制多通道图像直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('cat1.jpg')
color = ('b','g','r')
for i,col in enumerate(color):
histr = cv2.calcHist([img],[i],None,[256],[0,256])
plt.plot(histr,color = col)
plt.xlim([0,256])
cv2.imshow('img', img)
cv2.waitKey(0)
plt.show()
使用掩模绘制直方图
cv2.calcHist()函数,其中参数mask用于标识是否使用掩模图像,当使用掩模图像获取直方图时,仅获取mask指定区域的直方图。
绘制方形掩模图像及直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread(r'girl2a.jpg', cv2.IMREAD_GRAYSCALE)
mask = np.zeros(img.shape, np.uint8)
mask[90:300, 50:280] = 250
histimg = cv2.calcHist([img], [0], None, [256], [0, 255])
histmaskimg = cv2.calcHist([img], [0], mask, [256], [0, 255])
image = cv2.add(img, np.zeros(np.shape(img), dtype=np.uint8), mask=mask)
cv2.imshow("img", img)
cv2.imshow("image", image)
plt.subplot(1, 2, 1)
plt.subplot(1, 2, 2)
plt.plot(histimg)
plt.plot(histmaskimg)
cv2.waitKey(0)
plt.show()
绘制圆形掩模图像及直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread("girl2a.jpg")
Mask1 = np.zeros((img1.shape[0], img1.shape[1]), dtype=np.uint8)
Mask2 = Mask1.copy()
cv2.circle(Mask1, (150, 200), 110, (255, 255, 255), -1) # -1 实心
imgAddMask1 = cv2.add(img1, np.zeros(np.shape(img1), dtype=np.uint8), mask=Mask1) # 取圆
cv2.imshow("imgAddMask1", imgAddMask1)
hist = cv2.calcHist([imgAddMask1], [0], None, [256], [0, 256])
plt.hist(imgAddMask1.ravel(),256);
cv2.waitKey(0)
plt.show()
总结
本文介绍了计算机视觉里直方图的原理和应用。下篇文章将学习如何通过直方图调整图片效果。直方图均衡化是一种经典的图像处理算法,用以改善图像的亮度和对比度。