- 形态学
- 1. 二值化
- 1.1 图像全局二值化
- 1.2 自适应二值化
- 2. 腐蚀
- 2.1 自定义kernel
- 2.2 获取形态学kernel
- 3. 膨胀
- 4. 开运算
- 5. 闭运算
- 6. 形态学梯度
- 7. 顶帽操作
- 8. 黑帽操作
系列所有代码,复制粘贴即可运行。
希望有能力的朋友还是拿C++运行一下。
形态学本节讨论图像的二值化,局部二值化,膨胀,腐蚀,开运算,闭运算,顶帽,黑帽等
仍然是利用卷积核,来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别,基本操作有(基本都处理二进制图像):
- 膨胀和腐蚀
- 开运算
- 闭运算
- 顶帽
- 黑帽
- 形态学的魅力就在于可以获取各种形态的图形,感兴趣区域,噪点等
threshold(src, thresh, maxval, type[,dst])
- src: 灰度图
- thresh:阈值
- maxval:最大值
- type:操作类型,开窗,截断等
import cv2
import numpy as np
img = cv2.imread('cat.jpeg')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 阈值 处理后图片
ret, dst = cv2.threshold(gray, 120, 255, cv2.THRESH_BINARY)
#print(dst)
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
1.2 自适应二值化
同一图像上,不同部分具有不同亮度时。根据图像上每一个小区域计算与其对应的阈值,从而能在亮度不同的情况下得到更好的结果
- adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C[, dst])
- adaptiveMethod:指定计算阈值的方法
- cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域平均值
- cv2.ADPTIBE_THRESH_GAUSSIAN_C:阈值取自相邻区域的加权和,权重为一高斯窗口
- Block Size: 邻域(卷积核)大小
- C: 阈值等于计算结果加上这个常数
- adaptiveMethod:指定计算阈值的方法
#自适应阈值只返回一个值,即二值化后的图像 ##这里的kernel size仍然只是一个数 dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C,cv2.THRESH_BINARY_INV,21,0) #print(dst)2. 腐蚀
腐蚀操作也是用卷积核扫描图像,大部分腐蚀操作的卷积核内数字都是1,卷积操作就是相乘再相加
- 核中1所在的位置:全白(255)才为白,有黑(0)则为黑
- erode(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
- iterations是腐蚀操作的迭代次数,次数越多,效果越明显
- 腐蚀操作是放大暗部
import cv2
import numpy as np
cat = cv2.imread('homework.jpg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
#定义核
kernel = np.ones((5,5), np.uint8)
dst = cv2.erode(img, kernel, iterations=1)
cv2.imshow('cat', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
2.2 获取形态学kernel
- getStructuringElement(shape, ksize[, anchor])
- shape: 卷积核形状,不是长款,是卷积核中1的元素所形成的形状
- MORPH_RECT 卷积核中1的形成矩形
- MORPH_ELLIPSE 椭圆
- MORPH_CROSS 十字
- shape: 卷积核形状,不是长款,是卷积核中1的元素所形成的形状
import cv2
import numpy as np
cat = cv2.imread('homework.jpg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
#自主获取的卷积核
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dst = cv2.erode(img, kernel, iterations=1)
cv2.imshow('cat', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
3. 膨胀
膨胀是腐蚀的反操作,只要保证卷积核的锚点是非0值,周边值均变为非零值
- 膨胀是放大白色
- 核中1对应的位置:有白(255)则为白,全黑(0)才为黑/对锚点而言
- dilate(src, kernel[, dst[, anchor[, iterations[, borderType[, borderValue]]]]])
import cv2
import numpy as np
cat = cv2.imread('homework.jpg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
#定义核
#kernel = np.ones((5,5), np.uint8)
#自主获取的卷积核
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dst = cv2.dilate(img, kernel, iterations=1)
cv2.imshow('cat', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
4. 开运算
- 开运算 = 先腐蚀 + 后膨胀
- 适用: 黑背景 白噪点
- morphologyEx(img, MORPH_OPEN, kernel)
- MORPH_OPEN: 形态学的开运算
- kernel 如果噪点较多 选择大一点的kernel,如果噪点较少,选择小点的kernel
#开运算提供了另一种去噪声的思路
cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
#腐蚀
#dst = cv2.erode(img, kernel, iterations=2)
#膨胀
#dst = cv2.dilate(img,kernel, iterations=2)
#直接调用opencv提供的开运算
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=2)
cv2.imshow('img', np.hstack((img, dst)))
5. 闭运算
- 闭运算 = 先膨胀 + 后腐蚀
- 适用:白背景 黑噪点
- morphologyEx(img, MORPH_CLOSE, kernel)
- MORPH_CLOSE: 形态学的闭运算
- kernel 如果噪点较多 选择大一点的kernel,如果噪点较少,选择小点的kernel
cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
#膨胀
#dst = cv2.dilate(img,kernel, iterations=2)
#腐蚀
#dst = cv2.erode(img, kernel, iterations=2)
#直接调用opencv提供的开运算
dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)
cv2.imshow('img', np.hstack((img, dst)))
6. 形态学梯度
- 梯度 = 原图图像 - 腐蚀的图像
- 腐蚀之后原图边缘变小了,做差后就可以得到腐蚀掉的部分,即边缘
- morphologyEx(img, MORPH_GRADIENT, kernel)
- MORPH_GRADIENT: 形态学梯度
import cv2
import numpy as np
cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
#调节kernel大小获得更清晰的边缘,腐蚀掉的东西
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)
cv2.imshow('img', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
7. 顶帽操作
- 顶帽 = 原图 - 开运算
- 黑图取被滤的白噪点
- 开运算的效果是去除噪点,顶帽得到了去掉的噪点
- morphologyEx(img, MORPH_TOPHAT, kernel)
- MORPH_TOPHAT: 顶帽操作
cat = cv2.imread('cat.jpeg')
img = cv2.cvtColor(cat, cv2.COLOR_BGR2GRAY)
#调节kernel大小以保留小图形
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (19,19))
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=1)
cv2.imshow('img', np.hstack((img, dst)))
8. 黑帽操作
- 黑帽 = 原图 - 闭运算
- 白中取被滤的黑噪点
- 闭运算的效果是去除图像内部的噪点,黑帽得到了图形内部去掉的噪点
- morphologyEx(img, MORPH_BLACKHAT, kernel)
- MORPH_BLACKHAT: 黑帽操作



