在日常做CV的过程中,慢慢的就得去琢磨怎么使用一些直观的方式来展现数据,甚至来展现一些图片的区别。在Python中,我们经常会用到matplotlib这个2D绘图库来绘制图形。在matplotlib能够绘制的种类很多,在这篇文章中,我会通过绘制直方图来去展现一些常用的绘图技巧和方式。写很长的东西不一定专业,只能帮助你对一个概念有一个快速入门,知识体系能稍微系统一点而已。抛砖引玉,大家共同学习。
一:什么是直方图?
直方图这个概念其实是一个统计学的概念,是一种对数据分布情况的图形表示,也就是一种二维的统计图表。在图像领域里,我们选取的坐标一般是统计样本(图像、视频帧)和样本的某种属性(亮度,像素值,梯度,方向,色彩等等任何特征)。
更直白一些就是说:图像的直方图是用来表现图像中亮度分布的直方图,给出的是图像中某个亮度或者某个范围亮度下共有几个像素。
直方图在CV里边应用的很广泛。比如我们可以通过标记帧和帧之间显著的边缘和颜色的统计变化,来检测视频中场景的变换。可以通过在每个兴趣点设置一个有相近特征的直方图所构成的标签,用以确定图像中的兴趣点。边缘、色彩、角度等直方图构成了可以被传递给目标识别分类器的一个通用特征类型。色彩和边缘的直方图还可以用来识别网络视频是否被复制等。因此直方图在CV中被称为是最经典的工具之一,也是一个很好的图像特征表示手段。
二:直方图绘制
前边说了,绘制直方图首先需要matplotlib这个库,这个库安装起来比较方便,在pycharm包管理哪里直接搜索安装也可以。或者运行cmd,然后在自己的python安装路径的Scripts文件夹目录下,输入命令:
pip install matplotlib
代码如下:
#画直方图
import cv2 as cv
from matplotlib import pyplot as plt
def plot_demo(image):
plt.hist(image.ravel(), 256, [0, 256]) #numpy的ravel函数功能是将多维数组降为一维数组
plt.show()
def image_hist(image): #画三通道图像的直方图
color = ('b', 'g', 'r') #这里画笔颜色的值可以为大写或小写或只写首字母或大小写混合
for i , color in enumerate(color):
hist = cv.calcHist([image], [i], None, [256], [0, 256]) #计算直方图
plt.plot(hist, color)
plt.xlim([0, 256])
plt.show()
src = cv.imread('1.png')
cv.namedWindow('input_image', cv.WINDOW_NORMAL)
cv.imshow('input_image', src)
plot_demo(src)
image_hist(src)
cv.waitKey(0)
cv.destroyAllWindows()
绘制直方图我们会用到cv.calcHist()这个函数
这个函数里边的参数如下:
calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]]) image输入图像,传入时应该用中括号[]括起来 channels::传入图像的通道,如果是灰度图像,那就不用说了,只有一个通道,值为0,如果是彩色图像(有3个通道),那么值为0,1,2,中选择一个,对应着BGR各个通道。这个值也得用[]传入。 mask:掩膜图像。如果统计整幅图,那么为none。主要是如果要统计部分图的直方图,就得构造相应的炎掩膜来计算。 histSize:灰度级的个数,需要中括号,比如[256] ranges:像素值的范围,通常[0,256],有的图像如果不是0-256,比如说你来回各种变换导致像素值负值、很大,则需要调整后才可以。
运行结果如下:
二:直方图的均衡化
直方图均衡化是通过拉伸像素强度的分布范围,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。
在OpenCV中,我们使用的是cv2.equalizeHis()这个函数来实现直方图均衡化:
这个函数按照以下的步骤来实现均衡化:
也就是把直方图的每个灰度级进行归一化处理,求每种灰度的累积分布,得到一个映射的灰度映射表,然后根据相应的灰度值来修正原图中的每个像素。
代码如下:
#直方图的应用 直方图均衡化(即调整图像的对比度) 直方图即统计各像素点的频次
import cv2 as cv
#全局直方图均衡化
def eaualHist_demo(image):
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY) #opencv的直方图均衡化要基于单通道灰度图像
cv.namedWindow('input_image', cv.WINDOW_NORMAL)
cv.imshow('input_image', gray)
dst = cv.equalizeHist(gray) #自动调整图像对比度,把图像变得更清晰
cv.namedWindow("eaualHist_demo", cv.WINDOW_NORMAL)
cv.imshow("eaualHist_demo", dst)
#局部直方图均衡化
def clahe_demo(image):
gray = cv.cvtColor(image, cv.COLOR_RGB2GRAY)
clahe = cv.createCLAHE(5, (8,8))
dst = clahe.apply(gray)
cv.namedWindow("clahe_demo", cv.WINDOW_NORMAL)
cv.imshow("clahe_demo", dst)
src = cv.imread('1.png')
eaualHist_demo(src)
clahe_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()
实现结果如下:
三:直方图的反向投影
反向投影是反映直方图模型在目标图像中的分布情况;简单点说就是用直方图模型去目标图像中寻找是否有相似的对象。通常用HSV色彩空间的HS两个通道直方图模型
步骤:
1:建立直方图模型 2:计算待测图像直方图并映射到模型中 3:从模型反向计算生成图像
代码如下:
#直方图反向投影技术(通过二维直方图反映,必须先把原图像转换为hsv)
import cv2 as cv
#计算H-S直方图
def back_projection_demo():
sample = cv.imread("1.png")
target = cv.imread("1.png")
roi_hsv = cv.cvtColor(sample, cv.COLOR_BGR2HSV)
target_hsv = cv.cvtColor(target, cv.COLOR_BGR2HSV)
cv.namedWindow("sample", cv.WINDOW_NORMAL)
cv.imshow("sample", sample)
cv.namedWindow("target", cv.WINDOW_NORMAL)
cv.imshow("target", target)
roiHist = cv.calcHist([roi_hsv], [0, 1], None, [32, 30], [0, 180, 0, 256])#计算样本直方图 [32, 30]越小,效果越好
cv.normalize(roiHist, roiHist, 0, 255, cv.NORM_MINMAX) #规划到0-255之间
dst = cv.calcBackProject([target_hsv], [0,1], roiHist, [0, 180, 0, 256], 1) #计算反向投影
cv.namedWindow("back_projection_demo", cv.WINDOW_NORMAL)
cv.imshow("back_projection_demo", dst)
back_projection_demo()
cv.waitKey(0)
cv.destroyAllWindows()
在OpenCV中,需要使用到函数cv2.calcBackProject用来计算直方图反向投影
函数原型:calcBackProject(images, channels, hist, ranges, scale[, dst]) images参数表示输入图像(是HSV图像)。传入时应该用中括号[ ]括起来。 channels参数表示用于计算反向投影的通道列表,通道数必须与直方图维度相匹配。 hist参数表示输入的模板图像直方图。 ranges参数表示直方图中每个维度bin的取值范围 (即每个维度有多少个bin)。 scale参数表示可选输出反向投影的比例因子,一般取1。
同时也需要使用到cv2.normalize()归一化函数:
normalize(src, dst[, alpha[, beta[, norm_type[, dtype[, mask]]]]]) src参数表示输入数组。 dst参数表示输出与src相同大小的数组,支持原地运算。 alpha参数表示range normalization模式的最小值。 beta参数表示range normalization模式的最大值,不用于norm normalization(范数归一化)模式。 norm_type参数表示归一化的类型。 norm_type参数可以有以下的取值: NORM_MINMAX:数组的数值被平移或缩放到一个指定的范围,线性归一化,一般较常用。 NORM_INF:归一化数组的C-范数(绝对值的最大值)。 NORM_L1 :归一化数组的L1-范数(绝对值的和)。 NORM_L2 :归一化数组的(欧几里德)L2-范数。
实现的结果:
四:参考文章
1:OpenCV从入门到放弃(七):直方图那些事儿
CSDN-专业IT技术社区-登录blog.csdn.net
2:
OpenCV直方图(直方图、直方图均衡,直方图匹配,原理、实现) - konglongdanfo - 博客园www.cnblogs.com
3:OpenCV官方中文文档
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。