立即注册找回密码

QQ登录

只需一步,快速开始

微信登录

微信扫一扫,快速登录

手机动态码快速登录

手机号快速注册登录

搜索

图文播报

查看: 116|回复: 3

[分享] 边缘检测能实现区域分割吗?

[复制链接]
发表于 2025-7-4 13:09 | 显示全部楼层 |阅读模式
回复

使用道具 举报

发表于 2025-7-4 13:10 | 显示全部楼层
一、多尺度边缘检测方法

多尺度边缘检测通过在不同分辨率/平滑度下分析图像,实现:

  • 粗尺度(大σ值):抑制噪声,提取主体轮廓
  • 细尺度(小σ值):保留细节,检测微观缺陷
  • 尺度融合:综合各层级特征形成完整边缘描述
1.1 数学表达(高斯尺度空间)

图像在尺度)下的表示为:

其中高斯核
<hr/>1.2 典型案例

高斯金字塔多尺度Canny

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


def multi_scale_canny(img, scales=[1.0, 2.0, 4.0]):
    # 初始化结果矩阵
    edges_stack = np.zeros_like(img, dtype=np.uint8)

    for sigma in scales:
        # 高斯模糊
        blurred = cv2.GaussianBlur(img, (0, 0), sigmaX=sigma)
        # 动态阈值Canny(阈值随尺度调整)
        low_thresh = int(30 * (sigma / 2.0))
        high_thresh = int(90 * (sigma / 2.0))
        edges = cv2.Canny(blurred, low_thresh, high_thresh)
        # 多尺度叠加
        edges_stack = cv2.bitwise_or(edges_stack, edges)

    return edges_stack

img = cv2.imread("../sports.jpg", 0)
result = multi_scale_canny(img, scales=[1.0, 2.0, 4.0])

plt.figure(figsize=(15, 5))
plt.subplot(121), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.subplot(122), plt.imshow(result, cmap='gray'), plt.title('multi_scale_canny')
plt.show()




高斯金字塔多尺度

Laplacian of Gaussian(LoG)算子

Laplacian of Gaussian(LoG)是一种基于二阶导数的边缘检测方法,通过结合高斯平滑与拉普拉斯算子实现多尺度边缘检测,其核心优势在于:

  • 噪声免疫:高斯滤波先消除高频噪声,再进行边缘定位
  • 零交叉特性:通过检测二阶导数过零点(Zero-Crossing)精确定位边缘中心
  • 多尺度适应:调节高斯核σ值可控制边缘检测的粗细程度
数学表达式:

实际应用中常使用离散近似核(如9×9核,σ=1.4)
代码例子
import cv2
import numpy as np
import matplotlib.pyplot as plt

# 生成测试图像
img = np.zeros((300, 300), dtype=np.uint8)
cv2.rectangle(img, (50, 50), (250, 250), 200, 20)  # 灰色矩形框
img[120:180, 140:160] = 100  # 添加垂直划痕
img = cv2.GaussianBlur(img, (5, 5), 0.5)  # 模拟表面模糊

# LoG计算
gaussian = cv2.GaussianBlur(img, (9, 9), sigmaX=1.4)
laplacian = cv2.Laplacian(gaussian, cv2.CV_64F, ksize=3)

# 过零检测
log_edges = np.zeros_like(img, dtype=np.uint8)
h, w = laplacian.shape
for i in range(1, h - 1):
    for j in range(1, w - 1):
        # 检测相邻像素符号变化
        if (laplacian[i, j] * laplacian[i + 1, j] < 0) or \
                (laplacian[i, j] * laplacian[i, j + 1] < 0):
            log_edges[i, j] = 255

# 可视化
plt.figure(figsize=(15, 5))
plt.subplot(131), plt.imshow(img, cmap='gray'), plt.title('Original')
plt.subplot(132), plt.imshow(laplacian, cmap='jet'), plt.title('LoG Response')
plt.subplot(133), plt.imshow(log_edges, cmap='gray'), plt.title('Zero-Crossing Edges')
plt.show()




LoG

小波多分辨率检测

使用OpenCV的高斯金字塔模拟小波多尺度分解,通过残差计算提取高频信息,实现多分辨率边缘检测。
import cv2
import numpy as np

