图像分割-传统算法-边缘分割

基于边缘检测的图像分割流程

1、灰度图转变

2、使用边缘检测算子进行边缘提取,如canny、sobel、拉普拉斯算子

3、对边缘进行闭合处理

4、显示闭合后的轮廓

试了下canny、sobel、拉普拉斯,其中拉普拉斯算子可以事先对灰度图平滑处理一下(拉普拉斯对噪声敏感)。

python 复制代码
import cv2
import numpy as np

def edge_detection_canny(img_path, thres=(50,150), ksize=5):
    '''
    :param img_path:
    :param thres: canny算子的限制阈值,[0]为低阈值,[1]为高阈值
    :param ksize: canny的核大小
    :return:
    '''
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    edges = cv2.Canny(gray, thres[0], thres[1])

    #  形态学闭运算:连接断裂的边缘, cv2.MORPH_RECT结果元素矩形, cv2.MORPH_ELLIPSE椭圆形, CROSS十字形
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (ksize, ksize))
    # kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (ksize, ksize))
    # kernel = cv2.getStructuringElement(cv2.MORPH_CROSS, (ksize, ksize))
    #  闭运算:先膨胀后腐蚀,用于填充边缘间的细小间隙,连接相邻的边缘片段
    closed = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)

    # 查找轮廓
    # 在闭运算后的边缘图像中查找物体的轮廓
    # RETR_EXTERNAL: 只检索最外层轮廓(忽略内部孔洞的轮廓),RETR_LIST检索所有轮廓不建立层级,RETR_CCOMP检索所有轮廓组织为两级层级;检索所有轮廓,重建完整的嵌套层级
    # CHAIN_APPROX_SIMPLE: 压缩水平、垂直和对角线段,只保留端点;CHAIN_APPROX_NONE:存储所有轮廓
    contours, _ = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 在原图上绘制轮廓
    cv2.drawContours(img, contours, -1, (0, 255, 0), 2)

    cv2.imshow('edge', edges)
    cv2.imshow('closed', closed)
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def edge_detection_sobel(img_path, ksize=3):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    sobel_x = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=ksize)
    sobel_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=ksize)
    sobel_magnitude = np.sqrt(sobel_x ** 2 + sobel_y ** 2)

    # 转换为8位无符号整数并归一化到0-255
    sobel_edges = np.uint8(np.clip(sobel_magnitude, 0, 255))

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    closed = cv2.morphologyEx(sobel_edges, cv2.MORPH_CLOSE, kernel)

    contours, _ = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    cv2.drawContours(img, contours, -1, (0, 255, 0), 2)

    cv2.imshow('edge', sobel_edges)
    cv2.imshow('closed', closed)
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()

def edge_detection_lap(img_path, ksize=3):
    img = cv2.imread(img_path)
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    blurred = cv2.GaussianBlur(gray, (5, 5), 0)
    edges = cv2.Laplacian(blurred, cv2.CV_64F, ksize=ksize)

    laplacian_abs = np.absolute(edges)
    laplacian_edges = np.uint8(np.clip(laplacian_abs, 0, 255))

    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
    closed = cv2.morphologyEx(laplacian_edges, cv2.MORPH_CLOSE, kernel)

    contours, _ = cv2.findContours(closed.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    cv2.drawContours(img, contours, -1, (0, 255, 0), 2)

    cv2.imshow('edge', laplacian_edges)
    cv2.imshow('closed', closed)
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()


if __name__ == '__main__':
    img_path = './test/test_img.jpg'
    edge_detection_canny(img_path)
    # edge_detection_sobel(img_path)
    # edge_detection_lap(img_path)

参考
理论学习1
理论学习2
代码参考1

相关推荐
Gigavision13 分钟前
DEAP数据集 2026最新Transformer算法 DEAP 数据集 下载
深度学习·算法·transformer
夜之眷属35 分钟前
PriorityQueue:for-each 遍历和 poll 取出,顺序一样吗?
java·服务器·数据结构·后端·算法
地平线开发者1 小时前
不是线程越多越快:用 hrt_model_exec 在 征程6M 上给 YOLOv5x 建立性能基线
算法
姜鱼问生2 小时前
fail2ban 实战:从默认配置到生产可用
后端·算法·架构
垆边人似月.2 小时前
华为题:全排列
算法·深度优先·图论
杜 硕2 小时前
快速排序详解01
数据结构·算法·排序算法
Martina_03212 小时前
AI生成的海岸城市一移动镜头,水面反射就跳?用6步统一反射探针、SSR与平面反射
图像处理·人工智能·平面·3d·ai·自然语言处理·游戏策划
Matlab程序猿2 小时前
【MATLAB源码-第459期】基于matlab的D-H模型与阻尼最小二乘逆运动学的六自由度机械臂五次轨迹规划及动力学前馈PD控制仿真。
人工智能·算法·matlab·d-h建模·六自由度串联机械臂
信奥卷王2 小时前
[GESP202606 六级] 满二叉树
数据结构·算法
积流成海3 小时前
用代码实现哈希计算器:Web Crypto API 实战
前端·算法·哈希算法·哈希函数·盘子工具站