# 图像平滑
img = cv2.imread('lena.jpg')
# 1. 均值滤波
img_mean = cv2.blur(img, ksize=(3,3)) # 注意ksize写法
cv2.imshow('image', img)
cv2.imshow('image_mean', img_mean)
cv2.waitKey(0)
# 2. 中值滤波
img_median = cv2.medianBlur(img, ksize=3) # 注意ksize写法
cv2.imshow('image', img)
cv2.imshow('image_median', img_median)
cv2.waitKey(0)
# 3. 高斯滤波
img_gauss = cv2.GaussianBlur(img, ksize=(3,3), sigmaX=1.2, sigmaY=0.8)
cv2.imshow('image', img)
cv2.imshow('image_gauss', img_gauss)
cv2.waitKey(0)
# 图像锐化
# 1. Sobel算子
# (1)计算x轴方向的偏导
sobelx = cv2.Sobel(src=img, ddepth=cv2.CV_64F, dx=1, dy=0,
ksize=3, scale=1.2, delta=20)
# (2)计算y轴方向的偏导
sobely = cv2.Sobel(src=img, ddepth=cv2.CV_64F, dx=0, dy=1,
ksize=3, scale=1.2, delta=20)
# (3)合并两个方向的结果
sobelx = cv2.convertScaleAbs(sobelx) # 取绝对值,防止计算结果有负值
sobely = cv2.convertScaleAbs(sobely) # 取绝对值,防止计算结果有负值
sobelxy = cv2.addWeighted(sobelx, 0.8, sobely, 0.5, gamma=0)
cv2.imshow('image', img)
cv2.imshow('sobelx', sobelx)
cv2.imshow('sobely', sobely)
cv2.imshow('sobelxy', sobelxy)
cv2.waitKey(0)
2. Scharr算子
cv2.Sobel(ksize=-1)
cv2.Scharr(src=, ddepth=, dx=, dy=, ksize=,
scale=, delta=)
# 3. 拉普拉斯算子
img_lap = cv2.Laplacian(src=img, ddepth=cv2.CV_64F,
ksize=3, scale=1.2, delta=10)
img_lap = cv2.convertScaleAbs(img_lap)
cv2.imshow('image', img)
cv2.imshow('image_laplacian', img_lap)
cv2.waitKey(0)
Canny算子是John F. Canny于 1986 年开发出来的一个多级边缘检测算法。
Canny的目标是找到一个最优的边缘检测算法。 Canny边缘检测算法可以分为以下5个步骤:
应用高斯滤波来平滑图像,目的是去除噪声。
找寻图像的强度梯度(intensity gradients),即找寻一幅图像中灰度强度变化最强的位置。
应用非最大抑制(non-maximum suppression)技术来消除边误检(本来不是但检测出来是),保留了每个像素点上梯度强度的极大值,而删掉其他的值。
应用双阈值的方法来决定可能的(潜在的)边界。
利用滞后技术来跟踪边界。
应用高斯滤波来平滑图像后计算梯度幅值和方向。
图像的边缘可以指向不同方向,因此经典Canny算法用了四个梯度算子来分别计算水平,垂直和对角线方向的梯度。但是通常都不用四个梯度算子来分别计算四个方向。常用的边缘差分算子(如Rober,Prewitt,Sobel)计算水平和垂直方向的差分Gx和Gy。
非最大抑制是一种边缘细化方法。就是保留了每个像素点上梯度强度的极大值,而删掉其他的值。
即获得梯度和方向后,遍历所有像素点,比较当前点的梯度强度和正负梯度方向点的梯度强度:如果当前点的梯度强度和同方向的其他点的梯度强度相比较是最大,保留其值。否则抑制,即设为0。
Canny算法应用双阈值,即一个高阈值和一个低阈值来区分边缘像素。
如果边缘像素点梯度值大于高阈值,则被认为是强边缘点。如果边缘梯度值小于高阈值,大于低阈值,则标记为弱边缘点。小于低阈值的点则被抑制掉。
强边缘点可以认为是真的边缘,弱边缘点则可能是真的边缘,也可能是噪声或颜色变化引起的,后者引起的弱边缘点应该去掉。
所谓的滞后边界跟踪算法检查一个弱边缘点的8连通领域像素,只要有强边缘点存在,那么这个弱边缘点被认为是真是边缘保留下来。
实现Canny算子的方法:
cv2.Canny(image, threshold1, threshold2, apertureSize=None, L2gradient=None)
# 4. canny算子
img_canny = cv2.Canny(image=img, threshold1=100, threshold2=200,
apertureSize=3, L2gradient=False)
cv2.imshow('image', img)
cv2.imshow('image_canny', img_canny)
cv2.waitKey(0)