Python实现Roberts、Sobel与Laplace算子的图像边缘提取
本文详细解析如何使用Python结合OpenCV与NumPy,手动实现Roberts、Sobel和Laplace三种经典算子进行图像边缘提取。通过遍历像素点并执行矩阵卷积运算,计算梯度幅值或二阶导数,最终将结果转换为uint8格式并显示处理前后的图像对比。
边缘提取的核心原理
图像边缘提取的本质是寻找像素灰度值发生剧烈变化的区域。在数学上,这通常通过计算图像矩阵与特定卷积核(算子)的卷积来实现。具体步骤包括:将图片矩阵与算子进行卷积求和,对卷积结果取绝对值,并将计算出的值存入一个与原图大小相同的矩阵中。最后,为了在屏幕上正确显示,需要将接收卷积和值的矩阵数据类型转换为 uint8。
Roberts 算子实现
Roberts 算子是一种利用局部差分算子寻找边缘的算子,其对具有陡峭的低噪声图像的效果最好。它使用对角线方向的相邻像素之差来近似梯度。
# robert 算子[[-1,-1],[1,1]]
def robert_suanzi(img):
r, c = img.shape
r_sunnzi = [[-1,-1],[1,1]]
for x in range(r):
for y in range(c):
if (y + 2 <= c) and (x + 2 <= r):
imgChild = img[x:x+2, y:y+2]
list_robert = r_sunnzi*imgChild
img[x, y] = abs(list_robert.sum()) # 求和加绝对值
return img在实现中,我们遍历图像的每个像素点。对于坐标 (x, y),提取其右下角的 2x2 子矩阵 imgChild。将该子矩阵与 Roberts 算子矩阵进行逐元素相乘(在 NumPy 中,列表与数组相乘会触发广播机制),然后求和并取绝对值,结果直接覆盖原图对应位置。
Sobel 算子实现
Sobel 算子结合了高斯平滑和微分求导,对噪声具有平滑作用,能提供较理想的检测效果。它分别计算水平和垂直方向的梯度,然后合成总梯度。
# # sobel算子的实现
def sobel_suanzi(img):
r, c = img.shape
new_image = np.zeros((r, c))
new_imageX = np.zeros(img.shape)
new_imageY = np.zeros(img.shape)
s_suanziX = np.array([[-1,0,1],[-2,0,2],[-1,0,1]]) # X方向
s_suanziY = np.array([[-1,-2,-1],[0,0,0],[1,2,1]])
for i in range(r-2):
for j in range(c-2):
new_imageX[i+1, j+1] = abs(np.sum(img[i:i+3, j:j+3] * s_suanziX))
new_imageY[i+1, j+1] = abs(np.sum(img[i:i:i+3, j:j+3] * s_suanziY))
new_image[i+1, j+1] = (new_imageX[i+1, j+1]*new_imageX[i+1,j+1] + new_imageY[i+1, j+1]*new_imageY[i+1,j+1])**0.5
# return np.uint8(new_imageX)
# return np.uint8(new_imageY)
return np.uint8(new_image) # 无方向算子处理的图像代码首先初始化用于存储 X 方向、Y 方向以及最终合成结果的矩阵。Sobel 算子包含两个 3x3 的卷积核,分别对应 X 方向和 Y 方向。在双重循环中,提取 3x3 的子图像区域,分别与 X 和 Y 方向的算子进行卷积求和并取绝对值。最终图像的梯度幅值通过公式 sqrt(Gx^2 + Gy^2) 计算得出,最后转换为 uint8 类型返回。
Laplace 算子实现
Laplace 算子是二阶微分算子,对图像中的线条和孤立点比较敏感。常用的 Laplace 模板有两种形式,本文采用其中一种:
# Laplace算子
# 常用的Laplace算子模板 [[0,1,0],[1,-4,1],[0,1,0]] [[1,1,1],[1,-8,1],[1,1,1]]
def Laplace_suanzi(img):
r, c = img.shape
new_image = np.zeros((r, c))
L_sunnzi = np.array([[0,-1,0],[-1,4,-1],[0,-1,0]])
# L_sunnzi = np.array([[1,1,1],[1,-8,1],[1,1,1]])
for i in range(r-2):
for j in range(c-2):
new_image[i+1, j+1] = abs(np.sum(img[i:i+3, j:j+3] * L_sunnzi))
return np.uint8(new_image)该函数同样遍历图像,提取 3x3 区域与指定的 Laplace 卷积核进行卷积运算。计算结果取绝对值后存入新矩阵,最终返回转换后的图像。注意,Laplace 算子对噪声非常敏感,通常在实际应用中会先进行高斯平滑处理。
完整运行代码与结果展示
以下代码展示了如何读取灰度图像,并依次应用上述三种算子进行边缘提取,最后通过 OpenCV 窗口显示处理前后的图像。
img = cv2.imread('1.jpg', cv2.IMREAD_GRAYSCALE)
cv2.imshow('image', img)
# # robers算子
out_robert = robert_suanzi(img)
cv2.imshow('out_robert_image', out_robert)
# sobel 算子
out_sobel = sobel_suanzi(img)
cv2.imshow('out_sobel_image', out_sobel)
# Laplace算子
out_laplace = Laplace_suanzi(img)
cv2.imshow('out_laplace_image', out_laplace)
cv2.waitKey(0)
cv2.destroyAllWindows()程序首先读取名为 1.jpg 的图像并转换为灰度模式。随后,分别调用 robert_suanzi、sobel_suanzi 和 Laplace_suanzi 函数处理图像,并将结果在独立的窗口中显示。按任意键关闭窗口。
以上就是Python通过Roberts、Sobel、Laplace算子实现图像边缘提取的详细内容,更多关于Python图像处理资料请关注本站其它相关文章!免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