def opencv_wavelet_edge(img, levels=3):
    # 初始化高斯金字塔
    pyramid = [img.astype(np.float32)]
   
    # 构建高斯金字塔
    for _ in range(levels):
        layer = cv2.pyrDown(pyramid[-1])
        pyramid.append(layer)
   
    # 各尺度边缘检测
    edges = []
    for i in range(1, levels+1):
        # 上采样重建低频图像
        upsampled = cv2.pyrUp(pyramid, dstsize=pyramid[i-1].shape[::-1])
        
        # 计算高频残差(近似小波高频子带)
        residual = cv2.subtract(pyramid[i-1], upsampled)
        residual = cv2.normalize(residual, None, 0, 255, cv2.NORM_MINMAX)
        
        # 动态阈值Canny(基于尺度调整)
        thresh_low = 30 + 20*(i-1)
        thresh_high = 90 + 20*(i-1)
        edge_layer = cv2.Canny(np.uint8(residual), thresh_low, thresh_high)
        
        # 尺寸对齐(避免层级尺寸不匹配)
        if edge_layer.shape != img.shape:
            edge_layer = cv2.resize(edge_layer, img.shape[::-1])
        
        edges.append(edge_layer)
   
    # 多尺度融合(加权叠加)
    final = cv2.addWeighted(edges[0], 0.5, edges[1], 0.3, 0)
    if levels > 2:
        final = cv2.addWeighted(final, 0.7, edges[2], 0.2, 0)
    return final

# 使用示例
img = cv2.imread("sports.jpg", 0)
result = opencv_wavelet_edge(img, levels=3)



小波检测

二、形态学方法

1.1 核心原理与基础操作

形态学方法基于集合论结构元素对图像进行形状分析,主要操作包括:
操作类型数学定义视觉效果工业应用场景
腐蚀A \ominus B \\收缩物体,消除细小噪声去除塑料表面微小噪点
膨胀A \oplus B \\扩张物体,填充孔洞连接断裂的注塑件边缘
开运算(A \ominus B) \oplus B \\平滑轮廓,保持主体形状毛刺去除
闭运算(A \oplus B) \ominus B \\闭合小孔,连接邻近区域气泡缺陷修复
<hr/>2.1 基础形态学操作

import cv2
import numpy as np

def morphology_optimization(edges):
    # 定义结构元素(十字形消除毛刺,椭圆形填充孔洞)
    kernel_cross = cv2.getStructuringElement(cv2.MORPH_CROSS, (3,3))
    kernel_ellipse = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (5,5))

    # 去噪:开运算消除孤立噪点
    cleaned = cv2.morphologyEx(edges, cv2.MORPH_OPEN, kernel_cross)
   
    # 连接:闭运算修复断裂边缘
    connected = cv2.morphologyEx(cleaned, cv2.MORPH_CLOSE, kernel_ellipse)
   
    # 细化处理(可选)
    thin = cv2.ximgproc.thinning(connected)
    return thin

canny_edges = cv2.Canny(img, 50, 150)  # 初始Canny边缘
kernel = np.ones((3, 3), np.uint8)
edges = cv2.dilate(canny_edges, kernel, iterations=1)
optimized_edges = morphology_optimization(canny_edges)



形态学操作
回复 支持 反对

使用道具 举报

发表于 2025-7-4 13:11 | 显示全部楼层
边缘可以作为辅助信息来提升区域分割的精度,可以参考 segfix和 Gated-SCNN两篇论文
回复 支持 反对

使用道具 举报

发表于 2025-7-4 13:11 | 显示全部楼层
可以,但是大部分情况下比较麻烦。
麻烦来自于边缘检测算法本身。一般的边缘检测算法,不管是用简单的sobel,还是复杂的canny edge,会将所有“疑似”的边缘都输出来。之所以是“疑似”,是因为这些“传统”的边缘检测算法只考虑了计算效率,而没有考虑哪些边缘是我们真正需要的边缘。因此,仅管可以设置各种阈值将一些细小的、不重要的边缘都滤掉,仍然会有不是我们想要的边缘被留下。如果调大阈值,则可能将我们需要的边缘也滤掉了。
如此一来,使用边缘做分割就变得非常麻烦。当存在大量不需的边缘时,分割的粒度就会变大,我们需要分成一个整体的object,可能被分成很多小份,那么就要考滤怎么把这些小份整合起来。如果将细小边缘都滤掉了,则可能缺少真正有用的边缘,此时分割的粒度过大,并没有将object与背景分割开。
另外,即使有更好的边缘检测算法,输出的都是我们想要的边缘,你仍然需要做边缘封闭检测,这也是很麻烦的。
回复 支持 反对

使用道具 举报

发表回复

您需要登录后才可以回帖 登录 | 立即注册 微信登录 手机动态码快速登录

本版积分规则

关闭

官方推荐 上一条 /3 下一条

快速回复 返回列表 客服中心 搜索 官方QQ群 洽谈合作
快速回复返回顶部 返回列表