文章目录
一、图像预处理
6 图像色彩空间转换
6.3灰色/BGR/HSV相互转化
- 语法
new_img = cv.cvtColor(image, 类型)
- 参数:
- image:图片
- 类型
cv2.COLOR_BGR2GRAY
:将 BGR 图像转换为灰度图像。cv2.COLOR_BGR2HSV
:将 BGR 图像转换为 HSV 图像。cv2.COLOR_BGR2RGB
:将 BGR 图像转换为 RGB 图像。
7 彩图转灰图方法
这种做法在图像处理和计算机视觉领域非常常见。
灰度图与彩色图最大的不同就是:彩色图是由R、G、B三个通道组成,而灰度图只有一个通道,也称为单通道图像,所以彩色图转成灰度图的过程本质上就是将R、G、B三通道合并成一个通道的过程。本实验中一共介绍了三种合并方法,分别是最大值法、平均值法以及加权均值法。
7.1 最大值法
对于彩色图像的每个像素,它会从R、G、B三个通道的值中选出最大的一个,并将其作为灰度图像中对应位置的像素值。
7.2 平均值法
对于彩色图像的每个像素,它会将R、G、B三个通道的像素值全部加起来,然后再除以三,得到的平均值就是灰度图像中对应位置的像素值。
7.3 加权均值法
对于彩色图像的每个像素,它会按照一定的权重去乘以每个通道的像素值,并将其相加,得到最后的值就是灰度图像中对应位置的像素值。本实验中,权重的比例为: R乘以0.299,G乘以0.587,B乘以0.114,这是经过大量实验得到的一个权重比例,也是一个比较常用的权重比例。
所使用的权重之和应该等于1。这是为了确保生成的灰度图像素值保持在合理的亮度范围内,并且不会因为权重的比例不当导致整体过亮或过暗。
7.4 案例
import cv2 as cv
import numpy as np
# 读取图片
pig = cv.imread("./images/pig.png")
h, w, _ = pig.shape # 宽,长
# 创建灰度图
gray = np.zeros((h, w), dtype=np.uint8)
# 权重
wr, wg, wb = 0.299, 0.587, 0.114
# 遍历像素点,转化生成灰图
for i in range(h):
for j in range(w):
# 取最大值
gray[i, j] = np.max(cat[i, j])
# 取平均值
gray[i, j] = np.mean(pig[i, j])
# 取加权平均值--int目的是因为cv2.imwrite()函数的参数要求是uint8类型
gray[i, j] = int(wb * pig[i, j][0] + wg * pig[i, j][1] + wr * pig[i, j][2])
cv.imshow("gray", gray)
cv.imshow("pig", pig)
cv.waitKey(0)
cv.destroyAllWindows()
8 图像二值化处理
目的:将某张图像的所有像素都改成 0 或 255 。
二值化的过程:就是将一张灰度图上的像素根据某种规则修改为0和maxval(maxval表示最大值,一般为255,显示白色)两种像素值
特点
- 简便:降低计算量和计算需求,加快处理速度。
- 节约资源:二值图像占用空间远小于彩色图。
- 边缘检测:二值化常作为边缘检测的预处理步骤,因为简化后的图易于识别出轮廓和边界。
全局阈值法。
_,binary = cv2.threshold(img,thresh,maxval,type)
img
:输入图像,要进行二值化处理的灰度图。thresh
:设定的阈值。maxval
:最大像素值type
:阈值处理的类型。(下面在介绍)- 返回值:
- 第一个值:阈值
- 第二个值:二值化后的图像矩阵。与输入图像尺寸相同。
8.1 阈值法(type=cv2.THRESH_BINARY)
- 原理:每一个像素点与阈值判断,小于取0,大于阈值取阈值。
8.2 反阈值法(THRESH_BINARY_INV)
- 原理:每一个像素点与阈值判断,小于阈值取阈值,大于阈值取0。
8.3 截断阈值法(THRESH_TRUNC)
原理:每一个像素点与阈值判断,大于阈值修改为阈值,小于等于阈值的部分不变。
当阈值为255时,图片不发生变化。
8.4 低阈值零处理(THRESH_TOZERO)
- 原理:像素值小于等于阈值的部分被置为0(也就是黑色),大于阈值的部分不变。
8.5 超阈值零处理(THRESH_TOZERO_INV)
- 原理:每个像素与阈值进行比较,像素值大于阈值的部分置为0(也就是黑色),像素值小于等于阈值的部分不变。
8.6 OTSU阈值法
- 语法: type = cv2.THRESH_OTS
- 结合了阈值法(默认)和反阈值法
- type = cv2.THRESH_OTS + cv2.THRESH_BINARY
- 自动计算中最佳的阈值,所以传入的阈值无效。
OTSU算法是通过一个值将这张图分前景色和背景色(也就是灰度图中小于这个值的是一类,大于这个值的是一类。例如,如果你设置阈值为128,则所有大于128的像素点可以被视作前景,而小于等于128的像素点则被视为背景。),通过统计学方法(最大类间方差)来验证该值的合理性,当根据该值进行分割时,使用最大类间方差计算得到的值最大时,该值就是二值化算法中所需要的阈值。通常该值是从灰度图中的最小值加1开始进行迭代计算,直到灰度图中的最大像素值减1,然后把得到的最大类间方差值进行比较,来得到二值化的阈值。以下是一些符号规定:
T:阈值(决定怎么分割前景和北京)
N 0 N_{0} N0:前景像素点数
N 1 N_{1} N1:背景像素点数
ω 0 \omega_{0} ω0:前景的像素点数占整幅图像的比例
ω 1 \omega_{1} ω1:背景的像素点数占整幅图像的比例
U 0 \mathcal{U_{0}} U0:前景的平均像素值
U 1 \mathcal{U_{1}} U1:背景的平均像素值
U \mathcal{U} U:整幅图的平均像素值
rows×cols:图像的行数和列数
下面举个例子,有一张大小为4×4的图片,假设阈值T为1,那么:
也就是这张图片根据阈值1分为了前景(像素为2的部分)和背景(像素为0)的部分,并且计算出了OTSU算法所需要的各个数据,根据上面的数据,我们给出计算类间方差的公式:
g = ω 0 ( μ 0 − μ ) 2 + ω 1 ( μ 1 − μ ) 2 g=\omega_{0}(\mu_{0}-\mu)^{2}+\omega_{1}(\mu_{1}-\mu)^{2} g=ω0(μ0−μ)2+ω1(μ1−μ)2
g就是前景与背景两类之间的方差,这个值越大,说明前景和背景的差别就越大,效果就越好。OTSU算法就是在灰度图的像素值范围内遍历阈值T,使得g最大,基本上双峰图片的阈值T在两峰之间的谷底。
8.7 自适应二值化
与二值化算法相比,自适应二值化更加适合用在明暗分布不均的图片。
- 语法:只有一个返回值
new_img = cv2.adaptiveThreshold(image, 255, adaptiveMethod=cv2.ADAPTIVE_THRESH_MEAN_C,
thresholdType=cv2.THRESH_BINARY, blockSize=7, c=10)
其中各个参数的含义如下:
maxval
:最大阈值adaptiveMethod
:小区域阈值的计算方式:ADAPTIVE_THRESH_MEAN_C
:小区域内取均值(方法1)ADAPTIVE_THRESH_GAUSSIAN_C
:小区域内加权求和,权重是个高斯核(方法2)thresholdType
:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是阈值法和反阈值法blockSize
:处理核大小c
:最终阈值等于小区域计算出的阈值再减去此值
下面介绍一下这两种方法。
1. 取均值
- 每一个像素点的计算过程:
- 待计算像素点为中心,取3*3的区域(不够就使用边缘填充补齐)
- 然后卷积核与区域一一对应相乘再累加 -C(如下黑图)
2. 加权求和
具体原理,这里不需要理解。
某像素点的阈值计算过程如下图所示:
8.9 案例
import cv2 as cv
img = cv.imread('./images/flower.png')
img = cv.resize(img, (360, 360))
# 灰度化
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)
# 阈值发
_, binary = cv.threshold(gray, 127,255,cv.THRESH_BINARY)
# 反阈值法
_, binary2 = cv.threshold(gray, 127,255,cv.THRESH_BINARY_INV)
# 截断阈值法
_, binary3 = cv.threshold(gray, 127,255,cv.THRESH_TRUNC)
# 低阈值0处理法
_, binary4 = cv.threshold(gray, 127,255,cv.THRESH_TOZERO)
# 高阈值0处理法
_, binary5 = cv.threshold(gray, 127,255,cv.THRESH_TOZERO_INV)
# OTSU阈值法
_, binary6 = cv.threshold(gray, 127,255,cv.THRESH_OTSU+cv.THRESH_BINARY)
# 自适应二值法-取均值
binary7 = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_MEAN_C, cv.THRESH_BINARY, 5, 2)
# 自适应二值法-加权平均值
binary8 = cv.adaptiveThreshold(gray, 255, cv.ADAPTIVE_THRESH_GAUSSIAN_C, cv.THRESH_BINARY, 5, 2)
cv.imshow('binary', binary8)
cv.imshow('img', img)
cv.waitKey(0)
cv.destroyAllWindows()