首页 > 技术文章 > Python - opencv (五) 直方图均衡化

Asp1rant 2021-07-13 20:59 原文

转载自:https://blog.csdn.net/qq_44262417/article/details/89149942

直方图均衡化

图像的直方图是对图像对比度效果上的一种处理,旨在使得图像整体效果均匀,黑与白之间的各个像素级之间的点更均匀一点。
直方图均衡化:如果一副图像的像素占有很多的灰度级而且分布均匀,那么这样的图像往往有高对比度和多变的灰度色调。直方图均衡化就是一种能仅靠输入图像直方图信息自动达到这种效果的变换函数。它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展像元取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。
直方图均衡化只对灰度图进行处理。

直方图均衡化的两种方式

1. 全局直方图均衡化

全局直方图均衡化可能得到是一种全局意义上的均衡化,通过全局来增强对比度,提高图像质量。

函数
equalizeHist(src[, dst])

2. 局部直方图均衡化

但是有的时候全局直方图均衡化并不是很好,会把某些不该调整的部分给调整了。Opencv中还有一种直方图均衡化,它是一种局部直方图均衡化,也就是是说把整个图像分成许多小块(比如按10*10作为一个小块),那么对每个小块进行均衡化。

函数

createCLAHE([, clipLimit[, tileGridSize]])

其中:

clipLimit - 表示对比度的大小。

tileGridSize - 表示每次处理块的大小 。

 

代码:

 1 import cv2 as cv
 2 from matplotlib import pyplot as plt
 3 
 4 
 5 def equalHist_demo(image):
 6     # 将图片变成灰度图
 7     gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
 8     cv.imshow("gray", gray)
 9     # 全局直方图均衡函数
10     dst = cv.equalizeHist(gray)
11     plt.subplot(1, 4, 3)
12     plt.xlim([0, 256])
13     plt.ylim([0, 4000])
14     plt.grid(color='r', linestyle='--', linewidth=0.5, alpha=0.3)
15     plt.hist(gray.ravel(), 256, [0, 256])
16     plt.title("equalHist_demo")
17     cv.imshow("equalHist_demo", dst)
18 
19 def clahe_demo(image):
20     gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
21     plt.subplot(1,4,2)
22     plt.hist(gray.ravel(), 256, [0,256])
23     plt.title("gray")
24     plt.xlim([0, 256])
25     plt.ylim([0, 4000])
26     plt.grid(color='r', linestyle='--', linewidth=0.5, alpha=0.3)
27     # 局部直方图均衡化 对比度大小设置为5 处理块大小为8*8
28     calhe = cv.createCLAHE(clipLimit=5.0, tileGridSize=(8,8))
29     dst = calhe.apply(gray)
30     plt.subplot(1, 4, 4)
31     plt.grid(color='r', linestyle='--', linewidth=0.5, alpha=0.3)
32     plt.hist(dst.ravel(), 256, [0, 256])
33     plt.title("clahe_demo")
34     plt.xlim([0, 256])
35     plt.ylim([0, 4000])
36     cv.imshow("clahe_demo", dst)
37 
38 
39 src = cv.imread("scenery.jpg")
40 cv.namedWindow("input image", cv.WINDOW_AUTOSIZE)
41 cv.imshow("input image", src)
42 # 创建画图区域 figure(num=None, figsize=None, dpi=None, facecolor=None, edgecolor=None, frameon=True)
43 # num:图像编号或名称,数字为编号 ,字符串为名称
44 # figsize:figsize:指定figure的宽和高,单位为英寸
45 # dpi:指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80,1英寸等于2.5cm,A4纸是 21*30cm的纸张    
46 # facecolor:背景颜色     edgecolor:边框颜色      frameon:是否显示边框
47 plt.figure("scenery",figsize=(12, 5))
48 # .subplot()创建子图
49 plt.subplot(1,4,1)
50 # 给子图加上网格
51 plt.grid(color='r', linestyle='--', linewidth=0.5, alpha=0.3)
52 # 绘制直方图
53 plt.hist(src.ravel(), 256, [0, 256])
54 plt.title("original picture")
55 plt.xlim([0,256])
56 plt.ylim([0,4000])
57 equalHist_demo(src)
58 clahe_demo(src)
59 plt.show()
60 cv.waitKey(0)
61 cv.destroyAllWindows()

 

 

(1,1)图为原图,(1,2)图为原图的灰度图,(2,1)图为经过全局直方图均衡化后的效果,(2,2)图为进过局部直方图均衡化后的效果。

 

"直接"对BGR图进行局部直方图均衡化

所谓“直接”,其实也是对每个通道的灰度图进行直方图均衡化,然后对均衡化的三个通道进行叠加即变成了BGR图。

 1 import cv2 as cv
 2 from matplotlib import pyplot as plt
 3 
 4 
 5 # 对于plt.title(“中文”),不能再图一些标题显示中文,则在程序前加上以下两行代码即可:
 6 plt.rcParams['font.sans-serif']=['SimHei']
 7 plt.rcParams['axes.unicode_minus'] = False
 8 image = cv.imread("sine.jpg")
 9 cv.imshow("original picture", image)
10 plt.figure("")
11 plt.subplot(2,2,1)
12 plt.title("原图直方图")
13 plt.hist(image.ravel(), 256, [0, 256])
14 color = ["b", "g", "r"]
15 plt.subplot(2,2,3)
16 plt.title("原图三通道直方图")
17 for i, color in enumerate(color):
18     hist = cv.calcHist([image], [i], None, [256], [0, 256])
19     plt.plot(hist, color = color)
20 # 分离每一个通道
21 b, g, r = cv.split(image)
22 # 创建局部直方图均衡化
23 clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(5, 5))
24 # 对每一个通道进行局部直方图均衡化
25 b = clahe.apply(b)
26 g = clahe.apply(g)
27 r = clahe.apply(r)
28 # 合并处理后的三通道 成为处理后的图
29 image = cv.merge([b, g, r])
30 color = ["b", "g", "r"]
31 plt.subplot(2,2,4)
32 plt.title("三通道直方图均衡化")
33 for i, color in enumerate(color):
34     hist = cv.calcHist([image], [i], None, [256], [0, 256])
35     plt.plot(hist, color = color)
36 plt.subplot(2,2,2)
37 plt.title("直方图均衡化")
38 plt.hist(image.ravel(), 256, [0, 256])
39 cv.imshow("clahe", image)
40 plt.show()
41 cv.waitKey(0)
42 cv.destroyAllWindows()

 

 

推荐阅读