图像阈值
图像的每一个像素点的 RGB 值都是 0~255 之间的一个数字,我们可以设定一个阈值,当RGB 值大于(小于)这个数就分别进行相应的处理。
ret, dst = cv2.threshold(src, thresh, maxval, type)
src
:输入图,通常来说为单通道的灰度图dst
:输出图thresh
:阈值maxval
:当像素值超过了阈值(或者小于阈值,根据 type 来决定),所赋予的值type
:二值化操作的类型,包含以下5种类型:cv2.THRESH_BINARY
:超过阈值部分取maxval(最大值),否则取 0cv2.THRESH_BINARY_INV
:THRESH_BINARY 的反转cv2.THRESH_TRUNC
:大于阈值部分设为阈值,否则不变cv2.THRESH_TOZERO
:大于阈值部分不改变,否则取 0cv2.THRESH_TOZERO_INV
:THRESH_TOZERO的反转
例:
sky = cv2.imread('media/sky.jpg', cv2.IMREAD_GRAYSCALE)
ret, thresh1 = cv2.threshold(sky, 127, 255, cv2.THRESH_BINARY)
ret, thresh2 = cv2.threshold(sky, 127, 255, cv2.THRESH_BINARY_INV)
ret, thresh3 = cv2.threshold(sky, 127, 255, cv2.THRESH_TRUNC)
ret, thresh4 = cv2.threshold(sky, 127, 255, cv2.THRESH_TOZERO)
ret, thresh5 = cv2.threshold(sky, 127, 255, cv2.THRESH_TOZERO_INV)
titles = ['Original Image', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
images = [sky, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
图像平滑
也称滤波。
如图,这张图片上有很多噪音点,图像平滑的目标就是消除这些噪音点。
均值滤波
也称模糊,就是简单的平均卷积操作。
关于 卷积 可以参阅 理解图像卷积操作的意义_zxucver_CSDN 。
blur = cv2.blur(img, (3, 3))
(3, 3)
是规定的 卷积核 大小。
- 橙色区域就是卷积核。
方框滤波
基本和均值滤波相同,可以选择是否归一化。
box = cv2.boxFilter(img, -1, (3, 3), normalize=False)
如果不归一化,RGB 值很容易越界,就会取 255,图片就会很白。
高斯滤波
离卷积核中心最近,权值越大。比如:
gaussian = cv2.GaussianBlur(img, (5, 5), 1)
中值滤波
用卷积核的中值代替。
median = cv2.medianBlur(img, 5)
对比展示
import numpy as np
res = np.hstack((blur, gaussian, median))
cv_show('blur, gaussian, median', res)
可以看到中值滤波是效果最好的。
形态学运算
从上到下分别是:
- 腐蚀
- 膨胀
- 开运算
- 闭运算
- 梯度运算
- 礼帽(顶帽)
- 黑帽
- 击中击不中
腐蚀
正如 “腐蚀” 的含义,图像腐蚀就是把图像(通常是二值图像)中的一部分黑色或白色区域缩减细化。
img = cv2.imread('media/dige.png')
kernel = np.ones((3, 3), np.uint8)
erosion_1 = cv2.erode(img, kernel, iterations=1)
erosion_2 = cv2.erode(img, kernel, iterations=2)
res = np.hstack((img, erosion_1, erosion_2))
cv_show('img, erosion_1, erosion_2', res)
pie = cv2.imread('media/pie.png')
kernel = np.ones((30, 30), np.uint8)
erosion_1 = cv2.erode(pie, kernel, iterations=1)
erosion_2 = cv2.erode(pie, kernel, iterations=2)
res = np.hstack((pie, erosion_1, erosion_2))
cv_show('pie, erosion_1, erosion_2', res)
膨胀
膨胀就是和腐蚀相反。
img = cv2.imread('media/dige.png')
kernel = np.ones((3, 3), np.uint8)
dige_erosion = cv2.erode(img, kernel, iterations=1)
dige_dilate_1 = cv2.dilate(dige_erosion, kernel, iterations=1)
dige_dilate_2 = cv2.dilate(dige_erosion, kernel, iterations=2)
res = np.hstack((dige_erosion, dige_dilate_1, dige_dilate_2))
cv_show('dige_erosion, dige_dilate_1, dige_dilate_2', res)
pie = cv2.imread('media/pie.png')
kernel = np.ones((30, 30), np.uint8)
dilate_1 = cv2.dilate(pie, kernel, iterations=1)
dilate_2 = cv2.dilate(pie, kernel, iterations=2)
res = np.hstack((pie, dilate_1, dilate_2))
cv_show('pie, dilate_1, dilate_2', res)
开运算与闭运算
开运算:先腐蚀再膨胀。
img = cv2.imread('media/dige.png')
kernel = np.ones((5, 5), np.uint8)
opening = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel)
cv_show('opening', opening)
闭运算:先膨胀再腐蚀。
img = cv2.imread('media/dige.png')
kernel = np.ones((5, 5), np.uint8)
closing = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel)
cv_show('opening', closing)
梯度运算
梯度运算 = 膨胀 - 腐蚀
pie = cv2.imread('media/pie.png')
kernel = np.ones((7, 7), np.uint8)
dilate = cv2.dilate(pie, kernel, iterations=2)
erosion = cv2.erode(pie, kernel, iterations=2)
res = np.hstack((dilate, erosion))
cv_show('res', res)
pie = cv2.imread('media/pie.png')
kernel = np.ones((5, 5), np.uint8)
gradient = cv2.morphologyEx(pie, cv2.MORPH_GRADIENT, kernel)
cv_show('gradient', gradient)
礼帽与黑帽
礼帽 = 原始 - 开运算
img = cv2.imread('media/dige.png')
kernel = np.ones((3, 3), np.uint8)
tophat = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel)
cv_show('tophat', tophat)
黑帽 = 闭运算 - 原始
img = cv2.imread('media/dige.png')
kernel = np.ones((7, 7), np.uint8)
tophat = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel)
cv_show('tophat', tophat)