python实现图像特征提取算法1

1.Marr-Hildreth算法详解

Marr-Hildreth算法是一个用于图像边缘检测的经典算法,其基本思想是通过检测图像的二阶导数(拉普拉斯算子)来找到边缘。该算法首先对图像进行高斯平滑处理,以减少噪声,然后计算拉普拉斯算子,最后通过检测零交叉点来确定边缘。

算法步骤
  1. 高斯平滑:使用高斯滤波器对图像进行平滑处理,以减少噪声。
  2. 计算拉普拉斯算子:对平滑后的图像计算拉普拉斯算子。
  3. 检测零交叉点:在拉普拉斯算子图像中检测零交叉点,这些点即为边缘。
公式

在这里插入图片描述

Python 实现

以下是Marr-Hildreth算法的Python实现代码:

import numpy as np
import cv2
import matplotlib.pyplot as plt

def marr_hildreth(image, sigma=1.4):
    """
    Marr-Hildreth边缘检测算法实现

    参数:
    image (numpy.ndarray): 输入的灰度图像
    sigma (float): 高斯平滑的标准差

    返回:
    numpy.ndarray: 边缘检测后的二值化图像
    """
    # 1. 高斯平滑
    smoothed_image = cv2.GaussianBlur(image, (0, 0), sigma)

    # 2. 计算拉普拉斯算子
    laplacian = cv2.Laplacian(smoothed_image, cv2.CV_64F)

    # 3. 检测零交叉点
    zero_crossing = np.zeros_like(laplacian)
    for i in range(1, laplacian.shape[0] - 1):
        for j in range(1, laplacian.shape[1] - 1):
            if laplacian[i, j] == 0:
                if (laplacian[i, j-1] < 0 and laplacian[i, j+1] > 0) or (laplacian[i, j-1] > 0 and laplacian[i, j+1] < 0) or \
                   (laplacian[i-1, j] < 0 and laplacian[i+1, j] > 0) or (laplacian[i-1, j] > 0 and laplacian[i+1, j] < 0):
                    zero_crossing[i, j] = 255
            elif laplacian[i, j] < 0:
                if (laplacian[i, j-1] > 0 or laplacian[i, j+1] > 0 or laplacian[i-1, j] > 0 or laplacian[i+1, j] > 0):
                    zero_crossing[i, j] = 255

    return zero_crossing

# 示例用法
if __name__ == "__main__":
    # 读取灰度图像
    image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
    
    # 调用Marr-Hildreth边缘检测算法
    edges = marr_hildreth(image)
    
    # 显示原始图像和边缘检测后的图像
    plt.figure(figsize=(12, 6))
    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(image, cmap='gray')
    plt.axis('off')
    
    plt.subplot(1, 2, 2)
    plt.title('Marr-Hildreth Edges')
    plt.imshow(edges, cmap='gray')
    plt.axis('off')
    plt.show()
详细解释
  1. 读取图像并转换为灰度图像

    image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
    
  2. 高斯平滑

    smoothed_image = cv2.GaussianBlur(image, (0, 0), sigma)
    

    这里使用OpenCV的GaussianBlur函数对图像进行高斯平滑处理。

  3. 计算拉普拉斯算子

    laplacian = cv2.Laplacian(smoothed_image, cv2.CV_64F)
    

    使用OpenCV的Laplacian函数计算平滑后的图像的拉普拉斯算子。

  4. 检测零交叉点

    zero_crossing = np.zeros_like(laplacian)
    for i in range(1, laplacian.shape[0] - 1):
        for j in range(1, laplacian.shape[1] - 1):
            if laplacian[i, j] == 0:
                if (laplacian[i, j-1] < 0 and laplacian[i, j+1] > 0) or (laplacian[i, j-1] > 0 and laplacian[i, j+1] < 0) or \
                   (laplacian[i-1, j] < 0 and laplacian[i+1, j] > 0) or (laplacian[i-1, j] > 0 and laplacian[i+1, j] < 0):
                    zero_crossing[i, j] = 255
            elif laplacian[i, j] < 0:
                if (laplacian[i, j-1] > 0 or laplacian[i, j+1] > 0 or laplacian[i-1, j] > 0 or laplacian[i+1, j] > 0):
                    zero_crossing[i, j] = 255
    

    通过遍历拉普拉斯算子图像中的每个像素,并根据其相邻像素值检测零交叉点,从而确定边缘。

  5. 显示和保存边缘检测后的图像

    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(image, cmap='gray')
    plt.axis('off')
    
    plt.subplot(1, 2, 2)
    plt.title('Marr-Hildreth Edges')
    plt.imshow(edges, cmap='gray')
    plt.axis('off')
    plt.show()
    
优缺点

优点

  • 噪声抑制:通过高斯平滑处理,可以有效地抑制噪声。
  • 边缘检测准确:通过检测零交叉点,能够准确地找到图像中的边缘。

缺点

  • 计算复杂度高:计算高斯平滑和拉普拉斯算子比较耗时。
  • 参数敏感:平滑参数(σ)对结果影响较大,需要根据具体图像进行调整。

Marr-Hildreth算法通过高斯平滑和拉普拉斯算子相结合,实现了对图像边缘的有效检测,广泛应用于图像处理和计算机视觉领域。

2.Canny边缘检测器算法详解

Canny边缘检测器是一种经典的图像处理算法,用于检测图像中的边缘。它通过多步骤的处理流程来实现高质量的边缘检测,包括高斯平滑、计算梯度、非极大值抑制、双阈值检测和边缘跟踪。

算法步骤
  1. 高斯平滑:使用高斯滤波器对图像进行平滑处理,以减少噪声。
  2. 计算梯度:计算图像的梯度强度和方向。
  3. 非极大值抑制:对梯度图像进行非极大值抑制,以细化边缘。
  4. 双阈值检测:通过设定高低阈值,将像素分类为强边缘、弱边缘和非边缘。
  5. 边缘跟踪:通过连接强边缘像素,形成完整的边缘。
公式

在这里插入图片描述

Python 实现

以下是Canny边缘检测器的Python实现代码:

import numpy as np
import cv2
import matplotlib.pyplot as plt

def canny_edge_detection(image, sigma=1.4, low_threshold=20, high_threshold=60):
    """
    Canny边缘检测算法实现

    参数:
    image (numpy.ndarray): 输入的灰度图像
    sigma (float): 高斯平滑的标准差
    low_threshold (int): 双阈值低阈值
    high_threshold (int): 双阈值高阈值

    返回:
    numpy.ndarray: 边缘检测后的二值化图像
    """
    # 1. 高斯平滑
    smoothed_image = cv2.GaussianBlur(image, (5, 5), sigma)

    # 2. 计算梯度
    G_x = cv2.Sobel(smoothed_image, cv2.CV_64F, 1, 0, ksize=3)
    G_y = cv2.Sobel(smoothed_image, cv2.CV_64F, 0, 1, ksize=3)

    # 3. 计算梯度强度和方向
    magnitude = np.sqrt(G_x**2 + G_y**2)
    angle = np.arctan2(G_y, G_x) * (180 / np.pi)
    angle[angle < 0] += 180  # 调整角度范围从0到180度

    # 4. 非极大值抑制
    nms_image = np.zeros_like(smoothed_image)
    for i in range(1, magnitude.shape[0] - 1):
        for j in range(1, magnitude.shape[1] - 1):
            if (0 <= angle[i, j] < 22.5 or 157.5 <= angle[i, j] <= 180) or (22.5 <= angle[i, j] < 67.5):
                if magnitude[i, j] >= max(magnitude[i, j-1], magnitude[i, j+1]):
                    nms_image[i, j] = magnitude[i, j]
            elif (67.5 <= angle[i, j] < 112.5):
                if magnitude[i, j] >= max(magnitude[i-1, j-1], magnitude[i+1, j+1]):
                    nms_image[i, j] = magnitude[i, j]
            elif (112.5 <= angle[i, j] < 157.5):
                if magnitude[i, j] >= max(magnitude[i-1, j], magnitude[i+1, j]):
                    nms_image[i, j] = magnitude[i, j]

    # 5. 双阈值检测和边缘跟踪
    edges = np.zeros_like(nms_image)
    strong_edge = 255
    weak_edge = 50
    strong_i, strong_j = np.where(nms_image >= high_threshold)
    weak_i, weak_j = np.where((nms_image >= low_threshold) & (nms_image < high_threshold))

    edges[strong_i, strong_j] = strong_edge
    edges[weak_i, weak_j] = weak_edge

    # 边缘跟踪
    for i in range(1, edges.shape[0] - 1):
        for j in range(1, edges.shape[1] - 1):
            if edges[i, j] == weak_edge:
                if np.any(edges[i-1:i+2, j-1:j+2] == strong_edge):
                    edges[i, j] = strong_edge
                else:
                    edges[i, j] = 0

    return edges

