一、直方图
简介:
是图像中像素强度分布的图形表达方式。
使用直方图对我们图像的像素点进行统计操作。像素点的区间0-255也就是直方图的横坐标,像素点的个数也就是直方图的纵坐标。
作用:例如视频中。通过标记帧和帧之间显著的边缘和颜色的统计变化,来检测视频中场景的变换。

python
cv2.calcHist(images, channels, mask, histSize, ranges)
参数介绍:
images:
输入图像,必须用方括号包裹 (即使只有 1 张图)。示例:[img]
注意:图像需为 np.ndarray 类型,支持灰度图 / 彩色图
channels:
指定计算直方图的通道索引:
灰度图:只有 1 个通道,传 [0]
彩色图(BGR):蓝色 = 0、绿色 = 1、红色 = 2
mask:
掩码图像:
None:计算整张图的直方图
自定义掩码:仅计算掩码中值为 255 的区域的直方图
注意:掩码尺寸必须和输入图像完全一致,且为单通道 8 位图像
histSize:
直方图的 "分箱数"(bin 数量),即把像素值范围分成多少份
分箱数越多,直方图越精细;越少则越粗略
ranges:
像素值的取值范围: [0,256](注意是左闭右开,实际包含 0-255)
python
import matplotlib.pyplot as plt
imporrt cv2
shan = cv2.imread('../data/shan.jpeg')
#将图像转换为一维数组
#这里使用了numpy的ravel 函数,将多维数组拉成一维数组。
a = shan.ravel()
#绘制直方图
plt.hist(a,bins=256) #使用matplotlib 的hist 函数绘制直方图。
#参数解释:
#- a:一维数组,即图像的像素值组成的数组。
#-bins=256:指定直方图的条数,即灰度级的数量。
plt.show()
#显示直方图
shan_hist = cv2.calcHist([shan],[0],None,[16],[0,256])
plt.plot(shan_hist) #使用calcHist的值绘制曲线图
plt.show()
shan2 = cv2.imread('../data/shan.jpeg')
color = ('b','g','r')
for i,col in enumerate(color):
hist = cv2.calcHist([shan2],[i],None,[256],[0,256])
plt.plot(hist,color=col)
plt.show()
绘制这张图像所有像素值的整体直方图
python
import matplotlib.pyplot as plt
shan = cv2.imread('../data/shan.jpeg')
#将图像转换为一维数组
#这里使用了numpy的ravel 函数,将多维数组拉成一维数组。
a = shan.ravel()
#绘制直方图
plt.hist(a,bins=256) #使用matplotlib 的hist 函数绘制直方图。

表示灰度图,将像素分为16个区间
python
shan_hist = cv2.calcHist([shan],[0],None,[16],[0,256])
plt.plot(shan_hist) #使用calcHist的值绘制曲线图
plt.show()

三个颜色通道所呈现的直方图统计
python
shan2 = cv2.imread('../data/shan.jpeg')
color = ('b','g','r')
for i,col in enumerate(color):
hist = cv2.calcHist([shan2],[i],None,[256],[0,256])
plt.plot(hist,color=col)
plt.show()

掩膜的应用
1**.什么是掩膜**:掩膜是用选定的图像、图形或物体,对要处理的图像进行遮挡,来控制图像处理的区域,在数字图像处理中,通常使用二维矩阵进行掩膜,掩膜是由0和1组成的一个二进制图像,利用该掩膜对要处理的图像进行掩膜,其中值为1的区域被处理,0区域被屏蔽,不会处理
2.掩膜的作用:我们使用cv.calcHist()查找完整图像的直方图,当要查找图像某些区域的直方图,只需要在查找直方图的区域上创建一个白色的掩膜图像,否则创建黑色,将其作为掩码mask传递
为了对输入的图像的指定部分进行操作,需要通过mask来创建指定部分的全零数组, 再通过cv2.bitwise_and()来进行与操作从而实现获得指定区域的图像
python
import cv2
import pandas as pd
shan = cv2.imread('../data/shan.jpeg')
cv2.imshow("shan",shan)
cv2.waitKey(0)
mask = np.zeros(shan.shape[:2],np.uint8)
mask[50:250,100:200] = 255
cv2.imshow("mask",mask)
cv2.waitKey(0)
'''
cv2.bitwise-and():对图像(灰度图像或彩色图像均可)每个像素值进行二进制"与"操作,1&1=1,1&0=0,0&1=0,0&0=0
bitwise_and(src1,src2,dst=None,mask=None)参数:
src1、src2:为输入图像或标量,标src1和src2相与。
dst:可选输出变量,如果需要使用非None则要先定义,且其大小与输入变量相同
mask:图像掩膜,可选参数,用于指定要更改的输出图像数组的元素,mask为0的值,srC1和Src2相与的值都为0.
非O的值,为src1和src2相与的值。
'''
shan_mask = cv2.bitwise_and(shan,shan,mask=mask)
cv2.imshow("shan_mask",shan_mask)
cv2.waitKey(0)
'''-----------------------'''
mask_hist_mask = cv2.calcHist([shan],[0],mask,[256],[0,256])
plt.plot(mask_hist_mask)
plt.show()

