直方图处理

直方图从图像内部灰度级的角度对图像进行表述,它包含十分丰富而重要的信息,从直方图的角度对图像进行处理,可以到达增强图像显示效果的目的。

一:直方图的含义

1、 从统计的角度讲,直方图是图像内灰度值的统计特性和灰度图像值之间的函数,直方图统计图像内的各个灰度级出现的次数,从直方图的图像上观察,横坐标是图像中各像素点的灰度级,纵坐标是具有该灰度级(像素值)的像素个数。
2、有时,为了便于表示,也会采用归一化直方图,在归一化直方图中,横坐标仍然表示灰度级,纵坐标表示灰度级出现的频率
3、在opencv中,要注意三个概念
(1)DIMS:在绘制直方图时,收集的参数的数量,一般情况下,直方图中收集的数据都是灰度级,因此该值为1
(2)RANGE:表示统计的灰度级范围,一般为[0,255],0为黑色,255表示白色
(3)BINS:参数子集的数目,在处理数据的过程中,有时需要将众多的数据划分为若干个组,再进行分析。

二:绘制直方图

1、使用Numpy绘制直方图

模块matplotlib.pylot提供了类似matlab绘图方式的框架,可以使用其中的matplotlib.pylot.hist()绘制直方图。

matplotlib.pyplot.hist(X,BINS)
X:数据源,必须为一维的,需要使用ravel()函数将二维图像处理为一维数据后方能使用
BINS:表示灰度级的分组情况

##############如下所示#########

import cv2
import matplotlib.pyplot as plt

img=cv2.resize(cv2.imread(r"img/5.jpg"),(400,400))
cv2.imshow("img",img)
plt.subplot(2,1,1)
plt.hist(img.ravel(),256)
plt.subplot(2,1,2)
plt.hist(img.ravel(),16)#将灰度级分16组显示
plt.show()
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
2、使用opencv绘制直方图

hist=cv2.calcHist(image,channels,mask,histSize,ranges,accumulate)
hist:返回的直方图,是一个一维数组,数组内的元素是各个灰度级的像素个数
images:原始图像,该图像需要使用"[]"括起来
channels:指定通道编号,需要用"[]"括起来,如果输入图像是单通道灰度图,该参数的值就是[0],
对于彩色图像,他的值可以是[0],[1],[2],分别对应通道的B,G,R
mask:掩模图像。确定需要统计直方图的范围,当统计整幅图时,将其设置为None
histSize:BINS的值,该只需要用"[]"括起来
ranges:像素值范围
accumulate:是否累计,默认Flase,若为True,则直方图在开始计算时不会被清零,计算的是多个直方图的累计结果,一般用于对一组图像计算直方图。

3、plot()函数的使用

使用matplotlib.pylot模块内的plot()函数,可以将函数cv2.calcHist()的返回值绘制为图像直方图。
import matplotlib.pyplot as plt

a=[2,7,8,9,5]
b=[4,7,2,1,6]
plt.plot(a,b,color="y")
plt.plot(a,color="r")#若x轴省略,则默认为自然数序列x=[0,1,2,...,n-1]
plt.plot(b,color="g")
plt.show()

在这里插入图片描述
4、绘制统计直方图

import cv2
import matplotlib.pyplot as plt

img=cv2.imread("img/13.jpg")
histb=cv2.calcHist([img],[0],None,[256],[0,255])#B通道
histg=cv2.calcHist([img],[1],None,[256],[0,255])
histr=cv2.calcHist([img],[2],None,[256],[0,255])
plt.plot(histb,color="b")
plt.plot(histg,color="g")
plt.plot(histr,color="r")
plt.show()

在这里插入图片描述
5、使用掩模绘制直方图

当在一个函数F中使用了掩模时,就意味着要先将参与运算的图像与掩模图像进行按位与运算,得到掩模运算结果,然后再将掩模运算结果作为函数F的参数完成函数F指定的运算。

import cv2
import numpy as np
import matplotlib.pyplot as plt

img=cv2.resize(cv2.imread("img/13.jpg",0),(400,400))
cv2.imshow("img",img)

