OpenCV:06阈值与形态学

形态学概述morphology

什么是形态学?

  • 指一系列处理图像形状特征的图像处理技术
  • 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核,该卷积核只有0和1两个数字),通过01来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别
  • 这些处理方法基本是对二进制图像的处理,即黑白图像
  • 卷积核决定着图像处理后的效果
  • 形态学基本操作有:
    • 膨胀和腐蚀
    • 开运算
    • 闭运算
    • 顶帽
    • 黑帽

通俗地说,你想要获取图像中的任何部分(噪声、图形、轮廓…)形态学都能满足,这就是它的魅力

图像的全局二值化

二值化:将图像的每个像素变成两种值,比如0,255(0是黑色,255是白色)

二值化本质:对整个图片进行统一操作,即人为设置一个阈值,大于这个值的像素点赋一个值,小于这个值的像素点赋另一个值

关键API:cv2.threshold(src, thresh, maxval, type[, dst])
其中:
二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

  • src:进行全局二值化的图片最好不要是多通道的彩色图片,最好是灰度图

  • thresh:阈值,作用于下方的type操作类型的判断条件

  • maxval:最大值,不一定是255(但我们常设置为255)

  • type:操作类型,常见操作类型如下
    在这里插入图片描述
    THRESH_BINARY:当该点像素大于人为设置的阈值thresh,则该点的像素值被赋值为最大值maxval;当该点的像素值小于阈值thresh(otherwise条件下),则赋值为0

    THRESH_BINARY_INVINV表示invert(反转)的意思,当该点像素小于人为设置的阈值thresh,则该点的像素值被赋值为最大值maxval;当该点的像素值大于阈值thresh(otherwise条件下),则赋值为0

    THRESH_TRUNCTRUNC表示truncate,有将数字截尾取整的意思(夹断),当该点像素大于人为设置的阈值thresh,则该点的像素值统一被赋值为阈值thresh;当该点的像素值小于阈值thresh(otherwise条件下),则像素值还是其本身src(x,y)

    THRESH_TOZERO:当该点像素大于人为设置的阈值thresh,则该点的像素值还是其本身src(x,y);当该点的像素值小于阈值thresh(otherwise条件下),则赋值为0

    THRESH_TOZERO_INV:当该点像素大于人为设置的阈值thresh,则赋值为0;当该点的像素值小于阈值thresh(otherwise条件下),则该点的像素值还是其本身src(x,y)

# 全局二值化

import cv2
import numpy as np

# 导入图片
img = cv2.imread('./cat.jpeg')

# 二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 进行二值化操作(注意!threshold有两个返回值!一个是阈值,一个是二值化处理后的图片)
thresh,dst = cv2.threshold(gray,127,255,cv2.THRESH_BINARY) # 最终二值化的效果会受到阈值(第二个参数thresh)的影响


# 展示
# cv2.imshow('dst',dst)
cv2.imshow('img and dst ',np.hstack((gray,dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

结果:
在这里插入图片描述
左边的灰度图的值在0-255,即可以有128、254、222…这些值;而右边的黑白图只有0和255两个值,任取一个像素点不是0就是255

我们可以不断调整阈值大小来美化图片


自适应阈值二值化

我们可以发现上一个方法还是不太好,调了半天阈值,想要的东西都显示不出来。我们需要一个更灵活的阈值,能够根据当前的区域去自己计算出一个阈值,这就是我们的——自适应阈值

在前面的部分我们采用的是全局阈值,整幅图像采用同一个数作为阈值。当然这种方法并不适用于所有情况,尤其是当同一幅图像上的不同地方具有不同亮度时,这种情况我们需要采取自适应阈值。此时的阈值是根据图像上的每一个小区域计算对应的阈值。因此在同一幅图像的不同区域采取的是不同的阈值,从而我们能够在亮度不同的情况下得到更好的结果

关键API:cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])

这种方法需要指定6个参数,返回值只有一个
其中

  • src:操作的图像
  • maxValue:最大值,一般写为255
  • adaptiveMethod:自适应的方法,常用的两种
    • cv2.ADAPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值,类似我们的卷积操作,效果一般般,不如下面的高斯方法
    • cv2.ADAPTIVE_THRESH_GAUSSIAN_C:阈值取相邻区域的加权和,越靠近中心区域的点权重越大,权重是一个高斯窗口
  • thresholdType:阈值类型,和上面的type一模一样
  • blockSize:卷积核的大小,写一个数字就可以了(不用写元组)
  • C:一个常数,阈值就等于平均值或者加权平均值加上这个常数

例子1:

# 全局二值化

import cv2
import numpy as np

# 导入图片
img = cv2.imread('./dog.jpeg')

# 二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 进行二值化操作(注意!自适应二值化只有一个返回值:阈值)
dst = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,9,0)

# 展示
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

结果:

在这里插入图片描述

可以很清楚地看到🐕脖子上的钥匙(有个轮廓)
在这里插入图片描述

例子2:更具代表性的例子
我们的目标是看清楚这张图中的题目:由于光线的问题,拍出来上半部分亮度高一点,下半部分暗一点。如果使用全局二值化,效果非常差;我们选用自适应二值化
在这里插入图片描述

先看看全局二值化的效果:

thresh,dst = cv2.threshold(gray,200,255,cv2.THRESH_BINARY)在这里插入图片描述我们可以通过调小阈值,使得图片更加清晰

thresh,dst = cv2.threshold(gray,127,255,cv2.THRESH_BINARY)

在这里插入图片描述
我们发现全局二值化对光线不好的地方效果不太好,尽管可以通过调整阈值改进,但效果始终不如自适应阈值二值化!

# 全局二值化 更具有代表性的例子

import cv2
import numpy as np

# 导入图片
img = cv2.imread('./math.jpeg')

# 二值化操作是对灰度图操作的 ——> 因此我们首先要把图像变成灰度图!
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)

# 进行二值化操作(注意!自适应二值化只有一个返回值:阈值)
dst = cv2.adaptiveThreshold(gray,255,cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY,9,0)

# 展示
cv2.imshow('dst',dst)

cv2.waitKey(0)
cv2.destroyAllWindows()

在这里插入图片描述
如果我们想要把背景改成白色:只需要INV一下,把参数 thresholdType中的THRESH_BINARY改成THRESH_BINARY_INV即可

在这里插入图片描述


Otsu方法

上方的阈值127是我们自己设置的,而不是通过算法计算得到的。对于有些图像,当阈值被设置为127时,得到的效果并不好,这时就需要一个个地尝试,直到找到最合适的阈值

逐个寻找最合适的阈值不仅工作量大,而且效率低。为此,OpenCV提供了Otsu方法:能够遍历所有可能的阈值,从中找到最合适的阈值

Otsu方法的语法与cv2.threshold()方法的语法基本一致,只不过在为type传入参数时,要多传递一个参数,即cv2.THRESH_OTSUcv2.THRESH_OTSU的作用就是实现Otsu方法的阈值处理。Otsu方法的语法如下:

关键API:retval,dst = cv2.threshold(src,thresh,maxval,type)

  • src:进行全局二值化的图片最好不要是多通道的彩色图片,最好是灰度图
  • thresh:阈值,要设置为0
  • maxval:阈值处理采用的最大值,要设置为255
  • type:阈值处理类型。除了在上方选择的阈值处理类型threshol
  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值