12-直方图
灰度直方图
灰度直方图是表示图像中灰度值分布的直方图,标绘了图像中每个灰度值的像素数
横坐标:图像中各个像素点的灰度级
纵坐标:具有该灰度级的像素个数
归一化直方图
归一化直方图是表示图像中灰度值分布的概率之和等于1
横坐标:图像中各个像素点的灰度级
纵坐标:出现这个灰度级的概率
需要注意的,直方图术语:
dims:需要统计的特征的数目。当dims=1时,表示我们仅统计灰度值
bins:每个特征空间子区段的数目
range:每个特征空间的取值范围
使用python中matplotlib库来绘制直方图
import matplotlib.pyplot as plt
函数hist(数据源,像素级),根据数据源和像素级绘制直方图
其中,数据源必须是一维数组图像;像素级一般是256,指[0,255]
通过ravel()函数,将多维的数组,转化为一维的形式
# 将绘制的图显示在窗口 %matplotlib qt5 import cv2 import matplotlib.pyplot as plt img = cv2.imread(r"image\boat.jpg",cv2.IMREAD_COLOR) # 彩色图像转化为灰度图 img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # ravel()函数,将二维的图像,转化为一维的数组 img_2 = img.ravel() cv2.imshow("original",img) # 1.设置rc参数显示中文标题,设置字体为SimHei显示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 2.绘制灰度直方图 plt.hist(img_2,256) plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("灰度直方图") # 3.显示灰度直方图 plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
使用opencv来绘制统计直方图
hist = cv2.calcHist(images,channels,mask,histSize,ranges[,accumulate])
返回的hist直方图,相当于纵坐标的值,也就是具有灰度级像素个数的二维数组
1>channels:指定通道
通道的编号需要用中括号括起来,当输入图像是灰度图时,对应的通道是[0];当输入图像是彩色图像时,通道[0],[1],[2]分别对应B,G,R
2>mask:掩码图像
统计整幅图像的直方图,设为None;统计图像某一部分的直方图时,需要掩码图像
3>histSize:BINS的数量
每个特征空间子区段的数目,一般是256,需要用中括号括起来
4>range:每个特征空间的取值范围
一般是[0,255],需要用中括号括起来
5>accumulate:累计标识(可选参数)
默认值为False,如果被设置为True,则直方图在开始分配时不会被清零。也就是说计算一组图像的直方图
import cv2 import numpy as np # 输入图像是灰度图 img = cv2.imread(r"image\boat.bmp",cv2.IMREAD_GRAYSCALE) # 绘制统计直方图 hist = cv2.calcHist([img],[0],None,[256],[0,255]) print("统计直方图的类型:",type(hist)) print("统计直方图的大小:",hist.size) print("统计直方图的形状:",hist.shape)
import matplotlib.pyplot as plt
(如果是彩色图像,需要分别绘制BGR三个通道的直方图)
# 将绘制的图显示在窗口 %matplotlib qt5 import cv2 import matplotlib.pyplot as plt # 输入图像时彩色图像 img = cv2.imread(r"image\girl.bmp",cv2.IMREAD_COLOR) cv2.imshow("original",img) # 绘制统计直方图 histb = cv2.calcHist([img],[0],None,[256],[0,255]) histg = cv2.calcHist([img],[1],None,[256],[0,255]) histr = cv2.calcHist([img],[2],None,[256],[0,255]) # 1.设置rc参数显示中文标题,设置字体为SimHei显示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 2.绘制灰度直方图 plt.plot(histb,color="b") plt.plot(histg,color="g") plt.plot(histr,color="r") plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("统计直方图") # 3.显示灰度直方图 plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
使用掩膜mask的直方图
图像掩模一般用来对处理的图像(全部或者局部)进行遮挡,来控制图像处理的区域或处理过程
生成掩膜mask图像,一般需要两步:
1> mask = np.zeros(image.shape,np.uint8)
第一步,建立与原图一样大小的mask图像,并将所有像素初始化为0,也就是一张全黑色的图
2> mask[200:400,200:400] = 255
第二步,将mask图中指定区域的所有像素值设置为255,也就是将整个指定区域变成了白色
还是使用opencv来绘制统计直方图
hist = cv2.calcHist(images,channels,mask,histSize,ranges[,accumulate])
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r"image\boat.bmp",cv2.IMREAD_GRAYSCALE) cv2.imshow("original",img) # 生成掩膜mask图像 mask = np.zeros(img.shape,np.uint8) mask[200:400,200:400] = 255 cv2.imshow("mask",mask) # 绘制统计直方图 hist = cv2.calcHist([img],[0],mask,[256],[0,255]) # 1.设置rc参数显示中文标题,设置字体为SimHei显示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 2.绘制灰度直方图 plt.plot(hist) plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("统计直方图") # 3.显示灰度直方图 plt.show() cv2.waitKey(0) cv2.destroyAllWindows()
直方图均衡化
直方图均衡化是一种简单有效的图像增强技术,将图像的直方图分布变成近似均匀分布,从而增强图像的对比度,使色彩细节更丰富,多用于车牌识别、人脸识别场景
直方图均衡化的过程:
1> 计算累计直方图
2> 将累计直方图进行区间转换
使用opencv绘制直方图均衡化
dst = cv2.equalizeHist(src)
其中,src是源图像,dst是目标图像(处理结果)
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r"image\equ.bmp",cv2.IMREAD_GRAYSCALE) # 设置rc参数显示中文标题,设置字体为SimHei显示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 绘制灰度直方图 # ravel()函数,将二维的图像,转化为一维的数组 plt.hist(img.ravel(),256) plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("灰度直方图") # 绘制均衡直方图 # plt.figure()函数,创建自定义图像 plt.figure() equ = cv2.equalizeHist(img) plt.hist(equ.ravel(),256) plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("均衡直方图") # 3.显示灰度直方图 plt.show() cv2.imshow("original",img) cv2.imshow("result",equ) cv2.waitKey(0) cv2.destroyAllWindows()
需要注意:也可以通过plt.subplot()函数,绘制多个子窗口
import matplotlib.pyplot as plt
plt.subplot(nrows,ncols,plot_number)
其中,nrows是行数,ncols是列数,plot_number是窗口序号
# 将绘制的图显示在窗口 %matplotlib qt5 import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread(r"image\equ.bmp",cv2.IMREAD_GRAYSCALE) # 设置rc参数显示中文标题,设置字体为SimHei显示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 通过plt.subplot()绘制一个一行两列的子窗口 # 1.绘制灰度直方图 plt.subplot(1,2,1) plt.hist(img.ravel(),256) plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("灰度直方图") # 2.绘制均衡直方图 plt.subplot(1,2,2) equ = cv2.equalizeHist(img) plt.hist(equ.ravel(),256) plt.xlabel("灰度级") plt.ylabel("像素个数") plt.title("均衡直方图") # 3.显示灰度直方图 plt.show()
需要注意:也可以通过plt.imshow()函数,显示opencv读入的图像
import matplotlib.pyplot as plt
plt.imshow(x,cmap)
其中,x是要绘制的图像,cmap是颜色图谱
# 将绘制的图显示在窗口 %matplotlib qt5 import cv2 import numpy as np import matplotlib.pyplot as plt # 读取一个彩色图像 img = cv2.imread(r"image\girl.bmp",cv2.IMREAD_COLOR) # 彩色图像转换灰度图像 img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) # 设置rc参数显示中文标题,设置字体为SimHei显示中文 plt.rcParams['font.sans-serif'] = 'SimHei' plt.rcParams['axes.unicode_minus'] = False # 通过plt.subplot()绘制一个一行两列的子窗口 # 1.显示彩色图像 plt.subplot(1,2,1) # 拆分通道 b,g,r = cv2.split(img) # 合并通道 rgb_img = cv2.merge([r,g,b]) plt.imshow(rgb_img) plt.title("彩色图像") # 关闭坐标轴 plt.axis("off") # 2.显示灰度图像 plt.subplot(1,2,2) plt.imshow(img_gray,cmap=plt.cm.gray) plt.title("灰度图像") # 关闭坐标轴 plt.axis("off") # 3.显示灰度直方图 plt.show()