OpenCV自学记录(7)—— 直方图均衡化详解
OpenCV自学记录(7)—— 直方图均衡化详解
写在前面的话,昨天去参加了一个面试,面试管说现在好多人都在学计算机视觉方面的技术,但大部分都是只是效仿,有点东施效颦的意思。想想自己确实也是这样,最终幸运的是成功通过了面试,我一定会珍惜这次机会,进入公司之后一定要跟大佬学习更多,在毕业之前达到合格线!!!还有很长的路要走,道阻且长。
1、什么是直方图?
很久以前就知道直方图均衡化可以提高图片的对比度,然后。。。。就没有然后了。。。一直这样眼高手低也是自己感觉学的不少但真正工作的时候又发现自己还差的远的原因。。。
直方图提供了图像的统计信息,为了理解多种空域增强技术的内涵提供了铺垫。直方图是数值数据分布的精确图表现形式。
首先,我们要明白直方图统计的是什么:横轴:代表从黑到白的影调;纵轴:代表像素量。也就是说,直方图统计的是“照片中”不同影调的像素量多少。也就是说,直方图只统计多少,不统计在哪儿。
1.1灰度直方图
灰度直方图是关于灰度级分布的函数,将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。其中,横坐标是灰度级,纵坐标是该灰度级出现的频率。能够很直观的展示图像中灰度级的整体分布情况,对图像的后续处理有很好的指导作用。
灰度直方图绘制代码:
import cv2 as cv
import matplotlib.pyplot as plt
img_ = cv.imread('001.jpg')
plt.figure("lena")
arr=img_.flatten()
plt.subplot(1, 2, 1)
n, bins, patches = plt.hist(arr, bins=256, normed=1, facecolor='green', alpha=0.75)
plt.subplot(1, 2, 2)
plt.imshow(img_)
plt.show()
1.2彩色直方图
所谓的彩色直方图就是将RGB通道分割开来,对三个通道分别进行直方图绘制。
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
src=Image.open('001.jpg')
r,g,b=src.split()
plt.figure("lena")
ar=np.array(r).flatten()
plt.hist(ar, bins=256, normed=1,facecolor='r',edgecolor='r',hold=1)
ag=np.array(g).flatten()
plt.hist(ag, bins=256, normed=1, facecolor='g',edgecolor='g',hold=1)
ab=np.array(b).flatten()
plt.hist(ab, bins=256, normed=1, facecolor='b',edgecolor='b')
plt.show()
2、直方图均衡化
2.1灰度直方图均衡化和局部直方图均衡化
方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法,其主要思想是将一副图像的直方图分布变成近似均匀分布,从而增强图像的对比度。目的是为了使直方图能均匀分布,从而使图像的一些细节得到增强。这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布,这样就可以用于增强局部的对比度而不影响整体的对比度。
局部直方图均衡化:
直接上代码:
def equalHist(image):
"""直方图均衡化,图像增强的一个方法"""
# 彩色图片转换为灰度图片
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# 直方图均衡化,自动调整图像的对比度,让图像变得清晰
dst = cv.equalizeHist(gray)
return dst
def clahe(image):
"""
局部直方图均衡化
把整个图像分成许多小块(比如按8*8作为一个小块),
那么对每个小块进行均衡化。
这种方法主要对于图像直方图不是那么单一的(比如存在多峰情况)图像比较实用
"""
# 彩色图片转换为灰度图片
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# cliplimit:灰度值
# tilegridsize:图像切割成块,每块的大小
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
dst = clahe.apply(gray)
return dst
对图片进行直方图均衡化和局部直方图均衡化的代码如下:
import cv2 as cv
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
def equalHist(image):
"""直方图均衡化,图像增强的一个方法"""
# 彩色图片转换为灰度图片
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# 直方图均衡化,自动调整图像的对比度,让图像变得清晰
dst = cv.equalizeHist(gray)
return dst
def clahe(image):
"""
局部直方图均衡化
把整个图像分成许多小块(比如按8*8作为一个小块),
那么对每个小块进行均衡化。
这种方法主要对于图像直方图不是那么单一的(比如存在多峰情况)图像比较实用
"""
# 彩色图片转换为灰度图片
gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)
# cliplimit:灰度值
# tilegridsize:图像切割成块,每块的大小
clahe = cv.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
dst = clahe.apply(gray)
return dst
img_ = cv.imread('001.jpg')
plt.figure("lena")
arr=img_.flatten()
plt.subplot(2, 2, 1)
plt.title('直方图')
n, bins, patches = plt.hist(arr, bins=256, normed=1, facecolor='green', alpha=0.75)
plt.subplot(2, 2, 2)
plt.title('原图')
plt.imshow(img_)
plt.subplot(2, 2, 3)
plt.title('直方图均衡化')
img1 = equalHist(img_)
plt.imshow(img1)
plt.subplot(2, 2, 4)
plt.title('局部直方图均衡化')
img2 = clahe(img_)
plt.imshow(img2)
plt.show()
运行结果:
2.2 彩色图像直方图均衡化
import cv2 as cv
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['SimHei'] #用来正常显示中文标签
plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
img = cv.imread('001.jpg')
img0 = cv.equalizeHist(img[:, :, 0]) # 各个通道分别均衡化
img1 = cv.equalizeHist(img[:, :, 1])
img2 = cv.equalizeHist(img[:, :, 2])
img_e = cv.merge([img0, img1, img2])
plt.figure("lena")
plt.subplot(2, 2, 1)
plt.hist(img.ravel(), 256)
plt.subplot(2, 2, 2)
plt.hist(img_e.ravel(), 256)
plt.subplot(2, 2, 3)
plt.title('原图')
plt.imshow(img)
plt.subplot(2, 2, 4)
plt.title('彩色均衡化后')
plt.imshow(img_e)
plt.show()
运行结果: