OpenCV——第二课 图像处理(1)

本文详细介绍了图像处理中的关键技术,包括图像阈值分割,用于提取目标区域;图像平滑技术,如均值滤波、方框滤波、高斯滤波和中值滤波,用于去除噪声;以及形态学操作,如腐蚀、膨胀、开运算和闭运算,用于形状提取和边缘检测。此外,还讨论了Sobel、Scharr和Laplacian算子在图像梯度计算中的应用。
摘要由CSDN通过智能技术生成

图像处理

图像阈值

图像阈值分割是一种广泛应用的技术,利用图像中要提取的目标区域与其背景在灰度特性上的差异,把图像看作具有不同灰度级的两类区域的组合(目标区域和背景区域),选取一个合理的阈值,从而选取目标区域,但是两个区域的灰度值差异得明显才能处理,否则会导致错误划分。

图像的阈值处理又称为二值化,阈值也称临界值,即为了确定像素点范围,在这个范围内使用同种方法处理,范围外保持不变。
主要使用的函数:

ret,dst=cv2.threshold(src,thresh,maxval,type)
  • 返回值有两个,第一个为ret即二值化处理时的阈值的数值,dst即二值化处理后的图像
  • 参数有四个,src表示输入图,一般只能为单通道的灰度图,但三通道的RGB图像也可以进行处理(不过只能根据第一个通道的大小进行处理);thresh表示设定的阈值;maxval表示像素值超过阈值或小于阈值时,所赋予的值;type表示操作类型,总共有5种类型。
  • cv2.THRESH_BINARY:大于阈值部分取maxval,否则取0
  • cv2.THRESH_BINARY_INV:小于阈值部分取maxval,否则取0
  • cv2.THRESH_TRUNC:大于阈值部分设为阈值,否则不变
  • cv2.THRESH_TOZERO:大于阈值部分不改变,否则设为0
  • cv2.THRESH_TOZERO_INV:小于阈值部分不改变,否则设为0

图像平滑

由于亮度变化过大,图像上会出现一些亮点,即噪声(多余的干扰信息),为了去除图像中的噪声使得图像看起来更平滑,因此有了图像平滑处理,其原理是将噪声所在像素点处理为其周围临近像素点的近似值。主要有如下方法:

均值滤波

均值滤波的时候需要考虑周围多少个像素平均值,即确定卷积核的大小,通常情况下都是以当前像素点为中心,读相同的奇数行和奇数列求平均值,结果作为当前像素点的取值。

在这里插入图片描述
如上图,当所求像素点为32时,卷积核为3*3,计算值为:
( 25 + 106 + 178 + 43 + 32 + 167 + 178 + 198 + 200 ) / 9 = 125 (25+106+178+43+32+167+178+198+200)/9=125 (25+106+178+43+32+167+178+198+200)/9=125
计算值得到的125为新值,卷积核为:
[ 1 1 1 1 1 1 1 1 1 ] / ( 3 × 3 ) \begin{bmatrix} 1&1&1\\ 1&1&1\\ 1&1&1 \end{bmatrix}/(3\times3) 111111111 /(3×3)
若取值为23,则计算公式为 ( 23 + 158 + 199 + 25 ) / 4 (23+158+199+25)/4 (23+158+199+25)/4,即边缘像素点只需计算在图像内部的临近点
均值滤波通过blur函数实现,blur函数语法格式如下:

blur = cv2.blur(img, ksize,anchor,borderType)
  • blur是返回值,表示你均值滤波后得到的结果
  • img是输入的原始图像
  • ksize表示卷积核的大小
  • anchor为锚点,一般默认即可
  • borderType是边界样式,即对边界的处理方式
  • 一般形式:blur = cv2.blur(img,ksize)

方框滤波

方框滤波是均值滤波的一般形式,基本和均值一样,多了一个normalize参数表示是否归一化,它的取值为True或者1时,表示要进行归一化处理,即需要用临近像素点的和除以临近元素的数量总和(和均值滤波计算一样),反之则不用除,直接加法就可,若临近像素点的和大于255则取值255。

高斯滤波

高斯滤波采用的是对图像进行加权平均的过程,每一个像素点都由其本身和邻域内的其他像素值经过加权平均后得到,均值滤波的邻域内每个像素点的权重值都相同,而高斯滤波中,中心点的权重值最大,远离中心点的权重值减小。其3x3的卷积核可如下所示:
[ 0.05 0.1 0.05 0.1 0.4 0.1 0.05 0.1 0.05 ] \begin{bmatrix} 0.05&0.1&0.05\\ 0.1&0.4&0.1\\ 0.05&0.1&0.05 \end{bmatrix} 0.050.10.050.10.40.10.050.10.05
借用均值滤波中的图,则计算公式为:
( 25 ∗ 0.05 + 106 ∗ 0.1 + 178 ∗ 0.05 + 43 ∗ 0.1 + 32 ∗ 0.4 + 167 ∗ 0.1 + 178 ∗ 0.05 + 198 ∗ 0.1 + 200 ∗ 0.05 ) = 93.25 (25*0.05+106*0.1+178*0.05+43*0.1+32*0.4+167*0.1+178*0.05+198*0.1+200*0.05)=93.25 (250.05+1060.1+1780.05+430.1+320.4+1670.1+1780.05+1980.1+2000.05)=93.25
则新值为93.25,这里的卷积核的长和宽可以不同,但是必须是奇数

