【OpenCV-Python】 直方图均衡化

OpenCV 直方图均衡化

对曝光过度或者逆光拍摄的图片可以通过直方图均衡化的方法用来增强局部或者整体的对比度。

具体思路是通过找出图像中最亮和最暗的像素值将之映射到纯黑和纯白之后再将其他的像素值按某种算法映射到纯黑和纯白之间的值。另一种方法是寻找图像中像素的平均值作为中间灰度值,然后扩展范围以达到尽量充满可显示的值。

image

直方图

什么是直方图?你可以把直方图看作一个图或图,它给你一个关于图像的强度分布的总体思路。它是一个带有像素值的图(从0到255,不总是)在x轴上,在y轴上的图像对应的像素个数。

这只是理解图像的另一种方式。通过观察图像的直方图,你可以直观地了解图像的对比度、亮度、亮度分布等。今天几乎所有的图像处理工具都提供了直方图上的特征。以下是来自Cambridge in Color website的图片,建议去访问这个网站,了解更多细节。

image

你可以看到图像和它的直方图。(这个直方图是用灰度图像绘制的,而不是彩色图像)。直方图的左边部分显示了图像中较暗像素的数量,右边区域显示了更明亮的像素。从直方图中可以看到,深色区域的像素数量比亮色区域更多,而中间色调的数量(中值大约在127左右)则少得多。

直方图相关术语

现在我们已经知道了什么是直方图,我们可以看看如何得到它。OpenCV和Numpy都有内置的功能。在使用这些函数之前,我们需要了解一些与直方图相关的术语。

BINS

BINS:上面的直方图显示了每个像素值的像素数,从0到255。您需要256个值来显示以上的直方图。但是,考虑一下,如果您不需要单独查找所有像素值的像素数量,而是在一个像素值区间内的像素数量,该怎么办?例如,你需要找到介于0到15之间的像素数,然后是16到31……240到255。您只需要16个值来表示这个直方图。OpenCV Tutorials on histograms中展示了这个例子。

所以你要做的就是把整个直方图分成16个子部分,每个子部分的值是所有像素数的和。每个子部分都被称为“BIN”。在第一种情况下,BINS的数量是256(每个像素一个),而在第二种情况下,它只有16个。在OpenCV文档中,用术语 histSize 表示 BINS。

DIMS

DIMS:它是我们收集数据的参数的个数。在这种情况下,我们收集的数据只有一件事,强度值。所以这里是1。

RANGE

RANGE:它是你想测量的强度值的范围。通常,它是 [ 0,256 ],也就是所有的强度值。

OpenCV中直方图的计算

OpenCV提供了cv.calcHist()函数来获取直方图。让我们熟悉一下这个函数及其参数:

cv.calcHist(images, channels, mask, histSize, ranges[, hist[, accumulate]])
  • images:它是uint8类型或float32的源图像。它应该用方括号括起来,也就是”[img]”。

  • channels:它也用方括号括起来。它是我们计算直方图的信道的索引。例如,如果输入是灰度图像,它的值是0。对于颜色图像,您可以通过0、1或2来分别计算蓝色、绿色或红色通道的直方图。

  • mask:遮罩图。为了找到完整图像的直方图,它被指定为“None”。但如果你想找到图像的特定区域的直方图,你必须为它创建一个遮罩图,并将其作为遮罩。

  • histSize:这代表了我们的BINS数。需要用方括号来表示。在整个范围内,我们通过了256。

  • ranges:强度值范围,通常是 [ 0,256 ]

让我们从一个样本图像开始。只需在灰度模式下加载图像并找到其完整的直方图。

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

hist是一个256x1阵列,每个值对应于该图像中的像素值及其对应的像素值。

Numpy中直方图的计算

Numpy中提供了np.histogram()方法,用于对一维数组进行直方图统计,其参数列表如下:

Histogram(a,bins=10,range=None,normed=False,weights=None)
  • a:是保存待统计的数组

  • bins:指定统计的区间个数,即对统计范围的等分数

  • range:是一个长度为2的元组,表示统计范围的最大值和最小值,默认值为None,表示范围由数据的范围决定,即(a.min(), a.max))。

  • normed:当normed参数为False时,函数返回数组a中的数据在每个区间的个数,否则对个数进行正规化处理,使它等于每个区间的概率密度。

  • weights:weights参数和 bincount()的类似

返回值,有两个,

  • hist : hist和之前计算的一样,每个区间的统计结果。

  • bins : 数组,存储每个统计区间的起点。range为[0,256]时,bins有257个元素,因为Numpy计算bins是以0-0.99,1-1.99等,所以最后一个是255-255.99。为了表示这一点,他们还在bins的末端添加了256。但我们不需要256。到255就足够了。

让我们从一个样本图像开始。只需在灰度模式下加载图像并找到其完整的直方图。

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

Numpy还有另一个函数,np.bincount(),比np.histograme()要快得多(大约10X)。对于一维直方图,你可以试一下。不要忘记在np.bincount中设置minlength=256。例如,hist=np.bincount(img.ravel(),minlength=256)

OpenCV函数比np.histogram()快(大约40X)。所以考虑效率的时候坚持用OpenCV函数。

绘制直方图

1. 使用Matplotlib

Matplotlib有一个绘制直方图的函数:

matplotlib.pyplot.hist()

它直接找到了直方图并绘制了它。您不需要使用calcHist()或np.histogram()函数来找到直方图。看下面的代码:

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

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

image

或者你可以用常规的matplotlib的plot函数绘制直方图,适合绘制BGR图像直方图。为此,您需要首先找到直方图数据。试试下面的代码

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

img = cv.imread('home.jpg')
color = ('b', 'g', 'r'
  • 8
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值