知识重点
- 二值化操作 gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY),对灰度图像操作, 全局阈值,整幅图像采用同一个数作为阈值 。
-
自适应阈值二值化 dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 9, 7) 此时的阈值是根据图像上的每一个小区域计算与其对应的阈值 。
- 腐蚀操作 dst = cv2.erode(img, kernel, iterations = 2) 腐蚀操作也是用卷积核扫描图像, 去除图片中的噪点, 只不过腐蚀操作的卷积和一般都是1, 如果卷积核内所有像素点都是白色, 那么锚点即为白色. iterations是腐蚀操作的迭代次数, 次数越多, 腐蚀效果越明显 。
-
getStructuringElement(shape, ksize[, anchor]) opencv提供了获取卷积核的api.不需要我们手工创建卷积核.shape是指卷积核的形状, 注意不是指长宽, 是指卷积核中1形成的形状.
-
- 膨胀操作 dst = cv2.dilate(img, kernel, iterations = 1) 实现对图像的膨胀操作
- 开运算 dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel) 开运算 = 腐蚀 + 膨胀 去除图像外部的噪点 .
- 闭运算 dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel) 闭运算 = 膨胀 + 腐蚀 填充图像内部的噪点 .
- 形态学梯度 dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel) 梯度 = 原图 - 腐蚀, 腐蚀之后原图边缘变小了, 原图 - 腐蚀 就可以得到腐蚀掉的部分, 即边缘.
- 顶帽运算 dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel,iterations = 2) 顶帽 = 原图 - 开运算 开运算的效果是去除图像外的噪点, 原图 - 开运算就得到了去掉的噪点.
- 黑帽操作 dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel,iterations = 2)
- 黑帽 = 原图 - 闭运算 闭运算可以将图形内部的噪点去掉, 那么原图 - 闭运算的结果就是图形内部的噪点.
6. 形态学
6.1 形态学概述
什么是形态学
-
指一系列处理图像形状特征的图像处理技术
-
形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。
-
这些处理方法基本是对二进制图像进行处理, 即黑白图像
-
卷积核决定着图像处理后的效果
-
形态学常用基本操作有:
-
膨胀和腐蚀
-
开运算
-
闭运算
-
顶帽
-
黑帽
-
6.2 图像全局二值化
-
二值化: 将图像的每个像素变成两种值, 比如0, 255.
-
threshold(src, thresh, maxval, type[, dst])
-
src 最好是灰度图
-
thresh: 阈值
-
maxval: 最大值, 最大值不一定是255
-
type: 操作类型. 常见操作类型如下:
-
# 常见如黑白图
import cv2
import numpy as np
img = cv2.imread('./dog.jpeg')
# 二值化操作,对灰度图像操作
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 返回两个值,一个是阈值,一个是二值化处理后的图片
thresh, dst = cv2.threshold(gray, 90, 255, cv2.THRESH_BINARY)
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.3 自适应阈值二值化
在前面的部分我们使用是全局阈值,整幅图像采用同一个数作为阈值。当时这种方法并不适应与所有情况,尤其是当同一幅图像上的不同部分的具有不同亮度时。这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
- adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
- 这种方法需要我们指定六个参数,返回值只有一个。
- Adaptive Method - 指定计算阈值的方法。
- cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
- cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权重为一个高斯窗口。
- Block Size - 邻域大小(用来计算阈值的区域大小)。
- C - 这就是是一个常数,阈值就等于的平均值或者加权平均值减去这个常数。
- Adaptive Method - 指定计算阈值的方法。
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, 7)
# 展示
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.4 腐蚀操作
-
腐蚀操作也是用卷积核扫描图像, 只不过腐蚀操作的卷积和一般都是1, 如果卷积核内所有像素点都是白色, 那么锚点即为白色.
-
大部分时候腐蚀操作使用的都是全为1的卷积核.
-
erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
-
iterations是腐蚀操作的迭代次数, 次数越多, 腐蚀操作执行的次数越多, 腐蚀效果越明显.
-
import cv2
import numpy as np
# 导入图片
img = cv2.imread('./msb.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()
6.5 获取形态学卷积核
-
opencv提供了获取卷积核的api.不需要我们手工创建卷积核.
-
getStructuringElement(shape, ksize[, anchor])
-
shape是指卷积核的形状, 注意不是指长宽, 是指卷积核中1形成的形状.
-
MORPH_RECT 卷积核中的1是矩形, 常用.
-
MORPH_ELLIPSE 椭圆
-
MORPH_CROSS 十字
-
-
import cv2
import numpy as np
img = cv2.imread('./j.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5)) # 卷积核
print(kernel)
# 腐蚀
dst = cv2.erode(img, kernel)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.6 膨胀操作
膨胀是腐蚀的相反操作, 基本原理是只要保证卷积核的锚点是非0值, 周边无论是0还是非0值, 都变成非0值.
- dilate(img, kernel, iterations=1)
- 膨胀, 使用原图轮廓增加
import cv2
import numpy as np
img = cv2.imread('./msb.png')
kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (5,5))
print(kernel)
dst = cv2.dilate(img, kernel, iterations = 1)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.7 开运算
-
开运算和闭运算都是腐蚀和膨胀的基本应用.
-
开运算 = 腐蚀 + 膨胀
-
morphologyEx(img, MORPH_OPEN, kernel)
-
MORPH_OPEN 表示形态学的开运算
-
kernel 如果噪点比较多, 会选择大一点的kernel, 如果噪点比较小, 可以选择小点的kernel
-
# 开运算
import cv2
import numpy as np
# 开运算 = 腐蚀 + 膨胀 去噪声
img = cv2.imread('./dotj.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
# 调用OpenCV 提供的 api
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv2.imshow('img', np.hstack((img ,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.8 闭运算
-
闭运算 = 膨胀 + 腐蚀
-
填充图像内部的噪点 .
import cv2
import numpy as np
img = cv2.imread('./dotinj.png')
# 闭运算
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (9, 9))
# 调用OpenCV 提供的 api
dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv2.imshow('img', np.hstack((img ,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.9 形态学梯度
-
梯度 = 原图 - 腐蚀
-
腐蚀之后原图边缘变小了, 原图 - 腐蚀 就可以得到腐蚀掉的部分, 即边缘.
import cv2
import numpy as np
img = cv2.imread('./msb.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,2))
# 调用OpenCV 提供的 api
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel)
cv2.imshow('img', np.hstack((img ,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
6.10 顶帽运算
-
顶帽 = 原图 - 开运算
-
开运算的效果是去除图像外的噪点, 原图 - 开运算就得到了去掉的噪点.
# 留下噪声
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_TOPHAT, kernel,iterations = 2)
cv2.imshow('img', np.hstack((img ,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
- 右图为顶帽操作结果 .
6.11 黑帽操作
-
黑帽 = 原图 - 闭运算
-
闭运算可以将图形内部的噪点去掉, 那么原图 - 闭运算的结果就是图形内部的噪点.
# 留下图形内部的噪点
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_BLACKHAT, kernel,iterations = 2)
cv2.imshow('img', np.hstack((img ,dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()