# 示例用法
if __name__ == "__main__":
    # 读取灰度图像
    image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
    
    # 调用Canny边缘检测算法
    edges = canny_edge_detection(image)
    
    # 显示原始图像和边缘检测后的图像
    plt.figure(figsize=(12, 6))
    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(image, cmap='gray')
    plt.axis('off')
    
    plt.subplot(1, 2, 2)
    plt.title('Canny Edges')
    plt.imshow(edges, cmap='gray')
    plt.axis('off')
    plt.show()
详细解释
  1. 读取图像并转换为灰度图像

    image = cv2.imread('example.jpg', cv2.IMREAD_GRAYSCALE)
    
  2. 高斯平滑

    smoothed_image = cv2.GaussianBlur(image, (5, 5), sigma)
    

    这里使用OpenCV的GaussianBlur函数对图像进行高斯平滑处理,以减少噪声。

  3. 计算梯度

    G_x = cv2.Sobel(smoothed_image, cv2.CV_64F, 1, 0, ksize=3)
    G_y = cv2.Sobel(smoothed_image, cv2.CV_64F, 0, 1, ksize=3)
    

    使用OpenCV的Sobel函数计算平滑后的图像在水平和垂直方向的梯度。

  4. 计算梯度强度和方向

    magnitude = np.sqrt(G_x**2 + G_y**2)
    angle = np.arctan2(G_y, G_x) * (180 / np.pi)
    angle[angle < 0] += 180
    

    计算梯度强度和方向,注意调整方向角度范围从0到180度。

  5. 非极大值抑制

    for i in range(1, magnitude.shape[0] -
    
    

1):
for j in range(1, magnitude.shape[1] - 1):
if (0 <= angle[i, j] < 22.5 or 157.5 <= angle[i, j] <= 180) or (22.5 <= angle[i, j] < 67.5):
if magnitude[i, j] >= max(magnitude[i, j-1], magnitude[i, j+1]):
nms_image[i, j] = magnitude[i, j]
elif (67.5 <= angle[i, j] < 112.5):
if magnitude[i, j] >= max(magnitude[i-1, j-1], magnitude[i+1, j+1]):
nms_image[i, j] = magnitude[i, j]
elif (112.5 <= angle[i, j] < 157.5):
if magnitude[i, j] >= max(magnitude[i-1, j], magnitude[i+1, j]):
nms_image[i, j] = magnitude[i, j]
```
在梯度方向上执行非极大值抑制,以保留局部梯度最大值,细化边缘。

  1. 双阈值检测和边缘跟踪

    edges = np.zeros_like(nms_image)
    strong_edge = 255
    weak_edge = 50
    strong_i, strong_j = np.where(nms_image >= high_threshold)
    weak_i, weak_j = np.where((nms_image >= low_threshold) & (nms_image < high_threshold))
    
    edges[strong_i, strong_j] = strong_edge
    edges[weak_i, weak_j] = weak_edge
    
    # 边缘跟踪
    for i in range(1, edges.shape[0] - 1):
        for j in range(1, edges.shape[1] - 1):
            if edges[i, j] == weak_edge:
                if np.any(edges[i-1:i+2, j-1:j+2] == strong_edge):
                    edges[i, j] = strong_edge
                else:
                    edges[i, j] = 0
    

    根据设定的高低阈值,将像素分类为强边缘、弱边缘和非边缘,并通过边缘跟踪将弱边缘连接成完整的边缘。

  2. 显示和保存边缘检测后的图像

    plt.subplot(1, 2, 1)
    plt.title('Original Image')
    plt.imshow(image, cmap='gray')
    plt.axis('off')
    
    plt.subplot(1, 2, 2)
    plt.title('Canny Edges')
    plt.imshow(edges, cmap='gray')
    plt.axis('off')
    plt.show()
    

    使用Matplotlib库显示原始图像和Canny边缘检测后的图像。

优缺点

优点

  • 准确性高:能够检测出细节丰富的边缘。
  • 抗噪声能力强:通过高斯平滑和非极大值抑制,有效抑制噪声。
  • 参数少:只需设置两个阈值参数。

缺点

  • 计算复杂度高:包括高斯滤波和梯度计算等多个步骤,对计算资源要求较高。
  • 对图像质量敏感:图像质量对结果影响较大,需要进行适当的预处理。

Canny边缘检测器因其高精度和可控性而被广泛应用于计算机视觉和图像处理领域,特别适用于需要精确边缘检测的应用场景。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

闲人编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值