携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第23天,点击查看活动详情
灰度分析与变换
图像灰度分析是图像分析中最基本的内容,它使用各种图像灰度分析工具,提取图像或 ROI 区域内的灰度特征信息。基于对图像灰度的分析测量,可以实现最基本的机器视觉检测系统,如目标存在性检测系统等。
1 直方图介绍
直方图(histogram)是最基本的图像灰度分析工具。使用它不仅可以判断图像中是否包含可从背景中分割出的区域、图像的饱和度和对比度是否适合检测任务,还能确定应该如何对图像采集系统进行调整以获得较高质量的图像。
图像的直方图包含了丰富的图像信息,描述了图像的灰度级内容,反映了图像的灰度分布情况。图像的灰度直方图以图表的方式显示了图像中每个灰度级与其所对应像素数量的关系。图表的横坐标为灰度级,纵坐标是各个灰度级在图像中出现的频率。直方图是图像最基本的统计特征,其中像素数量可被看作灰度级的函数。从概率论的角度来看,灰度出现的频率可被看作其出现的概率,这样直方图就对应于概率密度函数(Probability Density Function,PDF),而概率分布函数就是直方图的累计和,即概率密度函数的积分。
要深刻理解直方图我们可以使用 Ubuntu 上的 Shotwell viewer 软件中 adjust 的可以先直观的的查看图片的直方图并可以调试相关参数。
- 第一行为曝光(Exposure)
- 第二行为饱和度(Saturation)
- 第三行为色度(Tint)
- 第四行为温度(Temperature)
- 第五行为阴影度(shadows)
- 第六行为亮度(Highlights)
我们可以调节这六个参数去观察直方图的变化去理解直方图的意义,例如我将亮度调节到最低此时直方图末尾将被抑制下去。
2 直方图绘制
OpenCV 提供了函数 cv2.calcHist() 用来计算图像的统计直方图,该函数能统计各个灰度级的像素点个数。利用 matplotlib.pyplot 模块中的 plot() 函数,可以将函数 cv2.calcHist() 的统计结果绘制成直方图。
函数原型:
cv2.calcHist(images, channels, mask, histSize, ranges, accumulate)
- 第一个参数 image 为原始图像,该图像需要使用必须用方括号括起来。
- 第二个参数 channels 为指定通道编号。通道编号需要用方括号括起来,如果输入图像是单通道灰度图像,该参数的值就是 [0]。对于彩色图像,它的值可以是 [0]、[1]、[2],分别对应通道 B、G、R。
- 第三个参数 Mask 为掩模图像,当统计整幅图像的直方图时,将这个值设为 None。当统计图像某一部分的直方图时,需要用到掩模图像。
- 第四个参数 histSize 表示这个直方图分成多少份(即多少个直方柱),BINS 的值是 256,需要使用“[256]” 作为此参数值。
- 第五个参数 ranges 表示直方图中各个像素的值,8 位灰度图像的像素值范围是 [0,255]。
- 第六个参数 accumulate 表示为累计(累积、叠加)标识,默认值为 False。如果被设置为 True,则直方图在开始计算时不会被清零,计算的是多个直方图的累积结果,用于对一组图像计算直方图。
要理解直方图,绕不开“亮度”这个概念。人们把照片的亮度分为 0 到 255 共 256 个数值,数值越大,代表的亮度越高。其中 0 代表纯黑色的最暗区域,255 表示最亮的纯白色,而中间的数字就是不同亮度的灰色。人们还进一步把这些亮度分为了 5 个区域,分别是黑色、阴影、中间调、高光和白色。
然后可以使用 matplotlib.pyplot 模块内的 plot() 函数,可以将函数 cv2.calcHist() 的返回值绘制为图像直方图。下面通过三个例子来学习 plot() 函数的基本使用方法。
1. 绘制灰度直方图
from matplotlib import pyplot as plt
import cv2
image = cv2.imread('/work/opencv/people2.png')
#图像直方图
hist = cv2.calcHist([image],[0],None,[256],[0,256])
plt.figure() #新建一个图像
plt.title("Grayscale Histogram") #图像的标题
plt.xlabel("Bins") #X轴标签
plt.ylabel("# of Pixels") #Y轴标签
plt.plot(hist) #画图
plt.xlim([0,256]) #设置x坐标轴范围
plt.show() #显示图像
2. 绘制彩色直方图
import cv2
from matplotlib import pyplot as plt
img = cv2.imread('/work/opencv/people2.png')
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])
plt.show()