1、线性变换
- 灰度的线性变换将图像中的所有像素点的值按线性变换函数进行变换。
- 在曝光不足或过度的情况下,图像的灰度值会局限在一个很小的范围内,这时在显示器上看到的将是一个模糊不清、似乎没有层次的图像。
- 针对这一情况,使用一个线性单值函数对图像内的每一个像素做线性扩展,将有效地改善图像的视觉效果。
- 线性变换原理如图所示。
根据上图,以曝光不足为例,假设原图像f(x,y)的灰度范围是[a,b],期望经过灰度线性变换后得到的图像g(x,y)灰度范围是[c,d],则线性变换过程如下式所示。
更普遍的数学表示是:
其中,g(x, y)为变换后的值,a为系数,b为常数项。
import cv2
import numpy as np
img = cv2.imread('img.jpg')
cv2.imshow('image', img)
linear_img = 1.5 * img + 10
linear_img.max()
linear_img[linear_img>255] = 255
linear_img = np.asarray(linear_img, np.uint8)
cv2.imshow('linear image', linear_img)
cv2.waitKey(0)
2、非线性变换
- 使用非线性函数对图像灰度进行映射,可实现图像灰度的非线性变换,常用的有对数函数和指数函数典型的有对数函数(图(a))、指数函数(图(b))等。
2.1 对数变换
- 对数变换可以增强低灰度值的像素,扩展低灰度区,压制高灰度值的像素,当希望对图像的低灰度区进行较大的拉伸而对高灰度区压缩时,可采用这种变换。
- 因为对数曲线在像素值较低的区域斜率大,在像素值较高的区域斜率较小,因此图像通过对数变换后,较暗区域的对比度将有所提高。可用于加强图像的暗部细节,从而用来扩展被压缩的高值图像中的较暗像素。
log_img = 10 + 20 * np.log(img+5)
log_img[log_img>255] = 255
log_img = np.asarray(log_img, np.uint8)
cv2.imshow('log_image', log_img)
cv2.imshow('image', img)
cv2.waitKey(0)
2.2 指数变换
- 指数变换(伽马变换)是用来图像加强,提高暗部细节,简单来讲就是经过非线性变换,让图像从曝光强度的线性响应变得更接近人眼感觉的响应,即将漂白(相机曝光)或过暗(曝光不足)的图片,进行矫正。
- 指数变换的表达式如式所示。
gamma_img = 10 * np.power(img, 1.1)
gamma_img[gamma_img>255] = 255
gamma_img = np.asarray(gamma_img, np.uint8)
cv2.imshow('gamma_image', gamma_img)
cv2.imshow('image', img)
cv2.waitKey(0)
3、直方图处理
- 图像的灰度直方图如图所示,用横坐标表示灰度级,纵坐标表示各个灰度级出现的像素数。
- 通过灰度直方图可以反映图像灰度的统计特性,以及图像中不同灰度值的面积或像素数在整幅图像中所占的比例。
- 如图所示的两个灰度直方图中,若直方图密集地分布在很窄的区域之内,说明图像的对比度很低;若直方图有两个峰值,则说明图像中有可能存在两种不同亮度的区域。
- 直方图是图像的一维特征,一个图像具有唯一的直方图。图像直方图灰度级的分布形态可以提供图像信息的许多特征,为图像分析提供一个有力的论据。
- 查看图像的直方图分布: plt.hist(src.ravel(),hitsizes, ranges, color)
import cv2
import numpy as np
import matplotlib.pyplot as plt
img = cv2.imread('img.jpg')
plt.hist(img.ravel(), 256, [0,255])
3.1 直方图均衡化
- 直方图均衡的基本思想是对原始图像中的像素灰度做某种映射变换,使变换后图像灰度的概率密度是均匀分布的,即变换后图像是一幅灰度级均匀分布的图像,这意味着图像灰度的动态范围得到了增加,从而提高图像的对比度。
- 实现直方图均衡可以使用:cv2.equalizeHist(src),
src要求是单通道图像。
对灰度图进行直方图均衡化如下:
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
img_hist = cv2.equalizeHist(img_gray)
cv2.imshow('gray', img_gray)
cv2.imshow('hist', img_hist)
cv2.waitKey(0)
3.2 彩色图像直方图均衡化
- 若要对多通道的图像进行直方图均衡,首先将原图的通道单独分割,然后分别进行直方图均衡,最后把处理完成的各个单通道图像合并即可。
- 通道分割可以通过cv2.split()实现,比如:b, g, r = cv2.split(img)
- 通道合并类似数组的合并,通过cv2.merge()实现,比如:cv2.merge((bH, gH, rH))
def EqualizeHist(img):
(b, g, r) = cv2.split(img)
bh = cv2.equalizeHist(b)
gh = cv2.equalizeHist(g)
rh = cv2.equalizeHist(r)
result = cv2.merge((bh, gh, rh))
return result
img_equal = EqualizeHist(img)
cv2.imshow('image', img)
cv2.imshow('image_equal', img_equal)
cv2.waitKey(0)
plt.hist(img_equal.ravel(), 256, [0,255])
4、二值化
- 二值化是值将图像只保留黑白二色,非黑即白。
- 彩色图像:三个通道,像素值0-255,0-255,0-255,所以可以有2^24位空间
- 灰度图像:一个通道,像素值0-255, 所以有256种颜色
- 二值图像:只有两种颜色,黑和白,255白色,0黑色
- 图像二值化(Image Binarization)就是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。
- 在数字图像处理中,二值图像占有非常重要的地位,图像的二值化使图像中数据量大为减少,从而能凸显出目标的轮廓。
- OpenCV中有两个方法可以实现图片的二值化:
• 阈值截断:选取一个全局阈值,以此值为界限把整幅图像分成非黑即白的二值图像。
• cv2.threshold(src, thresh, maxval, type)
img = cv2.imread('img.jpg')
img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
_, img_binary = cv2.threshold(src=img_gray, thresh=50, maxval=255,
type=cv2.THRESH_BINARY)
cv2.imshow('image_binary', img_binary)
cv2.imshow('image', img)
cv2.waitKey(0)
- OpenCV中有两个方法可以实现图片的二值化:
• 自适应阈值:自适应阈值可以看成一种局部阈值,通过规定一个区域大小,比较这个点与区域大小里面像素点的平均值(或者其他特征)的大小关系确定这个像素点是属于黑或者白。
• cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C)
adapt_thres = cv2.adaptiveThreshold(src=img_gray, maxValue=255,
adaptiveMethod=cv2.ADAPTIVE_THRESH_GAUSSIAN_C,
thresholdType=cv2.THRESH_BINARY,
blockSize=9, C=3)
cv2.imshow('adapt image', adapt_thres)
cv2.waitKey(0)