目录
一、灰度直方图概念
二、直接调用opencv的函数caclHist()
1、函数介绍
2、实例
(1)绘制全局直方图
(2)绘制局部的直方图
三、自定义函数进行灰度直方图的绘制
1、代码
2、结果
一、灰度直方图概念
灰度直方图是关于灰度级分布的函数,将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。其中,横坐标是灰度级,纵坐标是该灰度级出现的频率。
对图像中不同灰度级别出现的次数进行统计,统计后进行绘制直方图,横坐标表示灰度级别0-255,纵坐标表示每个灰度级别在图像中出现的次数,一般会对次数进行归一化,用每个灰度级出现的次数除以图像的像素总个数。
二、直接调用opencv的函数caclHist()
1、函数介绍
返回的是一个一维数组(256,1)
hist = cv2.calcHist([images],[channels],mask,histSize,ranges )
参数说明:
images:uint8或float32类型的原图像。用方括号表示,即“[img]”;
channels:计算直方图的通道索引,也在方括号中给出.例如,如果输入是灰度图像,则其值为[0].对于彩色图像,可以通过[0],[1]或[2]分别计算蓝色,绿色或红色通道的直方图.
mask:掩码,蒙版图像.要查找完整图像的直方图,它将显示为“无”.但是,如果要查找图像特定区域的直方图,则必须为其创建蒙版图像并将其作为蒙版.
histSize:灰度级的个数,这代表我们的BIN计数.需要在方括号中给出.对于满量程,我们通过[256].
ranges:这是像素值的范围的范围。通常,它是[0,256].
2、实例
(1)绘制全局直方图
获得上图的直方图,首先得先进行灰度化
import cv2
import numpy as np
import matplotlib.pyplot as plt
def image_calcuhist(imagepath):
img = cv2.imread(imagepath)#读取图片
img_shape = img.shape
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#灰度化
hist = cv2.calcHist([gray],[0],None,[256],[0,256])#计算灰度级别出现频率,返回的是一个(256,1)的数组
for i in range(hist.shape[0]):
hist[i] = hist[i]/(img_shape[0]*img_shape[1])#对获得的直方图数据进行归一化
return hist
if __name__ == '__main__':
x = np.linspace(0,255,256)#横坐标灰度级别
y = image_calcuhist("colorful_lena.jpg")#纵坐标值获取
plt.bar(x,y.ravel(),0.9,alpha=1,color='b')#通过matplotlib进行直方图的绘制
plt.show()#显示直方图
(2)绘制局部的直方图
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread("colorful_lena.jpg",0)
h,w = img.shape
#构建一个掩模,需要绘制直方图的局部图像区域的像素设置为255,其他部分设置为0
mask = np.zeros((h,w),np.uint8)
for i in range(0,int(h/2)):
for j in range(0,int(w/2)):
mask[int(h/4)+i,int(w/4)+j] = 255
#全幅图像的直方图
hist = cv2.calcHist([img],[0],None,[256],[0,256])
#局部的直方图
hist1 = cv2.calcHist([img],[0],mask,[256],[0,256])
x = np.linspace(0,255,256)
plt.plot(x,hist.ravel())
plt.plot(x,hist1.ravel())
plt.show()
cv2.imshow('',mask)
cv2.imshow('1',img)
cv2.waitKey(0)
蓝色线为全局直方图,橙色为局部直方图
三、自定义函数进行灰度直方图的绘制
1、代码
# 1 0-255 2 概率
# 本质:统计每个像素灰度 出现的概率 0-255 p
import cv2
import numpy as np
import matplotlib.pyplot as plt
def image_histdefinition(imagepath):
img = cv2.imread(imagepath)#读取图片
imgInfo = img.shape#获得图片的尺寸大小
height = imgInfo[0]
width = imgInfo[1]
# 灰度化
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
count = np.zeros(256,np.float) # 共256个,创建一个数组用于存放灰度级别出现的频率
#计算灰度级别频率
for i in range(0,height):
for j in range(0,width):
pixel = gray[i,j] # 获取灰度等级
index = int(pixel) # 强制类型转换
count[index] = count[index]+1
# 计算出现概率,即归一化
for i in range(0,255):
count[i] = count[i]/(height*width)
return count
if __name__ == '__main__':
# 绘图
x = np.linspace(0, 255, 256)
count = image_histdefinition('colorful_lena.jpg')
y = count
plt.bar(x, y, 0.9, alpha=1, color='b')
plt.show()
2、结果
两种方法得到的直方图是一样的,证明方法是可行的。