Roberts、Sobel、Prewitt、Kirsch、Canny、Laplacian图像边缘检测原理及其代码实现(Python3)

边缘检测

  • 在介绍边缘检测之前,我们需要先了解什么是图像梯度?

  • 图像梯度

    函数可以用一阶导数来表示变化程度,而对于二维图像来说,其局部特性的显著变化可以用梯度来表示。梯度是函数变化的一种度量,定义为:
    在这里插入图片描述
    而对数数字图像而言,导数可用差分来近似。
    在这里插入图片描述在这里插入图片描述
    以上就是图像梯度的简单介绍。下面进入本文正题:
    边缘检测算子(edge detectors),是用于在亮度函数中定位变化的非常重要的局部图像预处理方法,边缘是亮度函数发生急剧变化的位置。

  • 一阶微分边缘检测算子
    1.Roberts边缘算子
    Roberts边缘算子是利用局部差分算子寻找边缘的算子,差分公式如下:
    在这里插入图片描述
    2.Sobel边缘算子
    Sobel边缘算子与Roberts边缘算子不同的是,它是在3*3领域内计算梯度值的,这样可以避免像素间内插点上计算梯度。
    在这里插入图片描述3.Prewitt边缘算子
    Prewitt边缘算子与Sobel边缘算子形式上完全一样,只是c=1,Prewitt边缘算子没有将重点放在接近于模板中心的像素点。
    在这里插入图片描述4.Kirsch边缘算子
    Kirsch边缘算子由八个方向的卷积核构成,
    在这里插入图片描述
    5.Canny边缘检测
    Canny边缘检测的过程可以直接采用原始图像与平滑滤波脉冲响应一阶微分的卷积运算来实现。常用的平滑滤波器为高斯函数,图像经过高斯平滑后边缘变得模糊,因此计算的到的边缘就有一定的宽度,这种宽度边缘变细的方法叫做非极大点的抑制
    Canny边缘检测具体步骤如下:
    在这里插入图片描述
    这里滞后阈值化处理大家可以自行百度,该方法比较简单,相信聪明的你们看一遍就完全理解啦。

-图像锐化(sharpening)

目标是使边缘更陡峭,锐化的图像是供人观察的。锐化公式如下:
在这里插入图片描述
拉普拉斯(Laplacian)
拉普拉斯算子常用于这一目的,那么什么是拉普拉斯算子呢?
拉普拉斯(Laplacian)算子在二维图像中,它是常用的二阶微分边缘检测算子,是一种二阶导数算子。
在这里插入图片描述
在这里插入图片描述
Laplacian算子有一个缺点是它对图像中某些边缘产生双重响应
同为二阶微分边缘检测算子的还有LOG算子,又称马尔算子,同时它还是二阶导数过零点的算子。
在这里插入图片描述
在这里插入图片描述
具体代码如下:


#自定义卷积滤波
import cv2
import numpy as np

# 加载图像
image = cv2.imread('D:\Pycharm/untitled/13.jpg',0)
image = cv2.resize(image,(800,800))
# 自定义卷积核
# Roberts边缘算子
kernel_Roberts_x = np.array([
    [1, 0],
    [0, -1]
    ])
kernel_Roberts_y = np.array([
    [0, -1],
    [1, 0]
    ])
# Sobel边缘算子
kernel_Sobel_x = np.array([
    [-1, 0, 1],
    [-2, 0, 2],
    [-1, 0, 1]])
kernel_Sobel_y = np.array([
    [1, 2, 1],
    [0, 0, 0],
    [-1, -2, -1]])
# Prewitt边缘算子
kernel_Prewitt_x = np.array([
    [-1, 0, 1],
    [-1, 0, 1],
    [-1, 0, 1]])
kernel_Prewitt_y = np.array([
    [1, 1, 1],
    [0, 0, 0],
    [-1, -1, -1]])
