本文参考了该作者的笔记,如果想更深入地了解,可以去看原作:https://note.youdao.com/ynoteshare1/index.html?id=2b60df50f548a84923e7e201798dd390&type=note#/
一、基本灰度变换函数
1.常用的基本函数有三类:线性函数,对数函数(对数和反对数)和幂律函数(n次幂和n次根),正如下图所示,下图刚看可能会有点乱,我们来分析一下。
首先横纵坐标分别为输入的像素值和输出的像素值。
所谓的反转变换便是将图像的灰度值最大和最小值颠倒过来,即[0,255]转化为[255,0],转化成函数便是斜率为-1的线性函数。恒等变换不必多说,就是什么都不变。
对数变换:以L/4处为例,图像灰度范围[0,L/4]经过对数变换之后输出[0,3L/4],可见将灰度值较低的像素进行了增强,而对灰度值较高的像素值增强效果不明显,表现为压缩。反对数变换顾名思义,不必多说。
幂律函数变换根据根和幂的不同,效果也有很大的差别,可以类比于对数变换。
在opencv中,很多函数并没有现有的库,需要自己编写一下:
1.反转变换
适用于增强嵌入在一幅图像暗区域中的白色或灰色细节。图像灰度级范围为[0,L-1],变换公式为:
代码:
img = cv2.imread('F:\python\work\cv_learn\lena.jpg',0)
thresh,out = cv2.threshold(img,128,255,cv2.THRESH_BINARY)
cv2.imshow('output0', out)
def reverse(img):
output = 255 - img
return output
out2 = reverse(out)
cv2.imshow('output1', out2)
效果如图:
2.对数变换
对数变换可以拉伸范围较窄的低灰度值,同时压缩范围较宽的高灰度值。可以用来扩展图像中的暗像素值,同时压缩亮像素值。
其中c为常数,r加1可以使函数向左移一个单位,得到的s均大于0。
代码如下:
def log(c, img):
output_img = c*np.log(1.0+img)
output_img = np.uint8(output_img+0.5)
return output_img
img = cv2.imread('F:\python\work\cv_learn\lena.jpg',0)
cv2.imshow('imput', img)
out2 = log(20,img)
cv2.imshow('output', out2)
cv2.waitKey(0)#保持图像
效果如下:
3.伽马变换
变换的基本形式为:
c和γ为正常数
对于不同的γ值,有不同的曲线。
多用在图像整体偏暗,扩展灰度级。另外一种情况是,图像有“冲淡”的外观(很亮白)需要压缩中高以下的大部分的灰度级。伽马变换对于图像对比度偏低,并且整体亮度值偏高(对于于相机过曝)情况下的图像增强效果明显。
代码:
img = cv2.imread('F:\python\work\cv_learn\gamma.png',1)
cv2.imshow('imput', img)
def gamma(img, c, v):
lut = np.zeros(256, dtype=np.float32)
for i in range(256):
lut[i] = c * i ** v
output_img = cv2.LUT(img, lut)
output_img = np.uint8(output_img+0.5) # 这句一定要加上
return output_img
out2 = gamma(img,0.00000005,4.0)
cv2.imshow('output', out2)
cv2.waitKey(0)#保持图像
运行效果(因为没有合适的图片,直接搬运的云笔记上面的):
4.分段线性变换
分段线性变换原理也比较简单,如下图所示,就是将图像的像素值按照一定的线性规律进行变换
关键是要根据阈值编写自己的函数。
def SLT(img, x1, x2, y1, y2):
lut = np.zeros(256)
for i in range(256):
if i < x1:
lut[i] = (y1/x1)*i
elif i < x2:
lut[i] = ((y2-y1)/(x2-x1))*(i-x1)+y1
else:
lut[i] = ((y2-255.0)/(x2-255.0))*(i-255.0)+255.0
img_output = cv2.LUT(img, lut)
img_output = np.uint8(img_output+0.5)
return img_output
img = cv2.imread(r'F:\python\work\cv_learn\3.png',1)
cv2.imshow('input',img)
output_img = SLT(img, 100, 160, 30, 230)
# out2 = gamma(img,0.00000005,4.0)
cv2.imshow('output', output_img)
cv2.waitKey(0)#保持图像
处理效果如下:
5.拉普拉斯算子增强
拉普拉斯算子增强便是通过定义一个卷积核,将该卷积核与原图像进行卷积操作,来达到锐化增强图像的目的。
代码实现:
img = cv2.imread(r'F:\python\work\cv_learn\clipboard.png',1)
cv2.imshow('input',img)
kernel = np.array([[0, -1, 0], [0, 5, 0], [0, -1, 0]])#定义卷积核
imageEnhance = cv2.filter2D(img,-1, kernel)#进行卷积运算
cv2.imshow('output', imageEnhance)
cv2.waitKey(0)#保持图像
cv2.filter2D(src,ddepth, kernel)函数用于进行卷积操作,第一个参数是要卷积的图像,第二个函数是图像深度,最后一个参数是卷积核。深度为-1时,表示与原图像深度相同。
处理效果如图:
6.直方图均衡增强
直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。、
opencv自带的函数只能进行一个通道的增强,下面是彩色图像的直方图增强:
img = cv2.imread(r'F:\python\work\cv_learn\clipboard.png',1)
cv2.imshow('input',img)
result = img.copy()
for j in range(3):
result[:, :, j] = cv2.equalizeHist(img[:,:,j])
cv2.imshow('Result1', result)
cv2.waitKey(0)
效果如下: