一、灰度线性变换
图像的灰度线性变换是通过建立灰度映射来调整原始图像的灰度,从而改善图像的质量,凸显图像的细节,提高图像的对比度。灰度线性变换的计算公式如下所示
g(x)=αf(x)+β
(1)图像灰度上移变换:DB=DA + 50
(2)图像对比度增强变换:DB=DA * 1.5
(3)图像对比度减弱变换:DB=DA * 0.8
(4)图像灰度反色变换:DB=255 - DA
注意:由于图像的灰度值位于 0 至 255 区间之内,所以需要对灰度值进行溢出判断
有以下几种情况:
<1>当 α=1,b=0 时,保持原始图像
<2>当 α=1,b!=0 时,图像所有的灰度值上移或下移-----------(提升图像的亮度)
<3>当 α=-1,b=255 时,原始图像的灰度值反转
<4>当 α>1 时,输出图像的对比度增强
<5>当 0<α<1 时,输出图像的对比度减小
<6>当 α<0 时,原始图像暗区域变亮,亮区域变暗,图像求补
下面看具体的代码演示:
示例1:图像灰度上移变换
图像的所有灰度值上移 50,图像变得更白了。
注意:纯黑色对应的灰度值为 0,纯白色对应的灰度值为 255
import cv2import numpy as npfrom matplotlib import pyplot as pltimg=cv2.imread("lena.png")grayImg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#获取图像的高和宽grayImg_height=grayImg.shape[0]grayImg_width=grayImg.shape[1]#创建新图像newImg_move=np.zeros((grayImg_height,grayImg_width),np.uint8)#上移#DB=DA+50 上移for i in range(grayImg_height):for j in range(grayImg_width):if(int(grayImg[i,j]+50)>255):# 溢出判断gray=255else:gray=int(grayImg[i,j]+50)newImg_move[i,j]=np.uint8(gray)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题#原始图像img0=plt.subplot(1,2,1)img0.set_title("原始图像")plt.imshow(grayImg,cmap="gray")plt.xticks([])plt.yticks([])# newImg_move 上移img1=plt.subplot(1,2,2)img1.set_title("灰色上移变换")plt.imshow(newImg_move,cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
示例2:图像对比度增强变换
import cv2import numpy as npfrom matplotlib import pyplot as pltimg=cv2.imread("lena.png")grayImg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#获取图像的高和宽grayImg_height=grayImg.shape[0]grayImg_width=grayImg.shape[1]#创建新图像newImg_increase=np.zeros((grayImg_height,grayImg_width),np.uint8)#对比度增强# DB=DA*1.5 对比度增强for i in range(grayImg_height):for j in range(grayImg_width):if(int(grayImg[i,j]*1.5)>255):gray=255else:gray=int(grayImg[i,j]*1.5)newImg_increase[i,j]=np.uint8(gray)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题#原始图像img0=plt.subplot(1,2,1)img0.set_title("原始图像")plt.imshow(grayImg,cmap="gray")plt.xticks([])plt.yticks([])# newImg_increase 对比度增强img2=plt.subplot(1,2,2)img2.set_title("对比度增强")plt.imshow(newImg_increase,cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
示例3:图像对比度减弱变换
import cv2import numpy as npfrom matplotlib import pyplot as pltimg=cv2.imread("lena.png")grayImg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#获取图像的高和宽grayImg_height=grayImg.shape[0]grayImg_width=grayImg.shape[1]#创建新图像newImg_decrease=np.zeros((grayImg_height,grayImg_width),np.uint8)#对比度减弱# DB=DA*0.8 对比度减弱for i in range(grayImg_height):for j in range(grayImg_width):gray=int(grayImg[i,j])*0.8newImg_decrease[i,j]=np.uint8(gray)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题#原始图像img0=plt.subplot(1,2,1)img0.set_title("原始图像")plt.imshow(grayImg,cmap="gray")plt.xticks([])plt.yticks([])# newImg_decrease 对比度减弱img3=plt.subplot(1,2,2)img3.set_title("对比度减弱")plt.imshow(newImg_decrease,cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
示例4:图像灰度反色变换
import cv2import numpy as npfrom matplotlib import pyplot as pltimg=cv2.imread("lena.png")grayImg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#获取图像的高和宽grayImg_height=grayImg.shape[0]grayImg_width=grayImg.shape[1]#创建新图像newImg_reverse=np.zeros((grayImg_height,grayImg_width),np.uint8)#反转/求补# DB=255-DA 反转/求补for i in range(grayImg_height):for j in range(grayImg_width):gray=255-int(grayImg[i,j])newImg_reverse[i,j]=np.uint8(gray)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题#原始图像img0=plt.subplot(1,2,1)img0.set_title("原始图像")plt.imshow(grayImg,cmap="gray")plt.xticks([])plt.yticks([])# newImg_reverse 反转/求补img4=plt.subplot(1,2,2)img4.set_title("图像灰度反色变换")plt.imshow(newImg_reverse,cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
下面来看一个总体的代码演示:
import cv2import numpy as npfrom matplotlib import pyplot as pltimg=cv2.imread("lena.png")grayImg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)#获取图像的高和宽grayImg_height=grayImg.shape[0]grayImg_width=grayImg.shape[1]#创建新图像newImg_move=np.zeros((grayImg_height,grayImg_width),np.uint8)#上移newImg_reverse=np.zeros((grayImg_height,grayImg_width),np.uint8)#反转/求补newImg_increase=np.zeros((grayImg_height,grayImg_width),np.uint8)#对比度增强newImg_decrease=np.zeros((grayImg_height,grayImg_width),np.uint8)#对比度减弱#DB=DA+50 上移for i in range(grayImg_height):for j in range(grayImg_width):if(int(grayImg[i,j]+50)>255):# 溢出判断gray=255else:gray=int(grayImg[i,j]+50)newImg_move[i,j]=np.uint8(gray)# DB=255-DA 反转/求补for i in range(grayImg_height):for j in range(grayImg_width):gray=255-int(grayImg[i,j])newImg_reverse[i,j]=np.uint8(gray)# DB=DA*1.5 对比度增强for i in range(grayImg_height):for j in range(grayImg_width):if(int(grayImg[i,j]*1.5)>255):gray=255else:gray=int(grayImg[i,j]*1.5)newImg_increase[i,j]=np.uint8(gray)# DB=DA*0.8 对比度减弱for i in range(grayImg_height):for j in range(grayImg_width):gray=int(grayImg[i,j])*0.8newImg_decrease[i,j]=np.uint8(gray)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题imgs=[grayImg,newImg_move,newImg_increase,newImg_decrease,newImg_reverse]titles=["原始图像","灰色上移变换","对比度增强变换","对比度减弱变换","灰度反色变换"]for i in range(5):img0=plt.subplot(2,3,i+1)img0.set_title(titles[i])plt.imshow(imgs[i],cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
二、灰度非线性变换
(1)Gamma / 指数变换
Gamma变换是非线性变换,使输出图像灰度值与输入图像灰度值呈指数关系,公式见下图:
Gamma 变换就是用来图像增强,其提升了暗部细节,即通过非线性变换,让图像从曝光强度的线性响应变得更接近人眼感受的响应,即将漂白(相机曝光)或过暗(曝光不足)的图片,进行矫正
当 gamma 值小于 1 时,图像的整体亮度值得到提升,同时低灰度处的对比度得到增加,更利于分辩低灰度值时的图像细节
Gamma变换的基本形式
大于 1 时,对图像的灰度分布直方图具有拉伸作用(使灰度向高灰度值延展),
小于 1 时,对图像的灰度分布直方图具有收缩作用(是使灰度向低灰度值方向靠拢)
换一种说法,就是
当γ>1时,会拉伸图像中灰度级较高的区域,压缩灰度级较低的部分。
当γ<1时,会拉伸图像中灰度级较低的区域,压缩灰度级较高的部分。
当γ=1时,该灰度变换是线性的,此时通过线性方式改变原图像。
代码演示:
# Gamma变换--非线性变换import cv2from skimage import exposurefrom matplotlib import pyplot as pltimg=cv2.imread("airport.png")grayImg=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)gamma_img=exposure.adjust_gamma(grayImg,5)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题img1=plt.subplot(1,2,1)img1.set_title("原始图像")plt.imshow(grayImg,cmap="gray")plt.xticks([])plt.yticks([])img2=plt.subplot(1,2,2)img2.set_title("Gamma变换")plt.imshow(gamma_img,cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
(2)对数变换
图像灰度的对数变换是另外一种常见的灰度非线性变化。一般表示如公式所示
其中c为尺度比较常数,DA为原始图像灰度值,DB为变换后的目标灰度值。
对数变换对于整体对比度偏低并且灰度值偏低的图像增强效果较好。这种变换可用于增强图像的暗部细节,从而用来扩展被压缩的高值图像中的较暗像素
# 对数变换import cv2import numpy as npfrom matplotlib import pyplot as plt#对数变换def log(c,DA_img):new_img=c*np.log(1.0+DA_img)new_img=np.uint8(new_img+0.5)return new_imgimg=cv2.imread("street.jpg")gray_img=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)new_img=log(30,gray_img)plt.rcParams['font.sans-serif']=['SimHei']#解决中文乱码问题img1=plt.subplot(1,2,1)img1.set_title("原始图像")plt.imshow(gray_img,cmap="gray")plt.xticks([])plt.yticks([])img2=plt.subplot(1,2,2)img2.set_title("对数变换")plt.imshow(new_img,cmap="gray")plt.xticks([])plt.yticks([])plt.show()cv2.waitKey(0)
运行结果:
文中描述不恰当之处,请大家批评指正,谢谢,大家共同进步。
如果觉得《图像处理 | 灰度线性变换与非线性变化》对你有帮助,请点赞、收藏,并留下你的观点哦!