# Kirsch 边缘检测算子
def kirsch(image):
    m,n = image.shape
    list=[]
    kirsch = np.zeros((m,n))
    for i in range(2,m-1):
        for j in range(2,n-1):
            d1 = np.square(5 * image[i - 1, j - 1] + 5 * image[i - 1, j] + 5 * image[i - 1, j + 1] -
                  3 * image[i, j - 1] - 3 * image[i, j + 1] - 3 * image[i + 1, j - 1] -
                  3 * image[i + 1, j] - 3 * image[i + 1, j + 1])
            d2 = np.square((-3) * image[i - 1, j - 1] + 5 * image[i - 1, j] + 5 * image[i - 1, j + 1] -
                  3 * image[i, j - 1] + 5 * image[i, j + 1] - 3 * image[i + 1, j - 1] -
                  3 * image[i + 1, j] - 3 * image[i + 1, j + 1])
            d3 = np.square((-3) * image[i - 1, j - 1] - 3 * image[i - 1, j] + 5 * image[i - 1, j + 1] -
                  3 * image[i, j - 1] + 5 * image[i, j + 1] - 3 * image[i + 1, j - 1] -
                  3 * image[i + 1, j] + 5 * image[i + 1, j + 1])
            d4 = np.square((-3) * image[i - 1, j - 1] - 3 * image[i - 1, j] - 3 * image[i - 1, j + 1] -
                  3 * image[i, j - 1] + 5 * image[i, j + 1] - 3 * image[i + 1, j - 1] +
                  5 * image[i + 1, j] + 5 * image[i + 1, j + 1])
            d5 = np.square((-3) * image[i - 1, j - 1] - 3 * image[i - 1, j] - 3 * image[i - 1, j + 1] - 3
                  * image[i, j - 1] - 3 * image[i, j + 1] + 5 * image[i + 1, j - 1] +
                  5 * image[i + 1, j] + 5 * image[i + 1, j + 1])
            d6 = np.square((-3) * image[i - 1, j - 1] - 3 * image[i - 1, j] - 3 * image[i - 1, j + 1] +
                  5 * image[i, j - 1] - 3 * image[i, j + 1] + 5 * image[i + 1, j - 1] +
                  5 * image[i + 1, j] - 3 * image[i + 1, j + 1])
            d7 = np.square(5 * image[i - 1, j - 1] - 3 * image[i - 1, j] - 3 * image[i - 1, j + 1] +
                  5 * image[i, j - 1] - 3 * image[i, j + 1] + 5 * image[i + 1, j - 1] -
                  3 * image[i + 1, j] - 3 * image[i + 1, j + 1])
            d8 = np.square(5 * image[i - 1, j - 1] + 5 * image[i - 1, j] - 3 * image[i - 1, j + 1] +
                  5 * image[i, j - 1] - 3 * image[i, j + 1] - 3 * image[i + 1, j - 1] -
                  3 * image[i + 1, j] - 3 * image[i + 1, j + 1])

            # 第一种方法:取各个方向的最大值,效果并不好,采用另一种方法
            list=[d1, d2, d3, d4, d5, d6, d7, d8]
            kirsch[i,j]= int(np.sqrt(max(list)))
            # 第二种方法:对各个方向的模长取整
            #kirsch[i, j] =int(np.sqrt(d1+d2+d3+d4+d5+d6+d7+d8))
    for i in range(m):
        for j in range(n):
            if kirsch[i,j]>127:
                kirsch[i,j]=255
            else:
                kirsch[i,j]=0
    return kirsch

# Canny边缘检测 k为高斯核大小,t1,t2为阈值大小
def Canny(image,k,t1,t2):
    img = cv2.GaussianBlur(image, (k, k), 0)
    canny = cv2.Canny(img, t1, t2)
    return canny
# 拉普拉斯卷积核
kernel_Laplacian_1 = np.array([
    [0, 1, 0],
    [1, -4, 1],
    [0, 1, 0]])
kernel_Laplacian_2 = np.array([
    [1, 1, 1],
    [1, -8, 1],
    [1, 1, 1]])
#下面两个卷积核不具有旋转不变性
kernel_Laplacian_3 = np.array([
    [2, -1, 2],
    [-1, -4, -1],
    [2, 1, 2]])
kernel_Laplacian_4 = np.array([
    [-1, 2, -1],
    [2, -4, 2],
    [-1, 2, -1]])
