转载自:
https://blog.csdn.net/m0_38007695/article/details/82718107
1、灰度直方图
在讲解图像增强的方法之前先来认识一下灰度直方图,灰度直方图是图像灰度级的函数,用来描述每个灰度级在图像矩阵中的像素个数或者占有率。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
img = cv.imread("../testImages/4/img1.jpg", 0)
h, w = img.shape[:2]
pixelSequence = img.reshape([h * w, ])
numberBins = 256
histogram, bins, patch = plt.hist(pixelSequence, numberBins,
facecolor='black', histtype='bar')
plt.xlabel("pixels")
plt.ylabel("number of pixels")
plt.axis([0, 255, 0, np.max(histogram)])
plt.show()
cv.imshow("img", img)
cv.waitKey()
图像的对比度是通过灰度级范围来度量的,而灰度级范围可通过观察灰度直方图得到,灰度级范围越大代表对比度越高;反之对比度越低。低对比度的图像在视觉上给人的感觉是看起来不够清晰,所以通过算法调整图像的灰度值,从而调整图像的对比度是有必要的。最简单的一种对比度增强的方法是通过灰度值的线性变换实现的。下面介绍一下这个方法。
2、线性变换
假设输入图像为I,宽为W,高为H,输出图像记为O,图像的线性变换可以用以下公式定义:
-
当a=1,b=0时,O是I的一个副本;
-
a值的改变,影响的事输出图像的对比度。
当a>1,则输出图像的对比度比有所增大;当0<a<1,则的对比度比有所减小。 -
b值的改变,影响的是输出图像的亮度。
当b>0时,亮度增加;当b<0时,亮度减小。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
# 绘制直方图函数
def grayHist(img):
h, w = img.shape[:2]
pixelSequence = img.reshape([h * w, ])
numberBins = 256
histogram, bins, patch = plt.hist(pixelSequence, numberBins,
facecolor='black', histtype='bar')
plt.xlabel("gray label")
plt.ylabel("number of pixels")
plt.axis([0, 255, 0, np.max(histogram)])
plt.show()
img = cv.imread("../testImages/4/img4.jpg", 0)
out = 2.0 * img
# 进行数据截断,大于255的值截断为255
out[out > 255] = 255
# 数据类型转换
out = np.around(out)
out = out.astype(np.uint8)
# 分别绘制处理前后的直方图
# grayHist(img)
# grayHist(out)
cv.imshow("img", img)
cv.imshow("out", out)
cv.waitKey()
以上线性变换是对整个灰度级范围使用了相同的参数,有的时候也需要针对不同灰度级范围进行不同的线性变换,这就是常用的分段线性变换,经常用于降低较亮或较暗区域的对比度来增强灰度级处于中间范围的对比度,或者压低中间灰度级处的对比度来增强较亮或者较暗区域的对比度。
从下图(a)的灰度直方图(b)可以看出,图像的灰度主要集中在 [100,150]之间,可以通过以下分段线性变换将主要的灰度级拉伸到[50,230],结果如图(c)所示,对比度拉伸后显然比原图能够更加清晰地看到更多的细节。
img = cv.imread("../testImages/4/img7.jpg", 0)
img = cv.resize(img, None, fx=0.3, fy=0.3)
h, w = img.shape[:2]
out = np.zeros(img.shape, np.uint8)
for i in range(h):
for j in range(w):
pix = img[i][j]
if pix < 50:
out[i][j] = 0.5 * pix
elif pix < 150:
out[i][j] = 3.6 * pix - 310
else:
out[i][j] = 0.238 * pix + 194
# 数据类型转换
out = np.around(out)
out = out.astype(np.uint8)
# grayHist(img)
# grayHist(out)
cv.imshow("img", img)
cv.imshow("out", out)
cv.waitKey()
线性变换的参数需要根据不同的应用及图像自身的信息进行合理的选择,可能需要进行多次测试,所以选择合适的参数是相当麻烦的。直方图正规化就是基于当前图像情况自动选取a和b的值的方法,下面介绍这种方法。
3、直方图正规化
Imax = np.max(img)
Imin = np.min(img)
Omin, Omax = 0, 255
a = float(Omax - Omin) / (Imax - Imin)
b = Omin - a * Imin
out = a * img + b
out = out.astype(np.uint8)
cv.imshow("out", out)
4、伽马变换
首先将其灰度值归一化到[0,1]范围,对于8位图来说,除以255即可。再使用伽马变换:
- 当=1时,图像不变。
- 如果图像整体或者感兴趣区域较暗,则令0<<1可以增加图像对比度;
- 如果图像整体或者感兴趣区域较亮,则令>1可以降低图像对比度。
图像的伽马变换实质上是对图像矩阵中的每一个值进行幂运算。
img = cv.imread("../testImages/4/img8.jpg", 0)
# 图像归一化
fi = img / 255.0
# 伽马变换
gamma = 0.4
out = np.power(fi, gamma)
cv.imshow("img", img)
cv.imshow("out", out)
cv.waitKey()
网友评论