图像边缘信息主要集中在高频段,通常说图像锐化或检测边缘,实质就是高频滤波。
Canny算法实现分为以下几步:
图像灰度化
高斯模糊处理
图像梯度、梯度幅值、梯度方向计算
NMS(非极大值抑制)
双阈值的边界选取
运行代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread('D:\pythonb\chepai.jpg')
lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
#灰度化处理
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
#高斯滤波降噪
gaussian = cv2.GaussianBlur(grayImage, (3, 3), 0)
#腐蚀化
kernel = np.ones((5,5), np.uint8)
k_ys = cv2.morphologyEx(gaussian, cv2.MORPH_OPEN, kernel)
#Canny算子
Canny = cv2.Canny(k_ys, 50, 150)
#用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
#显示图形
titles = [u'原始图像', u'高斯滤波',u'Canny算子',]
images = [lenna_img, k_ys,Canny,]
for i in range(3):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()
sobel算子检测原理参考博文:
Sobel算子使用两个(3x3)矩阵来对原图进行卷积运算以计算出两个方向的灰度差分(偏导)的估计值(一个水平方向、一个竖直方向)。我们假定A是原始图像(彩色图像需先转换为灰度图像),Gx和Gy分别是在横向及纵向的灰度偏导的近似值(即两个方向上对原图的平面卷积结果)。数学表达如下:
对应的计算过程如下:
Gx = [ f(x+1,y-1)+2f(x+1,y)+f(x+1,y+1)] -
[f(x-1,y-1)+2f(x-1,y)+f(x-1,y+1) ]
Gy = [ f(x-1,y-1) + 2f(x,y-1) + f(x+1,y-1)] -
[f(x-1, y+1) + 2*f(x,y+1)+f(x+1,y+1)
通过横向Gx和 纵向Gy的计算得到其梯度的估计值G和:
运行代码如下:
import cv2
import numpy as np
import matplotlib.pyplot as plt
# 读取图像
img = cv2.imread('D:\pythonb\sobel.jpg')
lenna_img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# 灰度化处理图像
grayImage = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# Sobel算子
x = cv2.Sobel(grayImage, cv2.CV_16S, 1, 0) # 对x求一阶导,垂直检测
y = cv2.Sobel(grayImage, cv2.CV_16S, 0, 1) # 对y求一阶导,水平检测
absX = cv2.convertScaleAbs(x)
absY = cv2.convertScaleAbs(y)
Sobel = cv2.addWeighted(absX, 0.5, absY, 0.5, 0)
# 用来正常显示中文标签
plt.rcParams['font.sans-serif'] = ['SimHei']
#显示图形
titles = [u'原始图像', u'垂直检测',u'水平检测',u'sobel']
images = [lenna_img, absX, absY, Sobel]
for i in range(4):
plt.subplot(2, 2, i + 1), plt.imshow(images[i], 'gray')
plt.title(titles[i])
plt.xticks([]), plt.yticks([])
plt.show()