OpenCV学习笔记9-形态学的原理及代码实现

1 形态学概述

  • 什么是形态学(morphology)
  • 指一系列处理图像形状特征的图像处理技术
  • 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。该卷积核比较特殊,元素基本都是0/1.
  • 这些处理方法基本上都是处理二值图像,即黑白图像
  • 卷积核决定图像处理的效果
  • 形态学中常用的基本运算有:
  • 膨胀和腐蚀
  • 开放式操作
  • 封闭式操作
  • 大礼帽
  • 黑帽

2 图像全局二值化

  • 二值化: 将图像的每个像素变成两种值, 比如0, 255.
  • cv2.threshold(src, thresh, maxval, type[, dst])
  • src: 最好是灰度图
  • thresh: 阈值
  • maxval: 最大值, 最大值不一定是255(用的最多的还是255)
  • type: 操作类型. 常见操作类型如下(常用的是1、4):
  • 会返回两个结果,一个是阈值thresh, 另一个是处理后的图片dstOpenCV学习笔记9-形态学的原理及代码实现import cv2 import numpy as np# 导入图片img = cv2.imread(‘./dog.jpeg’)# 二值化操作是对灰度图像操作, 把dog变成灰度图像gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 注意, threshold会返回两个值, 一个是阈值, 二值化处理后的图片thresh, dst = cv2.threshold(gray, 110, 255, cv2.THRESH_BINARY)print(thresh)# 展示cv2.imshow(‘dog’, np.hstack((gray, dst)))cv2.waitKey(0)cv2.destroyAllWindows()OpenCV学习笔记9-形态学的原理及代码实现

3 自适应阈值二值化

在上一部分中,我们使用了全局阈值,整幅图像使用与阈值相同的数字。但这种方法并不适用于所有情况,尤其是当同一图像的不同部分具有不同的亮度时。在这种情况下,我们需要使用自适应阈值。此时的阈值是根据图像上的每个小区域计算出相应的阈值。因此,在同一张图像的不同区域使用不同的阈值,这样我们在不同亮度的情况下可以得到更好的结果,比全局二值化更加灵活。

  • cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
  • 这个方法需要我们指定六个参数,并且只有一个返回值。
  • src最好是灰度图
  • maxValue最大值, 最大值不一定是255(用的最多的还是255)
  • Adaptive Method- 指定计算阈值的方法。
    – cv2.ADPTIVE_THRESH_MEAN_C :阈值取自相邻区域的平均值
    – cv2.ADPTIVE_THRESH_GAUSSIAN_C :阈值取值相邻区域的加权和,权重为一个高斯窗口。(效果更好)
  • type: 操作类型. 常见操作类型如下:

OpenCV学习笔记9-形态学的原理及代码实现

  • Block Size- 邻域大小(用来计算阈值的区域大小,即卷积核大小),是一个奇数。
  • C- 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。
  • dst 输出图像
import cv2 
import numpy as np

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

# 二值化操作是对灰度图像操作, 把dog变成灰度图像
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# 自适应阈值二值化只有一个返回值,
dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 19, 0)

# 展示
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0vbgBaCb-1649317418206)(D:\Desktop\daxue\MSB\AIoT\机器视觉\day09_形态学(一)]\课件\img\1648738888(1).jpg)

4 腐蚀操作

  • 腐蚀操作也是用卷积核扫描图像,只不过腐蚀操作的卷积核元素一般都是1, 如果卷积核内所有像素点都是白色, 那么锚点即为白色.OpenCV学习笔记9-形态学的原理及代码实现
  • 大部分时候腐蚀操作使用的都是全为1的卷积核.OpenCV学习笔记9-形态学的原理及代码实现
  • cv2.erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src是原图
  • kernel是卷积核的大小,元组形式
  • dst 输出图像
  • anchor 锚点,是可选参数,默认是(-1,-1)
  • iterations是腐蚀操作的迭代次数, 次数越多, 腐蚀操作执行的次数越多, 腐蚀效果越明显
  • borderType 边界类型
  • borderValue 边缘值
import cv2 
import numpy as np

# 导入图片
img = cv2.imread('./j.png')

# 定义核
kernel = np.ones((3,3), np.uint8)
dst = cv2.erode(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DqIfvdNL-1649317418207)(D:\Desktop\daxue\MSB\AIoT\机器视觉\day09_形态学(一)]\课件\img\1648739257(1).jpg)

5 获取形态学卷积核

  • opencv提供了获取卷积核的api.不需要我们手工创建卷积核.
  • cv2.getStructuringElement(shape, ksize[, anchor])
  • shape是指卷积核的形状, 注意不是指长宽, 是指卷积核中 1 形成的形状.
  • MORPH_RECT 卷积核中的1是矩形, 常用.
  • MORPH_ELLIPSE 卷积核中的 1 椭圆
  • MORPH_CROSS 卷积核中的 1 十字
  • ksize 卷积核的大小,元组形式
import cv2
import numpy as np

img = cv2.imread('./j.png')

