目录
一、阈值处理
二、图像的平滑处理
三、腐蚀与膨胀
import cv2 as cv
import numpy as np
from matplotlib import pyplot as plt
img = cv.imread(r'../de/1_Handshaking_Handshaking_1_314.jpg', 0)
ret, thresh1 = cv.threshold(src=img, thresh=127, maxval=255, type=cv.THRESH_BINARY)
ret, thresh2 = cv.threshold(src=img, thresh=127, maxval=255, type=cv.THRESH_BINARY_INV)
ret, thresh3 = cv.threshold(src=img, thresh=127, maxval=255, type=cv.THRESH_TRUNC)
ret, thresh4 = cv.threshold(src=img, thresh=127, maxval=255, type=cv.THRESH_TOZERO)
ret, thresh5 = cv.threshold(src=img, thresh=127, maxval=255, type=cv.THRESH_TOZERO_INV)
'''
src :输入图片,只能是单通道图片,也就是灰度图
thresh1:输出图片
thresh:阈值
maxval:当像素超过了设置的阈值(或者小于阈值,由type来确定),所赋予的值
type:二值化操作类型,包含五种操作:
cv2.THRESH_BINARY:超过阈值的部分取maxval,否则取零
cv2.THRESH_BINARY_INV:THRESH_BINARY的反转
cv2.THRESH_TRUNC:大于阈值的设为阈值,否则不变
cv2.THRESH_TOZERO:大于阈值的不变,否则设置为零
cv2.THRESH_TOZERO_INV:THRESH_TOZERO的反转
'''
titles = ['img', 'BINARY', 'BINARY_INV', 'TRUNC', 'TOZERO', 'TOZERO_INV']
image = [img, thresh1, thresh2, thresh3, thresh4, thresh5]
for i in range(6):
plt.subplot(2, 3, i+1), plt.imshow(image[i], 'gray')
plt.title(titles[i])
plt.xticks()
plt.yticks()
plt.show()
具体效果:
(1)均值滤波
均值滤波是典型的线性滤波算法,它是指在图像上对目标像素给一个模板,该模板包括了其周围的临近像素(以目标像素为中心的周围8个像素,构成一个滤波模板,即包括目标像素本身),再用模板中的全体像素的平均值来代替原来像素值。
我使用的卷积核大小为3×3,即下图中黄色区域相加 ,然后求取平均数作为中心点的像素值。
在opencv中实现中值滤波:
import cv2 as cv
import numpy as np
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
cat = cv.imread('../de/cat.jpg')
cat = cv.resize(cat, (0, 0), fx=0.4, fy=0.4)
cat_blur = cv.blur(cat, (3, 3)) # 均值滤波
ret = np.hstack((cat, cat_blur)) # 展示所有
show('vs', ret)
原图像(左)和中值滤波后的图像(右)对比:
可以看到,对于椒盐噪声还是有一些效果,但是效果不是很好。
(2)方框滤波
方框滤波基本和均值滤波一样,只需要注意一个参数即可
import cv2 as cv
import numpy as np
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
cat = cv.imread('../de/cat.jpg')
cat = cv.resize(cat, (0, 0), fx=0.4, fy=0.4)
cat_box = cv.boxFilter(cat, -1, (3, 3), normalize=True) # 方框滤波,基本和均值滤波一样,当 normalize=True时,和均值滤波效果一样
cat_box1 = cv.boxFilter(cat, -1, (3, 3), normalize=False) # 当 normalize=False时,不做归一化处理,直接求和,和值大于255时就取255
ret = np.hstack((cat, cat_box, cat_box1)) # 展示所有
show('vs', ret)
从左至右分别是原图、normalize=True 、normalize=False
(3)高斯滤波
高斯滤波,高斯滤波的卷积核里面的卷积核满足高斯分布,相当于更重视中间的值
import cv2 as cv
import numpy as np
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
cat = cv.imread('../de/cat.jpg')
cat = cv.resize(cat, (0, 0), fx=0.4, fy=0.4)
cat_gaussian = cv.GaussianBlur(cat, (3, 3), 1) # 高斯滤波,高斯滤波的卷积核里面的卷积核满足高斯分布,相当于更重视中间的值
ret = np.hstack((cat, cat_gaussian)) # 展示所有
show('vs', ret)
进行高斯滤波后和原图进行对比:
(4)中值滤波
中值滤波, 相当于用中间值代替中心像素值
import cv2 as cv
import numpy as np
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
cat = cv.imread('../de/cat.jpg')
cat = cv.resize(cat, (0, 0), fx=0.4, fy=0.4)
cat_median = cv.medianBlur(cat, 5) # 中值滤波, 相当于用中间值代替
ret = np.hstack((cat, cat_median)) # 展示所有
show('vs', ret)
可以看到对于椒盐噪声,中值滤波的效果最好
腐蚀和膨胀是形态学最基本的操作,都是针对白色部分(高亮部分)而言的。膨胀就是使图像中高亮部分扩张,得到比原图更大的高亮区域;腐蚀是原图像中的高亮区域被蚕食,得到比原图更小的高亮区域。膨胀是求结构元素下像素最大值,腐蚀是求结构元素下像素最小值。
(1)腐蚀和膨胀
腐蚀和膨胀操作都是对于二值图而言的
import cv2 as cv
import numpy as np
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
image = cv.imread('../de/er.jpg')
kernel = np.ones((10, 10), dtype=np.uint8) # 卷积核大小
img_erode = cv.erode(image, kernel, iterations=1) # 进行腐蚀操作,iterations是迭代次数,就是进行几次腐蚀
img_dilate = cv.dilate(image, kernel, iterations=1) # 进行膨胀
res = np.hstack((image, img_erode, img_dilate))
show('vs', res)
原图、腐蚀图和膨胀图之间的对比:
(2)开运算和闭运算
开运算 :先腐蚀后膨胀
闭运算:先膨胀后腐蚀
import cv2 as cv
import numpy as np
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
image = cv.imread('../de/er.jpg')
kernel = np.ones((10, 10), dtype=np.uint8) # 卷积核大小
# 开运算:先腐蚀后膨胀
opening = cv.morphologyEx(image, cv.MORPH_OPEN, kernel)
# 闭运算:先膨胀后腐蚀
closing = cv.morphologyEx(image, cv.MORPH_CLOSE, kernel)
res = np.hstack((image, opening, closing))
show('vs', res)
原图、开运算和闭运算之间对比:
(3)梯度运算
梯度 = 膨胀-腐蚀。可以得到物体的轮廓。
import cv2 as cv
import numpy as np
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
image = cv.imread('../de/er.jpg')
kernel = np.ones((10, 10), dtype=np.uint8) # 卷积核大小
# 梯度=膨胀-腐蚀
gradient = cv.morphologyEx(image, cv.MORPH_GRADIENT, kernel) # 就可以将轮廓显示出来
res = np.hstack((image, gradient))
show('vs', res)
原图和梯度图
(4)礼帽和黑帽
礼帽 = 原始输入-开运算
黑帽 = 闭运算-原始输入
import cv2 as cv
# 图片展示函数
def show(name, img):
cv.imshow(name, img)
cv.waitKey(0)
image = cv.imread('../de/er.jpg')
kernel = np.ones((10, 10), dtype=np.uint8) # 卷积核大小
# 礼帽 = 原始输入-开运算
tophat = cv.morphologyEx(image, cv.MORPH_TOPHAT, kernel)
show('tophat', tophat)
# 黑帽 = 闭运算-原始输入
blackhat = cv.morphologyEx(image, cv.MORPH_BLACKHAT, kernel)
show('blackhat', blackhat)
礼帽效果图:
黑帽效果图: