Opencv python 直方图处理

Opencv直方图处理

  • 前言
  • 1.1 直方图的含义
  • 1.2 绘制直方图
    • 1.2.1 使用Numpy绘制直方图
    • 1.2.2 使用OpenCV绘制直方图
      • 1.2.2.1 用cv2.calcHist()函数统计图像直方图信息
      • 1.2.2.2 plot()函数的使用
      • 1.2.2.3 绘制统计直方图
    • 1.2.3 使用掩模绘制直方图
  • 1.3 直方图均衡化
    • 1.3.1 直方图均衡化处理
  • 1.4 pyplot模块介绍
    • 1.4.1 subplot函数
    • 1.4.2 imshow函数
  • 总结


前言

寒假打卡!小白入门,如有不正确的地方希望各位大佬指正。


1.1 直方图的含义

从统计学上讲,直方图是图像内灰度值的统计特征与图像灰度值之间的函数,直方图统计图像内各个灰度级出现的次数。从直方图的图形上观察,横坐标是图像中各个像素点的灰度级,纵坐标是具有该灰度级(像素值)的像素个数。
注意:折线图和直方图统称直方图
Opencv python 直方图处理_第1张图片

有时为了便于理解,也会采用归一化直方图。归一化直方图中,x轴仍然代表灰度级,y轴不再代表灰度级出现的次数,而是灰度值出现的频率。(频率从0到1)

在OpenCV官网上,特别提出了要注意的三个概念:DIMS、BINS、RANGE。
DINS:表示在绘制直方图时,收集的参数的数量。一般情况下,直方图中收集的数据只有一种,就是灰度级。因此,该值为1.
BINS:参数子集的数目。在处理数据的过程中,有时需要将众多的数据划分为若干个组,再进行讨论。例如:灰度级有1、2、3、4、5、6六种,可以分为6组,每组1个灰度级,也可以分为3组,每组两个灰度级。
RANGE:表示要统计的灰度级范围,一般为[0,255]。0对应的是黑色,255对应的是白色。

1.2 绘制直方图

主要有两种方式:Python模块matplotlib.pyplot中的hist()函数能够方便的绘制直方图;OpenCV中的cv2.calcHist()函数能够计算统计直方图,还可以在此基础上绘制图像的直方图。

1.2.1 使用Numpy绘制直方图

模块matplotlib.pyplot中的hist()函数能够方便的绘制直方图,其语法如下:

matplotlib.pyplot.hist(X,BINS)

X:数据源,必须是一维的。图像一般是二维的,需要使用ravel()函数将图像处理为一维数据源以后,再作参数使用。
BINS:BINS的具体值,表示灰度级的分组情况。
示例:

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\xiaoxinyi.jpg")  #读入图片
cv2.imshow("original",o)                    #展示图片
plt.hist(o.ravel(),256)                     #绘制转换为一维数据源,灰度级分组为256组的图像直方图
cv2.waitKey()
cv2.destroyAllWindows()

Opencv python 直方图处理_第2张图片
Opencv python 直方图处理_第3张图片
修改参数BINS,看一下画灰度级划分为16组的直方图。
Opencv python 直方图处理_第4张图片

1.2.2 使用OpenCV绘制直方图

OpenCV提供了函数cv2.calcHist()用来计算图像的统计直方图,该函数能统计各个灰度级的像素点的个数。利用matplolib.pyplot模块中的plot()函数,可以将函数cv2.calcHist()的统计结果绘制成直方图。

1.2.2.1 用cv2.calcHist()函数统计图像直方图信息

语法格式为:

hist = cv2.calcHist(images,channels,mask,histSize,ranges,accumulate)

hist:返回的统计直方图,是一个一维数组,数组内的元素是各个灰度级的像素个数。
images:原始图像,该图像需要用"[ ]"括起来
channels:指定通道标号。通道编号用"[ ]"括起来,如果输入图像时单通道灰度图像,该参数的值就是[0]。对于彩色图像,它的值可以是[1]、[2]、[3],分别对应B、G、R。
mask:掩模图像。当要统计整幅直方图时,将这个值设为None。当要统计图像的某一部分的直方图时,需要用到掩模图像。
histSize:BINS的值,该值需要用"[ ]"括起来
ranges:即像素范围。例如:8位灰度图像的像素值范围是[0,255]。
accumulate:累计标识,默认值为False。如果被设置为True,则直方图在开始计算时不会被清零,计算的是多个直方图的累计结果,用于对一组图像计算直方图。一般情况下不需要设置。

1.2.2.2 plot()函数的使用

通过一些例子演示plot()函数的使用方法。

import matplotlib.pyplot as plt
x = [0,1,2,3,4,5,6]           #指定x轴
y = [0.3,0.4,2,3.5,5.5,6,7]   #指定y轴
plt.plot(x,y)

Opencv python 直方图处理_第5张图片

import matplotlib.pyplot as plt
y = [0.3,0.4,2,3.5,5.5,6,7]       #仅指定y轴
plt.plot(y)

Opencv python 直方图处理_第6张图片
如果仅指定一个参数,则其对应的x轴的默认值是一个从0开始,步长为1的自然序列,自然序列x的长度与y的长度保持一致。

除此之外,我们还可以指定绘图颜色

import matplotlib.pyplot as plt
a = [0.3,0.4,2,3.5,5.5,6,7]
b = [1,3,4.5,5.3,6,6.8,7]
plt.plot(a,color='r')
plt.plot(b,color='g')

Opencv python 直方图处理_第7张图片

1.2.2.3 绘制统计直方图