# 获取形态学卷积核
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 腐蚀操作
dst = cv2.erode(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV学习笔记9-形态学的原理及代码实现

6 膨胀操作

膨胀是腐蚀的相反操作, 基本原理是只要保证卷积核的锚点是非0值, 周边无论是0还是非0值, 都变成非0值.

OpenCV学习笔记9-形态学的原理及代码实现

  • cv2.dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src是原图像
  • kernel是卷积核的大小,元组形式
  • dst 输出图像
  • anchor 是锚点
  • iterations是膨胀操作的迭代次数, 次数越多, 膨胀操作执行的次数越多, 膨胀效果越明显
  • borderType 边界类型
  • borderValue 边缘值
import cv2
import numpy as np

img = cv2.imread('./j.png')

# 获取形态学卷积核
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 膨胀操作
dst = cv2.dilate(img, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV学习笔记9-形态学的原理及代码实现

膨胀和腐蚀的简单应用:

# 膨胀和腐蚀简单应用
import cv2 
import numpy as np


# 导入图片
img = cv2.imread('./msb.png')

# 定义核
kernel = np.ones((5, 5), np.uint8)

# 先腐蚀
dst = cv2.erode(img, kernel, iterations=1)

# 再膨胀
dst = cv2.dilate(dst, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tNs093R9-1649317418208)(D:\Desktop\daxue\MSB\AIoT\机器视觉\day09_形态学(一)]\课件\img\8c8e15ce0a925557925280bbedbbfef.png)

7 开运算

  • 开运算和闭运算都是腐蚀和膨胀的基本应用。
  • 开运算=腐蚀+膨胀(腐蚀和膨胀)
  • 适合去除图像外的噪点
  • cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src是原图
  • op操作类型(operations),开运算是cv2.MORPH_OPEN
  • kernel是卷积核的大小,元组形式。如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel
  • dst 是输出图像
  • anchor 是锚点
  • iterations是操作的迭代次数, 次数越多, 操作执行的次数越多, 效果越明显
  • borderType 边界类型
  • borderValue 边缘值
import cv2
import numpy as np

# 开运算 = 腐蚀  + 膨胀
# 开运算提供了另一种去除噪声的思路.
img = cv2.imread('./dotj.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 直接调用opencv提供的开运算api
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

image-20211114171444825

8 闭运算

  • 闭运算 = 膨胀 + 腐蚀(膨胀和腐蚀)
  • 适合去除图像内部的噪点
  • cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src是原图
  • op操作类型(operations),开运算是 cv2.MORPH_CLOSE
  • kernel是卷积核的大小,元组形式。如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel
  • dst 是输出图像
  • anchor 是锚点
  • iterations是操作的迭代次数, 次数越多, 操作执行的次数越多, 效果越明显
  • borderType 边界类型
  • borderValue 边缘值
import cv2
import numpy as np

# 闭运算= 膨胀 + 腐蚀
# 闭运算可以去除图形内部的噪声
img = cv2.imread('./dotinj.png')

kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV学习笔记9-形态学的原理及代码实现

9 形态学梯度

  • 渐变 = 原始 – 腐蚀
  • 腐蚀后,原图边缘变小,原图-腐蚀可以得到被腐蚀的部分,即边缘。
  • cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src 是原图
  • op操作类型(operations),开运算是 cv2.MORPH_GRADIENT
  • kernel是卷积核的大小,元组形式。如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel
  • dst 是输出图像
  • anchor 是锚点
  • iterations是操作的迭代次数, 次数越多, 操作执行的次数越多, 效果越明显
  • borderType 边界类型
  • borderValue 边缘值
# 形态学梯度 = 原图 - 腐蚀
import cv2
import numpy as np

img = cv2.imread('./j.png')

# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))

# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV学习笔记9-形态学的原理及代码实现

10 顶帽操作

  • 大礼帽=原始图像-打开操作
  • 开运算的效果是去除图像外的噪声,而原始图像-开运算会得到去除的噪声。
  • morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src是原图
  • op操作类型(operations),开运算是 cv2.MORPH_TOPHAT
  • kernel是卷积核的大小,元组形式。如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel
  • dst 是输出图像
  • anchor 是锚点
  • iterations是操作的迭代次数, 次数越多, 操作执行的次数越多, 效果越明显
  • borderType 边界类型
  • borderValue 边缘值
# 顶帽操作 = 原图  - 开运算 得到图形外的噪声
import cv2 
import numpy as np

img = cv2.imread('./dotj.png')

# 注意调整kernel以保留小图形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YfwlF3II-1649317418209)(D:\Desktop\daxue\MSB\AIoT\机器视觉\day09_形态学(一)]\课件\img\1648741702(1).jpg)

11 黑帽操作

  • 黑帽=原始图像-关闭操作
  • 闭合操作可以去除图内部的噪声,所以原始图像闭合操作的结果是图内部的噪声。
  • cv2.morphologyEx(src, op, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
  • src是原图
  • op操作类型(operations),开运算是 cv2.MORPH_BLACKHAT
  • kernel是卷积核的大小,元组形式。如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel
  • dst 是输出图像
  • anchor 是锚点
  • iterations是操作的迭代次数, 次数越多, 操作执行的次数越多, 效果越明显
  • borderType 边界类型
  • borderValue 边缘值
# 黑帽操作 = 原图  - 闭运算 得到图形内部的噪声
import cv2 
import numpy as np

img = cv2.imread('./dotinj.png')

# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))

# 调用opencv提供的api
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=2)

cv2.imshow('img', np.hstack((img, dst)))

cv2.waitKey(0)
cv2.destroyAllWindows()

OpenCV学习笔记9-形态学的原理及代码实现

附OpenCV目录:OpenCV总目录学习笔记

我是知客的专业新手。写博客文章并不容易。如果你喜欢它,你可以给它一个大拇指! 请添加图片描述

文章出处登录后可见!

已经登录?立即刷新

共计人评分,平均

到目前为止还没有投票!成为第一位评论此文章。

(0)
社会演员多的头像社会演员多普通用户
上一篇 2022年4月9日 下午12:29
下一篇 2022年4月9日 下午12:48

相关推荐