还记得您看到低质量的图像时感到有些失望吗? 还不够清晰,细节有些模糊。 如果可以将该图像增强到更好的版本该怎么办? 那不是很好吗? 幸运的是,有一种方法可以使用Python!
可以用来增强图像的方法之一是直方图均衡化 ,特别是可以增强图像的对比度 。 几乎所有的相机系统实际上都使用直方图均衡来使我们的图片看起来更好,在本教程的最后,您将发现为什么会这样。
在下一节中,我将深入研究直方图均衡化的含义以及应用该方法时图像发生的变化,然后我们将了解如何在Python中实现该方法。 准备?
直方图均衡
假设您有pout.jpg图片(继续下载)。 这是在MATLAB中使用的演示图像,我从中获得了图像,但是我们将在本教程中使用它。 该图像如下所示:
让我们看一下如何访问图像的像素值,即强度 。 我写了这个小的Python脚本,我们可以用它来做到这一点(注意我正在使用OpenCV库):
import cv2
img = cv2.imread('pout.jpg')
img_shape = img.shape
height = img_shape[0]
width = img_shape[1]
for row in range(width):
for column in range(height):
print (img[column][row])
我在这里所做的是阅读图像(pout.jpg),然后研究图像的形状(大小)。 img_shape将返回: (1031, 850, 3) img_shape (1031, 850, 3) 。 这意味着我们的图像的高度(列数)为1031 ,宽度为(行数)为850 ,并具有3通道(RGB)。 请注意,结果中的第一个参数是高度,第二个参数是宽度。 最后,我们遍历行和列,并在每个行/列对上打印出不同的像素值(强度)。
输出的一个样本是: [137 137 137] 。 是的,我知道,您期望像素强度得到一个值。 实际上,我们在这里具有像素强度的值,但是输出显示给我们的是红色,绿色和蓝色( RGB )通道的结果。 但是请注意,在OpenCV中,顺序为BGR ,因为这是OpenCV加载图像的方式。 因此,以上样本结果包含每个通道的值137 ,分别为B , G和R的顺序。
引入的原因是直方图均衡实际上是关于像素强度的修改,目的是提高图像的对比度。 因此,我们的主要工作将在像素强度级别上。
此时,您可能想知道什么是直方图 。 尽管有时该术语可能有点令人困惑,但实际上这是一个非常简单的概念。 直方图只是一个示意图,它描述了在图像中找到的每个强度值下图像中像素的数量。
由于我们的像素具有三个值,每个BGR通道一个,因此绘制直方图的一种方法是具有三个直方图,每个通道一个,其中x轴将具有不同的像素值(强度),而y -轴将显示特定像素值在不同像素值中出现了多少次(频率)。
例如,红色通道直方图在x轴上的像素值可以为137 ,而y轴可以显示红色通道的此值有多少像素(例如86 。 因此,我们的读取方式是说137红色通道的像素值显示为86像素,或者在我们的图像中重复了86次。
使用此图像直方图文章中的代码绘制图像的直方图,我们得到以下信息:
直方图实际上是针对红色,绿色和蓝色通道的。 让我们从上一个代码中获取一小部分输出,如下所示。 这表明通道值似乎总是相同的,因此绘制的不同的三条线将具有相同的值,并且将被绘制在彼此的顶部,仅显示为一条线。
[94 94 94]
[95 95 95]
[97 97 97]
[99 99 99]
[100 100 100]
[101 101 101]
[101 101 101]
[101 101 101]
[100 100 100]
[98 98 98]
[95 95 95]
[93 93 93]
直方图均衡方法将对上述直方图执行的操作是,它将以使直方图在所得图像中看起来更平坦的方式来转换强度值。 换句话说,直方图均衡化是一种调整图像强度以增强图像对比度的方法。
上面的直方图看起来有点集中在图的中间,并且直方图均衡将要做的是进一步分配像素强度值以获得更平坦的直方图。
我想在这里讨论直方图均衡就足够了,因为我们不想在本教程中获得更多的数学信息,特别是因为它更多地是关于在Python中实现该方法。 但是,您可以检查这些注释,这些注释显示该方法涉及的不同公式: 直方图均衡化 。 现在让我们深入研究实现!
Python中的直方图均衡
在本节中,我将向您展示如何在Python中实现直方图均衡方法。 我们将在实验中使用以上图片( pout.jpg )。 让我们逐步进行该过程。 我们需要做的第一件事是导入OpenCV和NumPy库,如下所示:
import cv2
import numpy
之后,我们只需要读取图像pout.jpg即可 :
img = cv2.imread('pout.jpg')
好消息是OpenCV为我们提供了一个函数,通过该函数可以对图像应用直方图均衡,即equalizeHist() 。 将此功能应用于灰度图像很简单,因为该方法实际上均衡了灰度图像的直方图,但是在我们的示例中,每个像素有三个通道(RGB),并且不能在单独的三个通道上应用直方图均衡方式。
我在《 Python:真实世界机器学习 》一书中遇到的一个不错的解决方案是将图像转换为YUV颜色空间,均衡Y通道,最后将结果转换为RGB。 因此,我们要做的第一件事就是将图像转换为YUV 。 这可以使用cvtColor()方法完成,该方法将图像从一种空间颜色转换为另一种空间颜色,如下所示:
img_to_yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV)
注意,这里我们使用BGR而不是RGB ,因为OpenCV(如前所述)以BGR格式加载图像。
现在,我们使用equalizeHist()方法在Y通道上应用直方图均衡方法:
img_to_yuv[:,:,0] = cv2.equalizeHist(img_to_yuv[:,:,0])
最后,我们将Y通道转换为RGB (OpenCV中为BGR ),如下所示:
hist_equalization_result = cv2.cvtColor(img_to_yuv, cv2.COLOR_YUV2BGR)
恭喜你! 现在,您已将直方图均衡化应用于图像。 在下一节中,我将所有代码放在一起,并向您展示在应用直方图均衡后我们的图像的外观。
放在一起
让我们把我们学到的一切放在一起。 在pout.jpg上应用直方图均衡化的Python脚本如下所示:
import cv2
import numpy
img = cv2.imread('pout.jpg')
img_to_yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV)
img_to_yuv[:,:,0] = cv2.equalizeHist(img_to_yuv[:,:,0])
hist_equalization_result = cv2.cvtColor(img_to_yuv, cv2.COLOR_YUV2BGR)
cv2.imwrite('result.jpg',hist_equalization_result)
上面脚本的输出如下图:
为了更好地注意到差异,我将两个图像放在一起(左:原始图像;右:直方图均衡的结果):
您注意到差异了吗? 正确的图像看起来比原始图像清晰得多。 难怪几乎所有成像系统都执行直方图均衡化!
在总结之前,让我们看看结果的直方图是什么样的:
如果将生成的图像的直方图与原始图像的直方图进行比较,您会注意到生成的图像的直方图比原始图像的直方图平坦,这正是直方图均衡方法的作用。
结论
在本教程中,我们看到了如何使用称为直方图均衡的方法来增强图像的对比度,以及如何使用Python和OpenCV轻松实现它。
结果非常有趣,因为它比原始图像清晰得多,并且结果的直方图比原始图像的直方图平坦,显示了像素强度值在整个图像中的更好分布。
最后,不要犹豫,看看我们可以在Envato市场上出售和研究的东西 ,请提出任何问题,并使用下面的feed提供您的宝贵反馈。
翻译自: https://code.tutsplus.com/tutorials/histogram-equalization-in-python--cms-30202
165

被折叠的 条评论
为什么被折叠?



