OpenCV-Python -- Histograms - 1 : Find, Plot, Analyze !!!

学习目标

  • 计算直方图,使用OpenCV和Numpy.
  • 画直方图,使用OpenCV和Matplotlib.
  • 学习函数: cv2.calcHist()np.histogram().

理论知识

直方图是什么?可以将直方图看成是图表,可以直观给出图像的整体像素值的分布情况。通常绘制直方图的X轴是256级(0-255)灰度,Y轴统计该灰度下的像素数量。

直方图是理解图像的另外一种方式。通过直方图,可以直观上获得对比度,亮度,强度分布等。当前,几乎所有的图像处理工具提供了直方图特征。下图来自 Cambridge in Color website

在这里插入图片描述
从图中可以看出(统计直方图时,是灰度图像),直方图的左边区域的像素亮度较暗,右边的区域较亮。并且,暗的像素大于亮的像素,处于中间的像素(127)较少。

直方图计算

通过上面的介绍,我们对直方图有直观的概念,下面将研究如何计算直方图。OpenCV和Numpy都可以计算。使用内置函数计算之前,我们需要理解直方图的相关原理。

BINS:上面的图显示了每一个像素值的统计数量,比如0-255。但是,通常我们不需要每一个像素值的统计数量,而是一个像素区间的统计数量,比如,[0-15],[16-31],…, [240-255]. Y轴只需16个值表达。其中每一个子区间称之为 “BIN”,在OpenCV中,BINS用histSize参数表示。

DIMS:用于收集数据的参数数量,这里我们只用灰度图的灰度值作为统计参数,所以dims=1.

Range:统计的像素强度的范围,一般情况下,[0,256],是所有的强度值。

1. Histogram Calculation in OpenCV

现在,我们使用cv2.calcHist()计算直方图,该函数的定义如下:

cv2.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
	"""
	功能:计算直方图
	images:输入图像,类型为uint8或者float32. 输入的时候需要添加中括号,[img].
	channels:同样需要添加中括号,该值是指定计算哪个通道的直方图。比如,如果输入的是				
	灰度图像,那么值为[0]。彩色图像,可以传入[0],[1],[2]分别计算blue,green,red通道
	的直方图统计。
	mask:掩码图像。如果计算全图的直方图,该参数的值为None。但是,如果计算图像中某个	
	区域的直方图统计,那么需要掩码图像。
	histSize:表示BINS的个数,也需要有中括号,对于全图,则需传入[256].
	ranges:像素值的范围,通常为[0,256].
	"""

下面以一个例子展示使用:

img = cv2.imread('home.jpg',0)
hist = cv2.calcHist([img],[0],None,[256],[0,256])

2. Histogram Calculation in Numpy

Numpy也可以计算直方图,np.histogram(),使用如下:

hist,bins = np.histogram(img.ravel(),256,[0,256])

返回值跟CV计算的返回值一样。因为Numpy计算BINS为,0-0.99,1-1.99,2-2.99,…,255-255.99 等,所以BINS是257个值。

  1. numpy还有另外一个函数,np.bincount(),比np.histogram()快10倍以上。所以一维的直方图,可以尝试。但是要设置minlength=256。比如,hist = np.bincount(img.ravel(),minlength=256)
  2. OpenCV函数比np.histogram()快40倍。

Plotting Histogram

两种方式可以画图:

  1. Short Way:使用Matplotlib。
  2. Long Way:OpenCV。

1. Using Matplotlib

Matplotlib可以画直方图的函数为:Matplotlib.pyplot.hist(),可以直接得到直方图,然后绘制。代码如下:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('home.jpg', 0)
plt.hist(img.ravel(), 256, [0,256])
plt.show()

或者可以使用如下的方式绘制直方图:

import cv2
import numpy as np
from matplotlib import pyplot as plt

img = cv2.imread('home.jpg')
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()

运行结果如下:
在这里插入图片描述

2. Using OpenCV

OpenCV也可以达到上述的效果,需要使用cv2.line(),或者cv2.polyline().

Application of Mask

有时候,我们需要计算图像部分区域的直方图。那么我们需要创建一个掩码区域,实例如下:

img = cv2.imread('home.jpg',0)

# create a mask
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
masked_img = cv2.bitwise_and(img,img,mask = mask)

# Calculate histogram with mask and without mask
# Check third argument for mask
hist_full = cv2.calcHist([img],[0],None,[256],[0,256])
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])

plt.subplot(221), plt.imshow(img, 'gray')
plt.subplot(222), plt.imshow(mask,'gray')
plt.subplot(223), plt.imshow(masked_img, 'gray')
plt.subplot(224), plt.plot(hist_full), plt.plot(hist_mask)
plt.xlim([0,256])

plt.show()

运行结果如下:
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值