mask=np.zeros(img.shape,np.uint8)
mask[100:300,100:300]=255
img1=cv2.bitwise_and(img,mask)
cv2.imshow("img1",img1)
histImage=cv2.calcHist([img],[0],None,[256],[0,255])
#添加掩模
histMI=cv2.calcHist([img],[0],mask,[256],[0,255])
plt.plot(histImage,color="r")
plt.plot(histMI,"b")
plt.show()
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
三:直方图均衡化

如果一幅图像拥有全部可能的灰度级,并且像素值的灰度均匀分步,那么这幅图像就具有高对比度和多变的灰度色调,灰度级丰富且覆盖范围较大,在外观上,这样的图像具有更丰富的色彩,不会过暗或过亮。

直方图均衡化的目的主要是将原始图像的灰度级均匀的映射到整个灰度级范围内,得到一个灰度级分布均匀的图像,这种均衡化即实现了灰度值统计上的概率均衡,也实现了人类视觉系统(hsv)上的视觉均衡。

1、直方图均衡化原理
(1)、计算累计直方图
(2)、对累计直方图进行区间转换

如:图A有8个灰度级,范围为[0,7],其统计直方图如下:
在这里插入图片描述
则归一化直方图(各个灰度级出现的概率):
在这里插入图片描述
累计直方图:
在这里插入图片描述
在累计直方图的基础上,对原有灰度级空间进行转换,可以在原有范围内对灰度级实现均衡化,也可以在更广泛的灰度空间范围内对灰度级实现均衡化。

A:在原有范围内实现均衡化

在原有范围内实现直方图均衡化时,用当前灰度级的累计概率乘以当前灰度级的最大值(如上为7),对结果进行四舍五入(灰度级一般都为整数),得到新的灰度级,并作为均衡化结果。
在这里插入图片描述
则均衡化之后的每个灰度级的像素个数如下(将原来的不同灰度级下的像素个数对应过来即可):
在这里插入图片描述
直方图均衡化前后的对比如下所示:
在这里插入图片描述
从上可以看出,均衡化之前,灰度级在0-3之间的像素个数为29个,4-7之间的像素为20个,而均衡化之后,0-3之间的像素为24个,4-7之间的为25个,故均衡化之后的直方图的灰度级在整个灰度空间分布更加均匀(综合考虑统计概率和HSV的结果)。

B:在更广泛的范围内实现均衡化

在更广泛的范围内实现直方图均衡化时,用当前灰度级的累计概率乘以更广泛范围灰度级的最大值,得到新的灰度级,并作为均衡化的结果。例如:将灰度空间扩展到[0,255]共256个灰度级,就必须将原灰度级的累计概率乘以255,得到新的灰度级。如下表原灰度级在[0,7]内的图像A在新的灰度空间[0,255]内的均衡化之后的灰度级。
在这里插入图片描述
2、直方图均衡化处理

dst=cv2.equalizeHist(src)
src:8为单通道原始图像
dst:直方图均衡化处理的结果

##########如下所示########

import cv2
import matplotlib.pyplot as plt

img=cv2.resize(cv2.imread(r"img/13.jpg",0),(400,400))
equ=cv2.equalizeHist(img)
cv2.imshow("img",img)
cv2.imshow("equ",equ)
plt.subplot(2,1,1)
plt.hist(img.ravel(),256)
plt.title("Histogram of original image")
plt.subplot(2,1,2)
plt.hist(equ.ravel(),256)
plt.title("Histogram after equalization")
plt.show()
cv2.waitKey()
cv2.destroyAllWindows()

在这里插入图片描述
由直方图可以看出,在进行均衡化之前,像素值集中在右侧(密度相似,右侧的纵坐标更高),而均衡化之后,纵坐标高的相对稀疏,低的相对密集,而人眼并不能明显感到像素值的细微差别,我们可以将相近的像素看作同一像素值,这样直方图内的灰度级的分布就比较均匀了。

四:pyplot模块

1、subplot()函数

matplotlib.pyplot.subplot(nrows,ncols,index)
nrows:行数
ncols:列数
index:窗口序号

窗口是按行方向排列的,且窗口序号是从”1“开始的,若行列以及窗口序号都小于10,则可以省略中间的逗号。

2、imshow()函数

matplotlib.pyplot.imshow(X,cmap=None)
X:图像信息,可以是各种形式的数值
cmap:色彩空间,该值是可选值,默认为null,即使用RGB(A)色彩空间。使用时注意与需要展示图
片的色彩空间对应。否则图片不会正确显示。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值