目录
-
1、灰度化的常用方法
-
2、了解灰度变换应用场景并加以实现:反转、对数变化、幂律变化、分段性变换
-
3、练习图像直方图,直方图匹配
-
4、了解二值化常用方法阈值选取原理和方法,并练习实现对比效果,熟悉各自的应用场景
一、灰度化
1、原理
由于图片是由像素点组成,每个点是由RGB三个分量组成的,范围均为0~255,灰度图是指只含亮度信息,不含有色彩信息的图像,灰度化处理是把含有亮度和色彩的图片变化为灰度图像的过程。只有在将图片灰度化之后才能进行一系列的单数值的变换。
2、灰度化常用三种方法:
- 1)平均值法 f(x,y) = (R(x,y) + G(x,y) + B(x,y))/3
-
- 最大值法 f(x,y) = max(R(x,y) + G(x,y) + B(x,y))
- 3)加权平均法 f(x,y) = 0.3R(x,y) + 0.59G(x,y) + 0.11B(x,y)
python- opencv自带的灰度处理代码如下:
import cv2
# 方法一,imread方法中的第二个参数给定为0,可以直接读入一张灰度图
gray_img = cv2.imread("img.jpg",0)
#方法二,使用cv2.cvtColor()图像转换方法,可以将彩色图转换为灰度图
img = cv2.imread("img.jpg")
print(img[0][0]) #[192 219 253]
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
print(gray_img[0][0]) # 226
# 可见opencv自带的加权平均法
原图:灰度图:
二、灰度变换
1、定义
灰度变换是指根据某种目标条件按一定变换关系逐点改变源图像中每一个像素灰度值的方法。目的是为了改善画质,使图像的显示效果更加清晰。 灰度变换主要针对独立的像素点进行处理,通过改变原始图像数据所占据的灰度范围而使图像在视觉上得到良好的改变。如果选择的灰度变换函数不同,即使是同一图像也会得到不同的结果。因此,选择灰度变换函数应该根据图像的性质和处理的目的来决定。选择的标准是经过灰度变换后,像素的动态范围增加,图像的对比度扩展,使图像变得更加清晰、细腻,容易识别。(选自百度百科)
2、基本的变换函数
在灰度变换中,r,s分别代表处理前后的像素值,可以据此来表示变换的函数
-
1)图像反转
根据变换,可以得到灰度级范围为[0,L-1]的图像的反转图像,由下式给出
s = L − 1 − r s = L -1 - r s=L−1−r
img = cv2.imread("img.jpg")
print(img[0][0])
# 灰度变换
gray_img = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
#图像反转
h,w = gray_img.shape
for i in range(h):
for j in range(w):
pixel = gray_img[i][j]
gray_img[i][j] = 255 - pixel
此方法处理适合用于增强嵌入在一幅图像的暗区域中的白色或灰色细节,特别是当黑色面积在尺寸上占主导地位时
灰度图像:反转结果:
- 2)对数变换
s = c l o g ( 1 + r ) s = clog(1+r) s=clog(1+r)
其中c为一个常数,并假设r ≥ \geq ≥ 0 。该变换将输入中范围较窄的低灰度值映射为输出中较宽范围的灰度值,相反的,对高的输入灰度值也是如此。使用这种类型的变换来扩展图像中的暗像素的值,同时压缩更高灰度级的值。反对数变换的作用与此相反
#代码实现
res = 42 * np.log(1.0 + img)
res = np.uint8(res + 0.5)
灰度图像:对数变换:
- 3)幂律变换
基本公式:
s
=
c
(
r
−
ϵ
)
γ
s = c(r-\epsilon)^\gamma
s=c(r−ϵ)γ
其中c和
γ
\gamma
γ为正常数,
ϵ
\epsilon
ϵ,为偏移量。
[外链图片转存失败(img-mYJgtczI-1564302414343)(F:\学习笔记\opencv学习\20190727181932.png)]
伽马变换可以很好地拉伸图像的对比度,扩展灰度级。
由图可知,
当图像的整体灰度偏暗时,选择γ<1,可以使图像增亮;
当图像的整体灰度偏亮时,选择γ>1,可以使图像变暗,
提高图像的对比度,凸显细节。
用于图像获取、打印和显示的各种设备根据幂律来产生响应,用于校正这些幂律响应现象的处理称为伽马校正。
适用范围:伽马校正,对比增强
import cv2
import numpy as np
impor math
img = cv2.imread("img.jpg")
def gammaTranform(c,gamma,img):
#读取图片的高,宽,通道
h,w,n = img.shape
#构造一个与输入图片相同的模板图像
new_img = np.zeros((h,w,n),dtype=np.float32)
#构造每个像素点的幂律变换的值
for i in range(h):
for j in range(w):
new_img[i,j,0] = c*math.pow(img[i, j, 0], gamma)
new_img[i,j,1] = c*math.pow(img[i, j, 1], gamma)
new_img[i,j,2] = c*math.pow(img[i, j, 2], gamma)
#归一化处理,将计算后的值重新归到(0,255)之间
cv2.normalize(new_img,new_img,0,255,cv2.NORM_MINMAX)
new_img = cv2.convertScaleAbs(new_img)
return new_img
res = gammaTranform(1,2.4,img)
cv2.imshow("img",res)
原图:变换后:
- 4)分段线性变换
分段线性变换的形式可以是任意复杂的,可以根据自己的需求对图片进行变换,这是优点,也是缺点,技术说明要求用户输入。
对比度拉伸
最简单的分段线性函数之一,用来扩展图像灰度级动态范围,可以跨越记录介质和显示装置的全部灰度范围。当图片的灰度值趋于某一个值附近时,图片可能显示比较模糊,棱角不分明。对比度拉伸可以将差值较小的点位变化的大一些,有利于区分不同物体。
灰度级分层
突出图像中特定灰度范围,大多数为以下两种基本方法的变形。一种是将感兴趣范围内的所有灰度值显示为一个值,二其他灰度值显示为另一个值。另一种方法是将需要的范围变亮或者更暗,其他部分不变。
比特平面分层
像素是由比特组成的数字。在256级灰度图像中,每个像素的灰度由8比特组成。代替突出灰度级范围,可突出特定比特来为整个图像外观作出贡献
示例:
上边图例显示了0~7直接转换位三层比特平面的过程,高位显示的数字比较大,包含的信息多,低位多体现于细节。
三、直方图
1、定义
灰度级范围位[0,L-1]的数字图像的直方图是离散函数 h ( r k ) = n k h(r_k)=n_k h(rk)=nk,其中 r k r_k rk是第k级灰度值, n k n_k nk是图像中灰度为 r k r_k rk的像素个数。
性质
- 1、直方图反映了图像中的灰度分布规律。它描述每个灰度级具有的像元个数,但不包含这些像元在图像中的位置信息。
- 2、任何一幅特定的图像都有唯一的直方图与之对应,但不同的图像可以有相同的直方图。
- 3、如果一幅图像有两个不相连的区域组成,并且每个区域的直方图已知,则整幅图像的直方图是该两个区域的直方图之和
应用
-
1、对于每幅图像都可做出其灰度直方图。
-
2、根据直方图的形态可以大致推断图像质量的好坏。由于图像包含有大量的像元,其像元灰度值的分布应符合概率统计分布规律。假定像元的灰度值是随机分布的,那么其直方图应该是正态分布。
-
3、图像的灰度值是离散变量,因此直方图表示的是离散的概率分布。若以各灰度级的像元数占总像元数的比例值为纵坐标轴做出图像的直方图,将直方图中各条形的最高点连成一条外轮廓线,纵坐标的比例值即为某灰度级出现的概率密度,轮廓线可近似看成图像相应的连续函数的概率分布曲线。
代码示例
import cv2
import numpy as np
from matplotlib import pyplot as plt
img = cv2.imread("img.jpg",0)
#1.使用opencv自带的的求直方图方法
hist = cv2.calcHist([img],[0],None,[256],[0,256])
#2.使用numpy统计直方图函数方法
hist, bins = np.histogram(img.ravel(),256,[0,256])
plt.hist(hist)
plt.show()
# 使用掩膜,需要先构建区域,再传入方法中
mask = np.zeros(img.shape[:2], np.uint8)
mask[100:300, 100:400] = 255
hist_mask = cv2.calcHist([img],[0],mask,[256],[0,256])
使用掩膜时可以之统计图像中的roi区域,将构建好的区域传入opencv自带的直方图构建函数中即可。
2、直方图均衡化
当图像的大多数像素点的像素值都集中在一个像素值的范围内,说明图像中的层次不明显,图像中物体分离不明显。例如,如果一幅图片整体很亮,那所有的像素值应该都会很高。但是一副高质量的图像的像素值分布应该很广泛。所以你应该把它的直方图做一个横向拉伸,这就是直方图均衡化要做的事情。通常情况下这种操作会改善图像的对比度。
代码示例
import cv2
import numpy as np
img = cv2.imread("img.jpg",0)
#使用oepncv自带的均衡化方法进行均衡化操作
equ = cv2.equalizeHist(img)
res = np.hstack((img,equ))
cv2.imshow("img", res)
示例图:
3、直方图匹配
定义
直方图匹配又称为直方图规定化,是指将一幅图像的直方图变成规定形状的直方图而进行的图像增强方法。即将某幅影像或某一区域的直方图匹配到另一幅影像上。使两幅影像的色调保持一致。可以在单波段影像直方图之间进行匹配,也可以对多波段影像进行同时匹配。两幅图像比对前,通常要使其直方图形式一致。
当一幅图像被描述为直方图后,所有的空间信息都丢失了。直方图描述了每个灰度级具有的像素个数,但无法为这些像素在图像中的位置提供任何线索。即便如此,直方图仍有一些有用的性质:
(1)一个特定的图像有唯一的直方图,但两幅图像的直方图相同并不能说明图像相同。
(2)在图像中特定对象的直方图是平移不变的。
(3)在图像中特定对象的直方图是旋转不变的。
(4)如果一幅图像由两个不连接的区域组成,且每个区域的直方图已知,则整幅图像的直方图是两个区域的直方图之和。显然,该结论可以推广到任何数目的不连接区域的情形。(选自百度百科)
四、二值化
图像二值化是将图像上的像素点的灰度值设置为0或255,也就是将整个图像呈现出明显的黑白效果的过程。首先,图像的二值化有利于图像的进一步处理,使图像变得简单,而且数据量减小,能凸显出感兴趣的目标的轮廓。其次,要进行二值图像的处理与分析,首先要把灰度图像二值化,得到二值化图像
代码示例
import cv2
import numpy as np
img = cv2.imread('img.jpg', 0)
#img --原灰度图片
#阈值 这里将80 设置为阈值,大于80的全部变为后边给定的255,小于80的转为0
#最大值 255
#格式cv2.THRESH_BINARY 二值处理
ret,bin = cv2.threshold(img,80,255,cv2.THRESH_BINARY)
# 自动阈值
bins =cv2.adaptiveThreshold(img,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,\
cv2.THRESH_BINARY,25,10)
cv2.imshow("img", bin)
图片示例
二值化处理格式选择
阈值类型图示