计算机视觉OpenCV-图像直方图
Posted 吃猫的鱼python
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计算机视觉OpenCV-图像直方图相关的知识,希望对你有一定的参考价值。
💥💥💥欢迎来到本博客💥💥💥
🎉作者简介:⭐️⭐️⭐️目前计算机研究生在读。主要研究方向是人工智能和群智能算法方向。目前熟悉python网页爬虫、机器学习、计算机视觉(OpenCV)、群智能算法。然后正在学习深度学习的相关内容。以后可能会涉及到网络安全相关领域,毕竟这是每一个学习计算机的梦想嘛!
📋博主优势:🌞🌞🌞博客内容尽量做到每一步都可以进行实操,做到极度细致,不仅仅可以满足自己复习,也方便大家进行学习!亲民!!!
📝目前更新:🌟🌟🌟目前已经更新了关于网络爬虫得相关系列、机器学习得相关知识、目前正在更新计算机视觉-OpenCV,后续将继续更新其他知识。
📃个人主页:吃猫的鱼python个人主页
🔎支持:🎁🎁🎁如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦!这就是给予我最大的支持!
💛💛💛本文摘要💛💛💛
计算机视觉OpenCV图像直方图的相关知识。具体包括以下几个内容。
1.图像直方图基本含义和绘制
2.OpenCV统计直方图并绘制
3.使用掩码的直方图-直方图、掩膜
4.直方图均衡化原理及函数
5.子图的绘制
6.直方图均衡化对比
😎1.图像直方图基本含义和绘制
首先我们先要了解一下python三大剑客之一——matplotlib
我们都知道matlab作为一个工具是公认的绘图牛,但是我想说的是python下的matplotlib这个超级剑客也是非常厉害的,因为python近年来才火热起来,所以热度没有matlib高,但是matlib可以实现的功能作为python都是差不多可以实现的。
我们回归正题,先来介绍下matplotlib怎么简单的画一个直方图。
import numpy as np
import matplotlib.pyplot as plt
x=np.arange(0,5,0.1)
y=np.sim(x)
plt.plot(x,y)
简单的不能再简单了吧,我们使用它去绘制一个sin(x)的函数图像。
那么matplotlib如何和CV一起工作呢?
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("image\\\\boatGray.bmp")
histb = cv2.calcHist([o],[0],None,[256],[0,255])
plt.plot(histb,color='b')
plt.show()
结果是(也很好理解吧):
针对于彩色图像我们也可以针对BGR分别作图。
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("image\\\\girl.bmp")
histb = cv2.calcHist([o],[0],None,[256],[0,255])
histg = cv2.calcHist([o],[1],None,[256],[0,255])
histr = cv2.calcHist([o],[2],None,[256],[0,255])
plt.plot(histb,color='b')
plt.plot(histg,color='g')
plt.plot(histr,color='r')
plt.show()
直方图的绘制我们使用的函数还有:函数hist
功能:根据数据源和像素级绘制直方图。
语法: hist(数据源,像素级)
数据源:图像,必须是一维数组。
像素级:一般是256,指[0,255]
功能:将多维数组降为一维数组。格式:一维数组=多维数组.ravel()
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("image\\\\boat.jpg")
cv2.imshow("o",o)
cv2.waitKey()
cv2.destroyAllWindows()
plt.hist(o.ravel(),256)
😎2.OpenCV统计直方图并绘制
使用OpenCV对图像进行绘制的和横坐标表示像素值比如[0,255],纵坐标表示像素值的个数。
绘制函数:
hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )
其中,hist返回结果是一个直方图,返回的直方图,是一个二维数组。
image原始图像:图像需要使用“[ ]”括起来使用。
channels:
- 通道编号需要用中括号括起来
- 输入图像是灰度图时,它的值是[0];
- 彩色图像可以是[0],[1],[2]。分别对应通道B,G,R。
mask:掩码图像 - 统计整幅图像的直方图,设为None。
- 统计图像某一部分的直方图时,需要掩码图像。
histSize
BINS的数量,例如【256】
ranges
像素值范围RANGE
accumulate - 默认值为false。
- 如果被设置为true,则直方图在开始分配时不会被清零。
- 该参数允许从多个对象中计算单个直方图,或者用于实时更新直方图。
- 多个直方图的累积结果,用于对一组图像计算直方图。
使用OpenCV画出直方图:
import cv2
import matplotlib.pyplot as plt
o=cv2.imread("image\\\\girl.bmp")
histb = cv2.calcHist([o],[0],None,[256],[0,255])
histg = cv2.calcHist([o],[1],None,[256],[0,255])
histr = cv2.calcHist([o],[2],None,[256],[0,255])
plt.plot(histb,color='b')
plt.plot(histg,color='g')
plt.plot(histr,color='r')
plt.show()
😎3.使用掩码的直方图-直方图、掩膜
掩码说实话就是使用掩膜的黑色部分把原始图像的部分给覆盖掉,也称为过滤掉。那么我们怎么做呢?首先我们需要创建一个掩膜:
mask=np.zeros(image.shape,np.uint8)
mask[200:400,200:400]=255
首先创建一个全0的和原图像size一致的,然后我们把指定范围指定为白色。然后传入函数内:
import cv2
import numpy as np
import matplotlib.pyplot as plt
显示直方图
image=cv2.imread("image\\\\girl.bmp",cv2.IMREAD_GRAYSCALE)
mask=np.zeros(image.shape,np.uint8)
mask[200:400,200:400]=255
histMI=cv2.calcHist([image],[0],mask,[256],[0,255])
histImage=cv2.calcHist([image],[0],None,[256],[0,255])
plt.plot(histImage)
plt.plot(histMI)
结果是:
掩膜原理:
说实在的就是与和或的关系,与就是一个不行就都不行。或就是一个行就可以。
而我们的掩膜原理主要用到的就是与操作;
计算结果 = cv2.bitwise_and(图像1,图像2)
import cv2
import numpy as np
import matplotlib.pyplot as plt
image=cv2.imread("image\\\\boat.bmp",0)
mask=np.zeros(image.shape,np.uint8)
mask[200:400,200:400]=255
mi=cv2.bitwise_and(image,mask)
cv2.imshow('original',image)
cv2.imshow('mask',mask)
cv2.imshow('mi',mi)
cv2.waitKey()
cv2.destroyAllWindows()
😎4.直方图均衡化原理及函数
在维基百科是这样定义的:
对应在图像上就是:
前提:如果一幅图像占有全部可能的灰度级,并且均匀分布。
结论:该图像具有高对比度和多变的灰度色调。
外观:图像细节丰富,质量更高。
算法:
1.计算累计直方图
2.将累计直方图进行区间转换
3.在累计直方图中,概率相近的原始值,会被处理为相同的值。
1.计算灰度级出现的概率情况
𝑟𝑘:第K个灰度级
𝑛𝑘:第k级灰度的像素个数
N:图像内总像素的个数
L:灰度级最大值,灰度值区间[0,L-1]
2.变换函数
我们把公式表现在图片上就是:
这样就完成了从原始图像计算得到了均衡直方图。
虽然二者相似。但右侧的分布更均衡,相邻像素级概率和与高概率近似相等。可应用到医疗图像处理,车牌识别,人脸识别。
对应函数是:dst = cv2.equalizeHist( src )
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('image\\\\equ.bmp',cv2.IMREAD_GRAYSCALE)
equ = cv2.equalizeHist(img)
plt.hist(img.ravel(),256)
plt.figure()
plt.hist(equ.ravel(),256)
我们处理一下lena,就是这样:
😎5.子图的绘制
我们有的时候为了方便对比,会想要把几个图放在一张大图中进行比较,那么我们怎么去做呢?有没有一个函数可以完成这个操作呢。
subplot(nrows, ncols, plot_number)
nrows表示行数,ncols表示列数,plot_number表示第几个。subplot(2,3,4)那么就表示2行三列,第四个图。
当每一个参数都小于10时,可以直接书写三个数字,表示为“subplot(234)
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('image\\\\boatGray.bmp',cv2.IMREAD_GRAYSCALE)
equ = cv2.equalizeHist(img)
plt.subplot(121),plt.hist(img.ravel(),256)
plt.subplot(122),plt.hist(equ.ravel(),256)
imshow(X, cmap=None)
X表示要绘制的图像,cmap表示colormap,颜色图谱,默认为RGB(A)颜色空间。
灰度图像 :colormap,颜色图谱,默认为RGB(A)颜色空间使用参数cmap=plt.cm.gray
彩色图像 :colormap,颜色图谱,默认为RGB(A)颜色空间,如果使用opencv读入的图像,默认空间为BGR,需要调整色彩空间为RGB。
import cv2
import matplotlib.pyplot as plt
o = cv2.imread('image\\\\girl.bmp')
g=cv2.cvtColor(o, cv2.COLOR_BGR2GRAY)
plt.subplot(221)
plt.imshow(o),plt.axis('off')
plt.subplot(222)
plt.imshow(o,cmap=plt.cm.gray),plt.axis('off')
plt.subplot(223)
plt.imshow(g),plt.axis('off')
plt.subplot(224)
plt.imshow(g,cmap=plt.cm.gray),plt.axis('off')
第一个图是:彩色图像,使用默认参数。
第二个图是:彩色图像,使用参数cmap=plt.cm.gray
第三个图是:灰色图像,使用默认参数
第四个图是:灰色图像,使用参数cmap=plt.cm.gray
那么只有第四个图是正确的。
对于彩色图像:
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('image\\\\girl.bmp')
b,g,r=cv2.split(img)
img2=cv2.merge([r,g,b])
plt.subplot(121)
plt.imshow(img),plt.axis('off')
plt.subplot(122)
plt.imshow(img2),plt.axis('off')
必须要将BGR split然后merge成RGB才可以。
😎6.直方图均衡化对比
import cv2
import matplotlib.pyplot as plt
img = cv2.imread('image\\\\boat.bmp',cv2.IMREAD_GRAYSCALE)
equ = cv2.equalizeHist(img)
plt.subplot(221)
plt.imshow(img,cmap=plt.cm.gray),plt.axis('off')
plt.subplot(222)
plt.imshow(equ,cmap=plt.cm.gray),plt.axis('off')
plt.subplot(223)
plt.hist(img.ravel(),256)
plt.subplot(224)
plt.hist(equ.ravel(),256)
🔎支持:🎁🎁🎁如果觉得博主的文章还不错或者您用得到的话,可以免费的关注一下博主,如果三连收藏支持就更好啦!这就是给予我最大的支持!
以上是关于计算机视觉OpenCV-图像直方图的主要内容,如果未能解决你的问题,请参考以下文章