目录
一、Matplotlib 绘制直方图
1、概念
直方图简单来说就是图像中每个像素值的个数统计,比如说一副灰度图中像素值为0的有多少个,1的多少个……直方图是一种分析图片的手段:
归一化直方图:统计不同像素值的个数在图像中出现的概率。
要理解直方图,绕不开“亮度”这个概念。人们把照片的亮度分为0到255共256个数值,数值越大,代表的亮度越高。其中0代表纯黑色的最暗区域,255表示最亮的纯白色,而中间的数字就是不同亮度的灰色。人们还进一步把这些亮度分为了5个区域,分别是黑色,阴影,中间调,高光和白色。
2、几个重要参数
-
dims:要计算的通道数,对于灰度图 dims=1
-
range:要计算的像素值范围,一般为[0,256](不包括256)
-
bins:子区段数目,如果我们统计0255每个像素值,bins=256;如果划分区间,比如015, 1631…240255这样16个区间,bins=16
3、绘制直方图
(1)使用 Matplotlib 绘制直方图
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
array = gray.ravel()
plt.hist(array,256)
plt.show()
二、OpenCV 统计、绘制直方图
-
image 输入图像,传入时应该用中括号[]括起来
-
channels::传入图像的通道,如果是灰度图像,那就不用说了,只有一个通道,值为0,如果是彩色图像(有3个通道),那么值为0,1,2,中选择一个,对应着BGR各个通道。这个值也得用[]传入。
-
mask:掩膜图像。如果统计整幅图,那么为none。主要是如果要统计部分图的直方图,就得构造相应的掩膜来计算。
-
histSize:灰度级的个数,需要中括号,比如[256]
-
ranges:像素值的范围,通常[0,256],有的图像如果不是0-256,比如说你来回各种变换导致像素值负值、很大,则需要调整后才可以。
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
def show_img(name="test",img=None):
plt.figure()
plt.imshow(img)
plt.title(name)
plt.show()
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
# 返回图像中每个像素值的个数
histR = cv2.calcHist([img],[0],mask=None,histSize=[256],ranges=[0,255])
histG = cv2.calcHist([img], [1], mask=None, histSize=[256], ranges=[0, 255])
histB = cv2.calcHist([img], [2], mask=None, histSize=[256], ranges=[0, 255])
print('hist type ={}\nhist size = {}\nhist shape = {}'
.format(type(histR),histR.size,histR.shape))
plt.plot(histR,color='r')
plt.plot(histG,color='g')
plt.plot(histB,color='b')
plt.show()
三、使用掩膜的直方图
图像掩模主要用于:
-
①提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
-
②屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
-
③结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
-
④特殊形状图像的制作。
1、绘制掩膜区域的直方图
掩膜就是一个区域大小,表示你接下来的直方图统计就是这个区域的像素统计
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
def show_img(name="test",img=None):
plt.figure()
plt.imshow(img)
plt.title(name)
plt.show()
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
# 掩膜
mask = np.zeros(gray.shape,np.uint8)
mask[200:400,200:400] = 255
# 返回图像中每个像素值的个数
histB = cv2.calcHist([img], [0], mask=None, histSize=[256], ranges=[0,255])
histB_m = cv2.calcHist([img], [0], mask=mask, histSize=[256], ranges=[0,255])
print('hist type ={}\nhist size = {}\nhist shape = {}'
.format(type(histB),histB.size,histB.shape))
plt.plot(histB,color='b')
plt.plot(histB_m,color='g')
plt.show()
2、生成掩膜图像
这里包括的按位操作有:AND,OR,NOT,XOR 等,
在cv2中调用的函数包括 cv2.bitwise_not,cv2.bitwise_and,cv2.bitwise_or,cv2.bitwise_xor
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
def show_img(name="test",img=None):
plt.figure()
plt.imshow(img)
plt.title(name)
plt.show()
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
# 构造掩膜
mask = np.zeros(gray.shape,np.uint8)
mask[200:400,200:400] = 255
# 1
# bitwise_not:
# 对图像进行非操作,二值化的图像均是由0,1,都成,取非之后将会对所有的值进行取反。
# 原来的1变为0。原来的0变为1。即图像颜色由黑变为白,由白变为黑。
# 对mask处的取非操作
bit_not = cv2.bitwise_not(binary,mask=mask)
show_img(img=bit_not)
# 2
# bitwise_and
# 对图像进行与操作时需要添加mask 。mask 和进行操作的图像的大小相同。
# 进行与操作的结果为mask中像素值为1保留带操作图像的像素值。mask中像素值为0则将操作图像的像素值变为0
# 保留掩膜出的图像
img_mask = cv2.bitwise_and(img,img,mask=mask)
show_img(img=img_mask)
四、直方图均衡化
图像的直方图是对图像对比度效果上的一种处理,旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。
直方图均衡化:如果一副图像的像素占有很多的灰度级而且分布均匀,那么这样的图像往往有高对比度和多变的灰度色调。直方图均衡化就是一种能仅靠输入图像直方图信息自动达到这种效果的变换函数。它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展像元取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。
直方图均衡化的三种情况,分别是:
-
灰度图像直方图均衡化
-
彩色图像直方图均衡化
-
YUV 直方图均衡化
1、函数
2、灰度图像直方图均衡化
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
def show_img(name="test",img=None):
plt.figure()
plt.imshow(img)
plt.title(name)
plt.show()
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
# 1 灰度图的 均衡化
equal = cv2.equalizeHist(gray)
# show_img(img=merge)
# 绘制 直方图
plt.hist(gray.ravel(),256)
plt.figure()
plt.hist(equal.ravel(),256)
plt.show()
3、彩色图像直方图均衡化
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
def show_img(name="test",img=None):
plt.figure()
plt.imshow(img)
plt.title(name)
plt.show()
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
# 2 彩色图的均衡化
b,g,r = cv2.split(img)
equal_b = cv2.equalizeHist(b)
equal_g = cv2.equalizeHist(g)
equal_r = cv2.equalizeHist(r)
merge = cv2.merge([b,g,r])
# show_img(img=merge)
四、直方图均衡化对比
# encoding: utf-8
import cv2
import matplotlib.pyplot as plt
import numpy as np
def show_img(name="test",img=None):
plt.figure()
channel = img.shape
if channel == 3:
b, g, r = cv2.split(img)
img = cv2.merge([r, g, b])
plt.imshow(img)
plt.title(name)
plt.show()
if __name__ == '__main__':
path = r"lena.jpg"
img = cv2.imread(path)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,binary = cv2.threshold(gray,127,255,0)
equal = cv2.equalizeHist(gray)
# 原始灰度图
plt.subplot(2,2,1),plt.imshow(gray,'gray'),plt.axis('off')
# 均衡化后的图像
plt.subplot(2,2,2),plt.imshow(equal,'gray'),plt.axis('off')
# 原始图像的灰度直方图
plt.subplot(2,2,3),plt.hist(gray.ravel(),256)
# 均衡化后的灰度直方图
plt.subplot(2,2,4),plt.hist(equal.ravel(),256)
plt.show()