文章目录
- 前言
- 一、图像颜色转换
- 1.HSV颜色空间
- 2.颜色转换
- 二、灰度化
- 1.最大值法
- 2.平均值法
- 3.加权均值法
- 三、二值化
- 1.全局阈值法
- 1.阈值法(THRESH_BINARY)
- 2.反阈值法(THRESH_BINARY_INV)
- 3.截断阈值法(THRESH_TRUNC)
- 4.低阈值零处理(THRESH_TOZERO)
- 5.超阈值零处理(THRESH_TOZERO_INV)
- 6.OTSU算法
- 7.代码展示
- 2.局部阈值法
前言
- 通过今天的学习,我掌握了OpenCV中有关图像颜色转换,灰度化,二值化的基本原理和操作方式
一、图像颜色转换
- 我们常见的单张图像,不仅可以用 RGB 颜色空间来描述其色彩信息 ,还可以用 HSV 颜色空间来表示
1.HSV颜色空间
- RGB颜色模型使用红、绿、蓝三原色的强度来表示颜色,是一种加色法模型,即颜色的混合是添加三原色的强度。而HSV颜色空间使用色调(Hue)、饱和度(Saturation)和亮度(Value)三个参数来表示颜色
- HSV颜色空间更加符合人类对颜色的感知方式
- 颜色调整更加直观,只需要调整色调和饱和度即可完成对图像颜色的调整
- 在图像处理中分割某种颜色物体时,只需在HSV空间中限定H的范围,而无需同时处理R、G、B三个通道的复杂组合,使用更加简便
2.颜色转换
- 我们可以将使用RGB颜色模型表示的图像转换为灰度图或者使用HSV颜色空间表示
- cv.cvtColor(img,code)
img = cv.imread('img\cat1.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY) #RBG转换为灰度图
hsv = cv.cvtColor(img,cv.COLOR_BGR2HSV) #RBG转换为HSV
cv.imshow('img',img)
cv.imshow('gray',gray)
cv.imshow('hsv',hsv)
cv.waitKey(0)
cv.destroyAllWindows()
二、灰度化
- 灰度化是图像处理以及计算机视觉的常用操作,就是将彩色图像转换为灰度图像的过程
- 灰度图只有一个通道,以下介绍三种方法进行灰度化
1.最大值法
- 顾名思义就是将RBG三通道中的最大值取出作为灰度图的像素值
img = cv.imread('img\cat1.png')
h,w,_ = img.shape
img1 = np.zeros((h,w),dtype=np.uint8)
for i in range(h):for j in range(w):arr = img[i][j]max_val = max(arr[0],arr[1],arr[2])img1[i][j] = max_val
cv.imshow('img1',img1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
2.平均值法
- 将RBG三通道的像素值取平均值取出作为灰度图的像素值
img = cv.imread('img\cat1.png')
h,w,_ = img.shape
img1 = np.zeros((h,w),dtype=np.uint8)
for i in range(h):for j in range(w):arr = img[i][j]mean_val = np.uint8(int(img[i][j][0])+int(img[i][j][1])+int(img[i][j][2])//3)img1[i][j] = max_val
cv.imshow('img1',img1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
tips:在之前的章节提到,图像是uint8类型的数组,使用Numpy的加法是取模运算,使用int函数进行类型转换可以避免数据溢出
3.加权均值法
- 与均值法类似,只不过为每个通道的像素值加入了权重
img = cv.imread('img\cat1.png')
h,w,_ = img.shape
wr,wg,wb = 0.3,0.5,0.2
img1 = np.zeros((h,w),dtype=np.uint8)
for i in range(h):for j in range(w):val = round(wb*img[i][j][0] + wg*img[i][j][1] + wr*img[i][j][2])img1[i][j] = val
cv.imshow('img1',img1)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
三、二值化
- 在对图像进行灰度化处理后,我们可以进一步对图像进行二值化操作(也就是二值化的操作对象必须是灰度图),使得图像的所有像素值只有两种值
- 通过二值化处理,能够帮助我们更好地分析图像中的形状、边缘和轮廓等特征
- 以下介绍几种常用的二值化处理方法
1.全局阈值法
- 对于整个灰度图像,只设定一个阈值
1.阈值法(THRESH_BINARY)
- 通过设定一个阈值,将灰度图中每一个点的像素值与之比较,如果小于阈值则设置为0,否则设置为maxval(需要自定义,通常设定为255)
2.反阈值法(THRESH_BINARY_INV)
- 与阈值法操作相反,即将灰度图中每一个点的像素值与之比较,如果小于阈值则设置为maxval,否则设置为0
3.截断阈值法(THRESH_TRUNC)
- 该方法将灰度图中每一个点的像素值与阈值比较,大于阈值的设置为阈值,否则不改变
4.低阈值零处理(THRESH_TOZERO)
- 该方法将灰度图中每一个点的像素值与阈值比较,低于阈值设置为0,否则不变
5.超阈值零处理(THRESH_TOZERO_INV)
- 该方法将灰度图中每一个点的像素值与阈值比较,低于阈值不变,高于阈值设置为0
6.OTSU算法
- 该算法较为特殊,不是单纯的阈值方法,通常它会结合
THRESH_BINARY
或THRESH_BINARY_INV
- OTSU算法是通过一个值将这张图分前景色和背景色(也就是灰度图中小于这个值的是一类,大于这个值的是一类。例如,如果你设置阈值为128,则所有大于128的像素点可以被视作前景,而小于等于128的像素点则被视为背景。
- 该算法将自动计算阈值
- OTSU算法就是在灰度图的像素值范围内遍历阈值T,使得g((类间方差))最大,基本上双峰图片的阈值T在两峰之间的谷底
7.代码展示
img = cv.imread('img\cat1.png')
gray = cv.cvtColor(img,cv.COLOR_BGR2GRAY)_,binary = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_BINARY) #阈值法
_,binary_inv = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_BINARY_INV) #反阈值法
_,binary_tru = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_TRUNC) #截断阈值法
_,binary_zero = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_TOZERO) #低阈值零处理
_,binary_zero_inv = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_TOZERO_INV) #超阈值零处理
_,otsu = cv.threshold(gray,thresh=150,maxval=255,type=cv.THRESH_OTSU) #OTSU阈值法,默认结合阈值法
adapt = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,3,10)
adapt_guass = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,3,10)
cv.imshow('gray',binary)
cv.imshow('gray1',binary_inv)
cv.imshow('gray2',binary_tru)
cv.imshow('gray3',binary_zero)
cv.imshow('gray4',binary_zero_inv)
cv.imshow('otsu',otsu)
cv.imshow('adapt',adapt)
cv.imshow('adapt',adapt_guass)
cv.imshow('img',img)
cv.waitKey(0)
cv.destroyAllWindows()
2.局部阈值法
-
当图片呈现出明暗分布不均匀的时候,如果继续使用全局阈值法可能导致结果不够准确,这时候我们可以使用自适应二值化的方法,对每一个像素点计算一个阈值,在结合普通的阈值法或反阈值法即可得到更加准确的结果
-
cv2.adaptiveThreshold(image_np_gray, maxval, cv2.ADAPTIVE_THRESH_MEAN_C, cv2.THRESH_BINARY, 7, 10)
-
maxval
:最大阈值,一般为255 -
adaptiveMethod
:小区域阈值的计算方式: -
thresholdType
:二值化方法,只能使用THRESH_BINARY、THRESH_BINARY_INV,也就是阈值法和反阈值法 -
blockSize
:选取的小区域的面积,如7就是7*7的小块。 -
c
:最终阈值等于小区域计算出的阈值再减去此值 -
ADAPTIVE_THRESH_MEAN_C
:小区域内取均值 -
- 该方法使用指定大小的区域,计算区域内像素点的均值
- 该方法使用指定大小的区域,计算区域内像素点的均值
adapt = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_MEAN_C,cv.THRESH_BINARY,3,10)
ADAPTIVE_THRESH_GAUSSIAN_C
:小区域内加权求和,权重是个高斯核-
- 该方法对指定大小区域内像素求加权均值,权重来自高斯分布
-
- 在opencv里,当kernel(小区域)的尺寸为1、3、5、7并且用户没有设置sigma的时候(sigma <= 0),核值就会取固定的系数,这是一种默认的值是高斯函数的近似
- 在opencv里,当kernel(小区域)的尺寸为1、3、5、7并且用户没有设置sigma的时候(sigma <= 0),核值就会取固定的系数,这是一种默认的值是高斯函数的近似
-
- 比如kernel的尺寸为3*3时,使用
[ 0.25 0.5 0.25 ] × [ 0.25 0.5 0.25 ] \left[\begin{array}{c}{{0.25}}\\ {{0.5}}\\ {{0.25}}\end{array}\right]\times\left[0.25~~~~0.5~~~~0.25\right] 0.250.50.25 ×[0.25 0.5 0.25]
进行矩阵的乘法,就会得到如下的权重值,其他的类似。
k e r n e l = [ 0.0625 0.125 0.0625 0.125 0.25 0.125 0.0625 0.125 0.0625 ] kernel=\left[\begin{array}{c}{{0.0625~~~0.125~~~0.0625}}\\{{0.125~~~~0.25~~~~0.125}}\\ {{0.0625~~~0.125~~~0.0625}} \end{array}\right] kernel= 0.0625 0.125 0.06250.125 0.25 0.1250.0625 0.125 0.0625
通过这个高斯核,即可对图片中的每个像素去计算其阈值,并将该阈值减去固定值得到最终值
- 比如kernel的尺寸为3*3时,使用
adapt_guass = cv.adaptiveThreshold(gray,255,cv.ADAPTIVE_THRESH_GAUSSIAN_C,cv.THRESH_BINARY,3,10)
tips:使用高斯核可以降低噪声对二值化的干扰,因为通常噪声原理所选定的区域,对应的权重较小,对最终结果的影响也就越小
THE END