# 5*5 LoG卷积模板
kernel_LoG = np.array([
    [0, 0, -1, 0, 0],
    [0, -1, -2, -1, 0],
    [-1, -2, 16, -2, -1],
    [0, -1, -2, -1, 0],
    [0, 0, -1, 0, 0]])
# 卷积

output_1 = cv2.filter2D(image, -1, kernel_Prewitt_x)
output_2 = cv2.filter2D(image, -1, kernel_Sobel_x)
output_3 = cv2.filter2D(image, -1, kernel_Prewitt_x)
output_4 = cv2.filter2D(image, -1, kernel_Laplacian_1)
output_5 = Canny(image,3,50,150)
output_6 = kirsch(image)
# 显示锐化效果
image = cv2.resize(image, (800, 600))
output_1 = cv2.resize(output_1, (800, 600))
output_2 = cv2.resize(output_2, (800, 600))
output_3 = cv2.resize(output_3, (800, 600))
output_4 = cv2.resize(output_4, (800, 600))
output_5 = cv2.resize(output_5, (800, 600))
output_6 = cv2.resize(output_6, (800, 600))
cv2.imshow('Original Image', image)
cv2.imshow('sharpen_1 Image', output_1)
cv2.imshow('sharpen_2 Image', output_2)
cv2.imshow('sharpen_3 Image', output_3)
cv2.imshow('sharpen_4 Image', output_4)
cv2.imshow('sharpen_5 Image', output_5)
cv2.imshow('sharpen_6 Image', output_6)
# 停顿
if cv2.waitKey(0) & 0xFF == 27:
    cv2.destroyAllWindows()

效果如图所示:
原图
原图像
在这里插入图片描述
Roberts算子在x轴方向
在这里插入图片描述
Sobel算子在x轴方向
在这里插入图片描述
Prewitt算子在x轴方向
在这里插入图片描述
Laplacian算子在x轴方向
在这里插入图片描述
Canny边缘检测
在这里插入图片描述
kirsch边缘检测算子

  • 4
    点赞
  • 62
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是可以回答的 Matlab 代码: ``` % 读入灰度图像 img = imread('image.jpg'); gray_img = rgb2gray(img); % Roberts 算子 roberts_h = [1 0; 0 -1]; roberts_v = [0 1; -1 0]; roberts_h_img = imfilter(double(gray_img), roberts_h); roberts_v_img = imfilter(double(gray_img), roberts_v); roberts_img = sqrt(roberts_h_img.^2 + roberts_v_img.^2); % Prewitt 算子 prewitt_h = [-1 0 1; -1 0 1; -1 0 1]; prewitt_v = [-1 -1 -1; 0 0 0; 1 1 1]; prewitt_h_img = imfilter(double(gray_img), prewitt_h); prewitt_v_img = imfilter(double(gray_img), prewitt_v); prewitt_img = sqrt(prewitt_h_img.^2 + prewitt_v_img.^2); % Sobel 算子 sobel_h = [-1 0 1; -2 0 2; -1 0 1]; sobel_v = [-1 -2 -1; 0 0 0; 1 2 1]; sobel_h_img = imfilter(double(gray_img), sobel_h); sobel_v_img = imfilter(double(gray_img), sobel_v); sobel_img = sqrt(sobel_h_img.^2 + sobel_v_img.^2); % 拉普拉斯高斯算子 log_filter = fspecial('log'); log_img = imfilter(double(gray_img), log_filter); % 显示结果 figure; subplot(2, 3, 1); imshow(gray_img); title('原图'); subplot(2, 3, 2); imshow(roberts_img, []); title('Roberts 算子'); subplot(2, 3, 3); imshow(prewitt_img, []); title('Prewitt 算子'); subplot(2, 3, 4); imshow(sobel_img, []); title('Sobel 算子'); subplot(2, 3, 5); imshow(log_img, []); title('拉普拉斯高斯算子'); ``` 注意,上述代码没有对输入的图像进行错误检查和处理,实际应用时需要添加相应的代码。另外,不同算子的边缘检测结果有时会不同,可以选择最适合具体应用的方法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值