将上文提及的函数cv2.calcHist()与函数plot()配套使用。

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\xiaoxinyi.jpg")
histb = cv2.calcHist([o],[0],None,[256],[0,255])   #因为处理的图像是彩图,所以这里的[0]是B通道
histg = cv2.calcHist([o],[1],None,[256],[0,255])  #这里的[1]是G通道
histr = cv2.calcHist([o],[2],None,[256],[0,255])  #这里的[2]是R通道
plt.plot(histb,color='b')                         #用蓝线绘制B通道的直方图
plt.plot(histg,color='g')                         #用绿线绘制G通道的直方图
plt.plot(histr,color='r')                         #用红线绘制R通道的直方图
plt.show()                                        #不必要,去掉这一行代码执行结果一样

Opencv python 直方图处理_第8张图片

1.2.3 使用掩模绘制直方图

在函数cv2.calcHist()中,参数mask用于标识是否使用掩模图像。当使用掩模图像获取直方图时,仅获取掩模参数mask指定区域的直方图。
关于掩模的详细介绍将会在下一篇博客中,这里仅介绍如何使用

import cv2
import numpy as np
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\xiaoxinyi.jpg",cv2.IMREAD_GRAYSCALE)
mask = np.zeros(o.shape,np.uint8)     #构造一个像素值都是0的二维数组
mask[200:400,200:400]=255             #将中间部分(根据本图像大小)的值设置为255
histImage = cv2.calcHist([o],[0],None,[256],[0,255])
histMI = cv2.calcHist([o],[0],mask,[256],[0,255])
plt.plot(histImage,color='r')         #原图的直方图用红色线画出
plt.plot(histMI,color='g')            #使用过掩模的直方图用绿色线画出

Opencv python 直方图处理_第9张图片
可以看到使用掩模在不同灰度值像素点的个数要明显小于原图。

1.3 直方图均衡化

直方图均衡化使图像色彩更均匀、外观更清晰,也使图像更便于处理。它被广泛用于医学图像处理、车牌识别、人脸识别等领域。

1.3.1 直方图均衡化处理

OpenCV使用函数cv2.equalizeHist(src)实现直方图均衡化,具体语法如下:

dst = cv2.equalizeHist(src)

src:8位单通道原始图像
dst:直方图均衡化的结果

但是很遗憾的是我没有找到合适的图像(色彩不均匀的)作为演示。所以就只能将就一下下,看一下这个效果一般的例子吧。

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\biaoqingbao.jpg",cv2.IMREAD_GRAYSCALE)   #单通道,所以要读入灰度图
equ = cv2.equalizeHist(o)
cv2.imshow("original",o)
cv2.imshow("equ",equ)
plt.figure("原始图像直方图")
plt.hist(o.ravel(),256)
plt.figure("均衡化图像直方图")
plt.hist(equ.ravel(),256)
cv2.waitKey()
cv2.destroyAllWindows()

Opencv python 直方图处理_第10张图片
Opencv python 直方图处理_第11张图片
可以看到均衡化后的直方图更均衡了。

1.4 pyplot模块介绍

主要用于方便的绘制图形。

1.4.1 subplot函数

用来向当前窗口添加一个子窗口对象。具体语法如下:

matplotlib.pyplot.subplot(nrows,ncols,index)

nrows:为行数。
ncols:为列数。
index:为窗口序号
例如:subplot(2,3,4)表示在当前的两行三列的窗口的第4个位置上,添加一个子窗口。

注意:窗口是按照行方向排序的,而且序号是从’1’开始而不是’0’。
如果所有参数都小于10,可以省略彼此之间的逗号,直接写三个数字。

举个例子:

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\biaoqingbao.jpg",cv2.IMREAD_GRAYSCALE)
equ = cv2.equalizeHist(o)
plt.figure("subplot示例")
plt.subplot(121),plt.hist(o.ravel(),256)    #ravel()函数处理为一维数组模式。256是BINS值
plt.subplot(122),plt.hist(equ.ravel(),256)

Opencv python 直方图处理_第12张图片

1.4.2 imshow函数

模块matplotlib.pyplot提供了函数matplotlib.pyplot.imshow()用来显示图像。其语法如下所示:

matplotlib.pyplot.imshow(X,cmap=None)

X:图像信息,可以是各种形式的数值。
cmap:表示色彩空间。该值是可选项,默认使用RGB(A)色彩空间。

在OpenCV中通道顺序是BGR模式的,而函数matplotlib.pyplot.imshow()的显示顺序是RGB模式的,所以如果不对通道顺序进行一次转换的话会无法正常显示
通道转换语句:imgRGB=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)

示例:

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\xiaoxinyi.jpg")
img = cv2.cvtColor(o,cv2.COLOR_BGR2RGB)    #要转化到RGB色彩空间
plt.imshow(img)

Opencv python 直方图处理_第13张图片
如果不想显示坐标轴的话可以在plt.imshow()加一个参数并且改变函数语法格式,具体如下所示

import cv2
import matplotlib.pyplot as plt
o = cv2.imread(r"D:\lesson\xiaoxinyi.jpg")
img = cv2.cvtColor(o,cv2.COLOR_BGR2RGB)
plt.imshow(img),plt.axis('off')     #关闭坐标轴(注意这里参数的写法)

Opencv python 直方图处理_第14张图片
总结:使用较麻烦,还是cv2.imshow()方便


总结

以上就是对Opencv直方图处理的学习,暂时还不知道其在项目实战中有什么用,如果以后用到了再继续补充。寒假打卡冲冲冲!

你可能感兴趣的:(opencv,python,计算机视觉)