什么是形态学?
二值化:将图像中的每个像素变成两种值,比如0,255
threshold()
用法:
cv2.threshold(src, thresh, maxval, type, dst)
参数说明:
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/dog_1.bmp')
# 二值化对灰度图像操作
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# threshold() 返回两个值 一个是阈值 一个是处理后图像
ret, dst = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
在前面的部分我们使用的是全局阈值,整幅图像采用同一个数作为阈值。但是这种方法并不适用于所有情况,尤其是当同一幅图像上的不同部分具有不同亮度时。
这种情况下我们需要采用自适应阈值。此时的阈值是根据图像上的每一个小区域计算出与其对应的阈值。因此在同一幅图像上的不同区域采用的是不同的阈值,从而使我们能在亮度不同的情况下得到更好的结果。
adaptiveThreshold()
用法:
cv2.adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst)
参数说明:
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/dog_1.bmp')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应阈值二值化,只有一个返回值
dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 5, 0)
cv2.imshow('dog', np.hstack((gray, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
腐蚀操作也是用卷积核扫描图像,只不过腐蚀操作的卷积核一般都是1,如果卷积核内所有像素点都是白色,那么锚点即为白色。
大部分时候,腐蚀操作使用的都是全为1的卷积核。
erode()
用法:
cv2.erode(src, kernel, dst, anchor, iterations, borderType, borderValue)
参数说明:
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint.png')
kernel = np.ones((3, 3), np.uint8)
dst = cv2.erode(img, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
OpenCV提供了获取卷积核的API,不需要我们手动创建卷积核。
getStructuringElement()
用法:
cv2.getStructuringElement(shape, ksize, anchor)
参数说明:
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint_1.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.erode(img, kernel, iterations=2)
cv2.imshow('dog', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
膨胀是腐蚀的相反操作,基本原理:只要保证卷积核的锚点是非0值,周边无论是0还是非0值,都变成非0值。
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint_1.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.dilate(img, kernel, iterations=2)
cv2.imshow('dog', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
import cv2
import numpy as np
img = cv2.imread('../resource/paint.png')
# 定义卷积核
kernel = np.ones((5, 5), np.uint8)
# 腐蚀
dst = cv2.erode(img, kernel, iterations=1)
# 膨胀
dst = cv2.dilate(dst, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
开运算和闭运算都是腐蚀和膨胀的基本应用。
开运算 = 腐蚀 + 膨胀
morphologyEx()
用法:
cv2.morphologyEx(src, op, kernel, dst, anchor, iterations, borderType, borderValue)
参数说明:
op:表示形态学的开运算(MORPH_OPEN)。
kernel:如果噪点比较多,会选择大一点的kernel;反之选择小一点的kernel。
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
# 腐蚀
# dst = cv2.erode(img, kernel, iterations=1)
# 膨胀
# dst = cv2.dilate(dst, kernel, iterations=1)
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
闭运算 = 膨胀 + 腐蚀
morphologyEx()
用法:
cv2.morphologyEx(src, op, kernel, dst, anchor, iterations, borderType, borderValue)
参数说明:
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint_2.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel, iterations=2)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.MORPH_GRADIENT
梯度 = 原图 - 腐蚀
腐蚀之后原图像边缘变小了,原图 - 腐蚀 就可以得到腐蚀掉的部分,即边缘。
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint_1.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.MORPH_TOPHAT
顶帽 = 原图 - 开运算
开运算的效果是去除图像外的噪点,原图 - 开运算 就得到了去掉的噪点。
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
cv2.MORPH_BLACKHAT
黑帽 = 原图 - 闭运算
闭运算可以将图像内部的噪点去除,那么原图 - 闭运算 的结果就是图像内部的噪点。
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint_2.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()
内部的噪点去除,那么原图 - 闭运算 的结果就是图像内部的噪点。
代码实现:
import cv2
import numpy as np
img = cv2.imread('../resource/paint_2.png')
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel, iterations=1)
cv2.imshow('OpenCV', np.hstack((img, dst)))
cv2.waitKey(0)
cv2.destroyAllWindows()