高斯滤波使用GaussianBlur函数,该函数语法如下:

dst=cv2.GaussianBlur(src,ksize,sigmaX,sigmaY,borderType)
  • dst为高斯滤波后得到的图像
  • src是输入的图像
  • ksize滤波卷积核,例如:(3,3)
  • sigmaX,sigmaY分别是卷积在水平方向和垂直方向的标准差
  • borderType是边界类型
  • 一般形式为:aussian = cv2.GaussianBlur(img,(3,3),0,0)

中值滤波

中值滤波将每一像素点灰度值设置为该点临近区域内所有像素点灰度值的中值(即将周围像素点排列取中位数)。借用上面均值滤波的图,取卷积核为3x3,得值为32的像素点的新值为167

中值滤波的实现函数为medianBlur,其基本语法格式为:

dst = cv2.medianBlur( src, ksize)
  • dst为返回的图像
  • src为输入的图像
  • ksize为卷积核大小,必须为奇数
  • 一般形式为median = cv2.medianBlur(img, 5),表示5x5的卷积核

中值滤波可以几乎不影响原有图像的情况下去除所有噪声,但是由于需要排序,因此需要的运算较大。

这里可以使用hstack函数将四种滤波后的图像横着拼接到一起,进行对比,如下分别为均值、高斯、中值滤波拼接到一起的代码,res为拼接后的图像,np为numpy库。

res = np.hstack((blur,aussian,median))

形态学操作

形态学操作的目的是为了提取图像中主要的分量信息,通常用于表达和描绘图像的形状。主要包括如下操作:

腐蚀操作

腐蚀操作能够将图像的边界点消除,使图像沿着边界向内收缩,也可以将小于指定结构体元素的部分去除。主要用来“细化”二值图像中的前景,借此实现去除噪声、元素分割等功能。如下为进行了一次腐蚀操作

在这里插入图片描述

在腐蚀过程中,通常使用一个结构体(即核)逐个像素的扫描要被腐蚀的图像,并根据结构元和被腐蚀的图像关系来确定腐蚀结果

在这里插入图片描述

如上图,根据两种不同关系来决定腐蚀结果图像中的结构元中心点所对应位置的像素点的像素值。红色为结构元,黄色为结构元中心,白色为前景,黑色为背景。

  • 左图,结构元完全处于前景图像中,就将结构元中心点所对应的腐蚀结果图像中的像素点的像素值处理为前景色(白色)
  • 右图,结构元未完全处于前景图像中(部分在或者完全不在前景图像中,一般为边界像素点),就将结构元中心点所对应的像素值处理为背景色(黑色)

腐蚀操作通过cv2.erode函数实现,语法格式如下:

dst = cv2.erode(src, kernel, anchor, iterations, borderType, borderValue)
  • dst为返回的图像
  • src为输入图像
  • kernal代表腐蚀操作采用的结构元的大小,结构元越大,一次腐蚀面积越大,也可以自定义,例如:kernel = np.ones((30,30),np.uint8)
  • anchor表示锚点的位置,一般默认即可
  • iterations腐蚀操作迭代的次数,默认为1,表示一次腐蚀操作
  • borderType代表边界样式,一般采用BORDER_CONSTANT为默认值。
  • borderValue表示边界值,默认即可
  • 一般形式为:erosion_1 = cv2.erode(pie,kernel,iterations = 1)

膨胀操作

膨胀操作可以说是腐蚀操作的逆运算,也是用一个结构元来逐个像素的扫描。

  • 如果结构元中任意一点在前景图像中,就将结构元对应的像素点处理为前景色
  • 如果结果元完全处于背景图像中,就将膨胀图像中对应像素点处理为背景色

膨胀操作主要由dilate函数实现,基本语法如下:

dst = cv2.dilate(src, kernel, anchor, iterations, borderType, borderValue)
  • 各个函数的含义和腐蚀函数erode相同
  • 一般形式为:dige_dilate = cv2.dilate(dige_erosion,kernel,iterations = 1)

:腐蚀一次后再膨胀,与原图不一样,因为腐蚀会改变图像像素点。

腐蚀和膨胀都是形态学的基础,两者的组合可以实现多种运算,OpenCV通过morphologyEx函数实现组合运算,基本语法如下:

dst=cv2.morphologyEx(src,op,kernel,anchor,iterations,borderType,borderValue)
  • dst表示经过形态学处理后输出的目标图像
  • src表示输入的图像
  • op表示操作类型,具体如下
类型说明含义
cv2.MORPH_ERODE腐蚀腐蚀
cv2.MORPH_DILATE膨胀膨胀
cv2.MORPH_OPEN开运算先腐蚀后膨胀
cv2.MORPH_CLOSE闭运算先膨胀后腐蚀
cv2.MORPH_GRADIENT形态学梯度运算膨胀图减腐蚀图
cv2.MORPH_TOPHAT顶帽运算原始图像减开运算
cv2.MORPH_BLACKHAT黑帽运算闭运算所得图像减原始图像
  • 其他参数与erode函数一致

开运算

开运算进行的操作是先将图像腐蚀,再对腐蚀的结果进行膨胀,可以用于去噪、计数(即分割连接的图像),如下图所示:
在这里插入图片描述

闭运算

闭运算进行的操作是先将图像膨胀,再对膨胀的结果进行腐蚀,可以用于去除图像上的黑点,也可将独立的图像连接到一起,如下图所示:
在这里插入图片描述

梯度运算

图像梯度运算是由图像的膨胀图像减去图像的腐蚀图像,该操作可以获取图像的前景图像的边缘。如下图,左为膨胀图像,右为腐蚀图像
在这里插入图片描述
梯度运算后得到的图像为:
在这里插入图片描述

礼帽运算

礼貌运算是由原始图像减去开运算图像的操作。礼貌运算可以获得图像的噪声信息,或者得到比原始图像的边缘更亮的边缘信息,如下图:
在这里插入图片描述

黑帽运算

黑帽运算是由闭运算图像减去原始图像的操作。黑帽运算能够获取图像内部的小孔,或者前景色中的小黑点,或者得到比原始图像的边缘更暗的边缘部分。
在这里插入图片描述

图像梯度算子

图像梯度是指图画强度或色彩的方向改动,对于一副图像,其边缘部分两侧灰度值相差大,梯度值大,而图像梯度一般通过计算像素差值来得到梯度的近似值。

Sobel算子

sobel算子可以计算图像梯度,用于提取边界
在这里插入图片描述
以上分别为sobel的三阶卷积核,Gx为计算水平梯度时的卷积核,即右边减左边,当目标点(即A的中心点)左右差别特别大的时候,目标的值会很大,说明该点为边界,同理对于Gy,计算的则是垂直方向梯度,垂直方向上有较大的差值,就说明该点为边界。

sobel算子函数语法如下:

dst = cv2.Sobel(src, ddepth, dx, dy, ksize)
  • **src为输入图像
  • ddepth表示图像的深度
  • dx、dy分别表示水平和竖直方向,取1表示取该方向,0表示不计算该方向
  • ksize表示算子的卷积核大小

以下图为例,右边为原图:
在这里插入图片描述
计算水平方向的梯度,由于根据sobel算子,可以看成是右减左,即在前景(白色圆圈)的左边缘为白(255)减黑(0)等于正,则为白色;右边缘为黑减白等于负,但是sobel算子对所有负数会被截断成0,即为黑色,因此计算后的图像左边有白色边界,右边只有黑色,为此我们需要在计算减法时取绝对值。如下代码:

sobelx = cv2.Sobel(img,cv2.CV_64F,1,0,ksize=3)
sobelx = cv2.convertScaleAbs(sobelx)       #convertScaleAbs即用来取绝对值
cv_show(sobelx,'sobelx')

可得如下图:
在这里插入图片描述
求出水平边界后,还需要垂直边界,但是这里通过比较发现,水平和垂直边界最好分开计算,再进行图像融合,而同时计算水平和垂直边界的结果并不是很好,如下图所示:

在这里插入图片描述
左边为分开计算,右边为同时计算,明显左边的边界优于右边。

scharr算子

scharr与sobel算子思想一样,只是卷积核的系数不同,scharr算子提取边界也更加灵敏,能提取到更小的边界,但是也容易造成边界的误判
在这里插入图片描述
该算子使用Scharr函数,语法和Sobel函数相同

Laplacian算子

laplacian算子也是用来提取边界的,但是和前面两个不同,该算子本身是一个二阶算子,它的运算规则就是在水平方向运算两次,垂直方向上运算两次,两个结果叠加替换中心点的像素值。算子如下:
在这里插入图片描述
该算子使用laplacian函数,不需要拆分xy,即

laplacian = cv2.Laplacian(img,cv2.CV_64F)     
laplacian = cv2.convertScaleAbs(laplacian)

该算子对噪声比较敏感,不会单独使用,下图为三个算子的对比:
在这里插入图片描述

总结

图像处理有很强力的Python工具包,但是了解底层原理还是非常有必要的

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zero3_msh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值