二、直方图均衡化
简介:
如果一幅图像整体很亮,那所有的像素值的取值个数应该都会很高。需要将此图像的直方图做一个横向拉伸,就可以扩大图像像素值的分布范围,提高图像的对比度,这就是直方图均衡化(通过将图像的像素值分布均匀化来实现这一目标)

python
cv2.equalizeHist(image)
参数:
image:
输入图像:必须是8 位单通道灰度图(不能是彩色图、浮点图、16 位图)
输入必须是 uint8 类型(0-255),否则报错;不支持直接处理彩色图的单通道
输出结果:
输出图像和输入图像尺寸、数据类型完全一致(np.ndarray(8 位单通道数组))
python
import cv2
import numpy as np
import matplotlib.pyplot as plt
black = cv2.imread('../data/hei.jpg',cv2.IMREAD_GRAYSCALE)
plt.hist(black.ravel(),bins=256) #numpy中的ravel将数组多维度拉成一维数组
plt.show()
black_equalize = cv2.equalizeHist(black)
plt.hist(black_equalize.ravel(),bins=256)
plt.show()
res = np.hstack((black,black_equalize)) #hstack:横向拼接,将多个数组按水平方向(列顺序)堆叠成一个新的数组。 vstack:纵向拼接
cv2.imshow('black_equalize',res)
cv2.waitKey(0)

三、自适应的直方图均衡化
简介:
直方图均衡化中,考虑的是图像全局的对比度,许多情况下,会由于均衡化而丢失许多信息,为了解决此问题,需要使用自适应的直方图均衡化,此时,整幅图片被分成许多小块,称为tiles(在OpenCV中tiles的大小默认是8x8),然后再对每一个小块分别进行直方图均衡化。如果有噪声的话,噪声会被放大。为了避免这种情况的出现要使用对比度限制。对于每个小块来说,如果直方图中的bin超过对比度的上限的话,就把其中的像素点均匀分散到其他bins中,然后在进行直方图均衡化。最后使用双线性差值,对每一小块进行拼接。
python
cv2.createCLAHE(clipLimit, tileGridSize)
参数介绍:
clipLimit:对比度限制阈值(默认值40.0)(float型)
作用:限制每个小区域(tile)的直方图超出该阈值的部分,避免过度增强噪声;
值越小,对比度增强越温和(噪声越少);值越大,增强越明显(但易放大噪声)
tileGridSize:图像分块尺寸(将图像划分为多少个小区域)(默认值为(8,8))(tuple型)
作用:将整幅图像分成 tileGridSize[0]×tileGridSize[1] 个独立小块,分别做均衡化;
分块越多,细节增强越细腻,但计算量稍大;分块过少会丢失局部特征,效果接近普通均衡化
使用逻辑 :先创建 CLAHE 处理器,再调用 apply() 处理图像(输入输出均为 8 位单通道灰度图)
python
import cv2
import numpy as np
import matplotlib.pyplot as plt
clahe = cv2.createCLAHE(clipLimit=12,tileGridSize=(10,10))
black_clahe = clahe.apply(black)
res = np.hstack((black,black_equalize,black_clahe))
cv2.imshow( 'black_equalize',res)
cv2.waitKey(0)
