”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 掌握图像分割:传统技术如何在数字时代仍然大放异彩

掌握图像分割:传统技术如何在数字时代仍然大放异彩

发布于2024-11-08
浏览:511

介绍

图像分割是计算机视觉中最基本的过程之一,它允许系统分解和分析图像内的各个区域。无论您是在处理对象识别、医学成像还是自动驾驶,分割都可以将图像分解为有意义的部分。

尽管深度学习模型在这项任务中越来越受欢迎,但数字图像处理中的传统技术仍然强大且实用。本文回顾的方法包括阈值处理、边缘检测、基于区域和通过实施公认的细胞图像分析数据集(MIVIA HEp-2 图像数据集)进行聚类。

MIVIA HEp-2 图像数据集

MIVIA HEp-2 图像数据集是一组细胞图片,用于分析 HEp-2 细胞中的抗核抗体 (ANA) 模式。它由通过荧光显微镜拍摄的二维图片组成。这使得它非常适合分割任务,最重要的是那些与医学图像分析有关的任务,其中细胞区域检测是最重要的。

现在,让我们继续讨论用于处理这些图像的分割技术,根据 F1 分数比较它们的性能。


1. 阈值分割

阈值处理是根据像素强度将灰度图像转换为二值图像的过程。在 MIVIA HEp-2 数据集中,此过程对于从背景中提取细胞非常有用。它在很大程度上是简单有效的,特别是使用大津方法,因为它会自动计算最佳阈值。

Otsu 的方法 是一种自动阈值方法,它试图找到最佳阈值以产生最小的类内方差,从而分离两个类:前景(细胞)和背景。该方法检查图像直方图并计算完美阈值,其中每个类别中的像素强度方差的总和最小化。

# Thresholding Segmentation
def thresholding(img):
    # Convert image to grayscale
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # Apply Otsu's thresholding
    _, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY   cv.THRESH_OTSU)

    return thresh

Mastering Image Segmentation: How Traditional Techniques Still Shine in the Digital Age


2. 边缘检测分割

边缘检测涉及识别对象或区域的边界,例如 MIVIA HEp-2 数据集中的细胞边缘。在用于检测突然强度变化的许多可用方法中,Canny 边缘检测器 是最好的,因此也是最适合用于检测细胞边界的方法。

Canny 边缘检测器 是一种多阶段算法,可以通过检测强度梯度较强的区域来检测边缘。该过程包括使用高斯滤波器进行平滑、计算强度梯度、应用非极大值抑制来消除寄生响应,以及最终的双阈值操作以仅保留显着边缘。

# Edge Detection Segmentation
def edge_detection(img):
    # Convert image to grayscale
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # Apply Gaussian blur
    gray = cv.GaussianBlur(gray, (3, 3), 0)

    # Calculate lower and upper thresholds for Canny edge detection
    sigma = 0.33
    v = np.median(gray)
    lower = int(max(0, (1.0 - sigma) * v))
    upper = int(min(255, (1.0   sigma) * v))

    # Apply Canny edge detection
    edges = cv.Canny(gray, lower, upper)

    # Dilate the edges to fill gaps
    kernel = np.ones((5, 5), np.uint8)
    dilated_edges = cv.dilate(edges, kernel, iterations=2)

    # Clean the edges using morphological opening
    cleaned_edges = cv.morphologyEx(dilated_edges, cv.MORPH_OPEN, kernel, iterations=1)

    # Find connected components and filter out small components
    num_labels, labels, stats, _ = cv.connectedComponentsWithStats(
        cleaned_edges, connectivity=8
    )
    min_size = 500
    filtered_mask = np.zeros_like(cleaned_edges)
    for i in range(1, num_labels):
        if stats[i, cv.CC_STAT_AREA] >= min_size:
            filtered_mask[labels == i] = 255

    # Find contours of the filtered mask
    contours, _ = cv.findContours(
        filtered_mask, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE
    )

    # Create a filled mask using the contours
    filled_mask = np.zeros_like(gray)
    cv.drawContours(filled_mask, contours, -1, (255), thickness=cv.FILLED)

    # Perform morphological closing to fill holes
    final_filled_image = cv.morphologyEx(
        filled_mask, cv.MORPH_CLOSE, kernel, iterations=2
    )

    # Dilate the final filled image to smooth the edges
    final_filled_image = cv.dilate(final_filled_image, kernel, iterations=1)

    return final_filled_image

Mastering Image Segmentation: How Traditional Techniques Still Shine in the Digital Age


3. 基于区域的分割

基于区域的分割根据某些标准(例如强度或颜色)将相似的像素分组到区域中。 分水岭分割技术可用于帮助分割 HEp-2 细胞图像,以便能够检测代表细胞的那些区域;它将像素强度视为地形表面并勾勒出区分区域的轮廓。

分水岭分割将像素的强度视为地形表面。该算法识别“盆地”,在其中识别局部最小值,然后逐渐淹没这些盆地以扩大不同的区域。当人们想要分离触摸物体时(例如显微图像中的细胞),这种技术非常有用,但它可能对噪声敏感。该过程可以通过标记来指导,并且通常可以减少过度分割。

# Region-Based Segmentation
def region_based(img):
    # Convert image to grayscale
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # Apply Otsu's thresholding
    _, thresh = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV   cv.THRESH_OTSU)

    # Apply morphological opening to remove noise
    kernel = np.ones((3, 3), np.uint8)
    opening = cv.morphologyEx(thresh, cv.MORPH_OPEN, kernel, iterations=2)

    # Dilate the opening to get the background
    sure_bg = cv.dilate(opening, kernel, iterations=3)

    # Calculate the distance transform
    dist_transform = cv.distanceTransform(opening, cv.DIST_L2, 5)

    # Threshold the distance transform to get the foreground
    _, sure_fg = cv.threshold(dist_transform, 0.2 * dist_transform.max(), 255, 0)
    sure_fg = np.uint8(sure_fg)

    # Find the unknown region
    unknown = cv.subtract(sure_bg, sure_fg)

    # Label the markers for watershed algorithm
    _, markers = cv.connectedComponents(sure_fg)
    markers = markers   1
    markers[unknown == 255] = 0

    # Apply watershed algorithm
    markers = cv.watershed(img, markers)

    # Create a mask for the segmented region
    mask = np.zeros_like(gray, dtype=np.uint8)
    mask[markers == 1] = 255

    return mask

Mastering Image Segmentation: How Traditional Techniques Still Shine in the Digital Age


4. 基于聚类的分割

诸如K-Means之类的聚类技术倾向于将像素分组到相似的聚类中,当想要在多色或复杂环境中分割细胞时,这种方法效果很好,如 HEp-2 细胞图像中所示。从根本上讲,这可以代表不同的类别,例如细胞区域与背景。

K-means 是一种基于颜色或强度的像素相似性对图像进行聚类的无监督学习算法。该算法随机选择K个质心,将每个像素分配给最近的质心,并迭代更新质心直至收敛。它对于分割具有多个彼此非常不同的感兴趣区域的图像特别有效。

# Clustering Segmentation
def clustering(img):
    # Convert image to grayscale
    gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

    # Reshape the image
    Z = gray.reshape((-1, 3))
    Z = np.float32(Z)

    # Define the criteria for k-means clustering
    criteria = (cv.TERM_CRITERIA_EPS   cv.TERM_CRITERIA_MAX_ITER, 10, 1.0)

    # Set the number of clusters
    K = 2

    # Perform k-means clustering
    _, label, center = cv.kmeans(Z, K, None, criteria, 10, cv.KMEANS_RANDOM_CENTERS)

    # Convert the center values to uint8
    center = np.uint8(center)

    # Reshape the result
    res = center[label.flatten()]
    res = res.reshape((gray.shape))

    # Apply thresholding to the result
    _, res = cv.threshold(res, 0, 255, cv.THRESH_BINARY   cv.THRESH_OTSU)

    return res

Mastering Image Segmentation: How Traditional Techniques Still Shine in the Digital Age


使用 F1 分数评估技术

F1 分数 是一种将精度和召回率结合在一起的度量,用于将预测分割图像与地面真实图像进行比较。它是精度和召回率的调和平均值,在数据高度不平衡的情况下非常有用,例如在医学成像数据集中。

我们通过展平地面实况和分割图像并计算加权 F1 分数来计算每种分割方法的 F1 分数。

def calculate_f1_score(ground_image, segmented_image):
    ground_image = ground_image.flatten()
    segmented_image = segmented_image.flatten()
    return f1_score(ground_image, segmented_image, average="weighted")

然后我们使用简单的条形图可视化不同方法的 F1 分数:

Mastering Image Segmentation: How Traditional Techniques Still Shine in the Digital Age


结论

尽管最近出现了许多图像分割方法,但阈值处理、边缘检测、基于区域的方法和聚类等传统分割技术在应用于 MIVIA HEp-2 图像数据集等数据集时非常有用。

每种方法都有其优点:

  • 阈值适用于简单的二进制分割。
  • 边缘检测是边界检测的理想技术。
  • 基于区域的分割对于将连接的组件与其邻居分离非常有用。
  • 聚类方法非常适合多区域分割任务。

通过使用 F1 分数评估这些方法,我们了解了每个模型的权衡。这些方法可能不像最新的深度学习模型中开发的那么复杂,但它们仍然快速、可解释且可在广泛的应用中使用。


感谢您的阅读!我希望对传统图像分割技术的探索能够启发您的下一个项目。欢迎在下面的评论中分享您的想法和经验!

版本声明 本文转载于:https://dev.to/ahmedmbutt/mastering-image-segmentation-how-traditional-techniques-still-shine-in-the-digital-age-36fa?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • 如何有效地选择熊猫数据框中的列?
    如何有效地选择熊猫数据框中的列?
    在处理数据操作任务时,在Pandas DataFrames 中选择列时,选择特定列的必要条件是必要的。在Pandas中,选择列的各种选项。选项1:使用列名 如果已知列索引,请使用ILOC函数选择它们。请注意,python索引基于零。 df1 = df.iloc [:,0:2]#使用索引0和1 c...
    编程 发布于2025-04-04
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符在postgresql中提取最后一行,您可能需要遇到与数据集合中每个不同标识的信息相关的信息。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: id dat...
    编程 发布于2025-04-04
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,可以更快地搜索这些前缀。了解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-04-04
  • Python读取CSV文件UnicodeDecodeError终极解决方法
    Python读取CSV文件UnicodeDecodeError终极解决方法
    在试图使用已内置的CSV模块读取Python中时,CSV文件中的Unicode Decode Decode Decode Decode decode Error读取,您可能会遇到错误的错误:无法解码字节 在位置2-3中:截断\ uxxxxxxxx逃脱当CSV文件包含特殊字符或Unicode的路径逃...
    编程 发布于2025-04-04
  • 如何使用组在MySQL中旋转数据?
    如何使用组在MySQL中旋转数据?
    在关系数据库中使用mySQL组使用mySQL组进行查询结果,在关系数据库中使用MySQL组,转移数据的数据是指重新排列的行和列的重排以增强数据可视化。在这里,我们面对一个共同的挑战:使用组的组将数据从基于行的基于列的转换为基于列。 Let's consider the following ...
    编程 发布于2025-04-04
  • 如何从Google API中检索最新的jQuery库?
    如何从Google API中检索最新的jQuery库?
    从Google APIS 问题中提供的jQuery URL是版本1.2.6。对于检索最新版本,以前有一种使用特定版本编号的替代方法,它是使用以下语法:获取最新版本:未压缩)While these legacy URLs still remain in use, it is recommended ...
    编程 发布于2025-04-04
  • 如何将来自三个MySQL表的数据组合到新表中?
    如何将来自三个MySQL表的数据组合到新表中?
    mysql:从三个表和列的新表创建新表 答案:为了实现这一目标,您可以利用一个3-way Join。 选择p。*,d.content作为年龄 来自人为p的人 加入d.person_id = p.id上的d的详细信息 加入T.Id = d.detail_id的分类法 其中t.taxonomy =...
    编程 发布于2025-04-04
  • 如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    如何将多种用户类型(学生,老师和管理员)重定向到Firebase应用中的各自活动?
    Red: How to Redirect Multiple User Types to Respective ActivitiesUnderstanding the ProblemIn a Firebase-based voting app with three distinct user type...
    编程 发布于2025-04-04
  • 为什么不使用CSS`content'属性显示图像?
    为什么不使用CSS`content'属性显示图像?
    在Firefox extemers属性为某些图像很大,&& && && &&华倍华倍[华氏华倍华氏度]很少见,却是某些浏览属性很少,尤其是特定于Firefox的某些浏览器未能在使用内容属性引用时未能显示图像的情况。这可以在提供的CSS类中看到:。googlepic { 内容:url(&#...
    编程 发布于2025-04-04
  • 为什么PYTZ最初显示出意外的时区偏移?
    为什么PYTZ最初显示出意外的时区偏移?
    与pytz 最初从pytz获得特定的偏移。例如,亚洲/hong_kong最初显示一个七个小时37分钟的偏移: 差异源利用本地化将时区分配给日期,使用了适当的时区名称和偏移量。但是,直接使用DateTime构造器分配时区不允许进行正确的调整。 example pytz.timezone(...
    编程 发布于2025-04-04
  • 如何同步迭代并从PHP中的两个等级阵列打印值?
    如何同步迭代并从PHP中的两个等级阵列打印值?
    同步的迭代和打印值来自相同大小的两个数组使用两个数组相等大小的selectbox时,一个包含country代码的数组,另一个包含乡村代码,另一个包含其相应名称的数组,可能会因不当提供了exply for for for the uncore for the forsion for for ytry...
    编程 发布于2025-04-04
  • 版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    版本5.6.5之前,使用current_timestamp与时间戳列的current_timestamp与时间戳列有什么限制?
    在时间戳列上使用current_timestamp或MySQL版本中的current_timestamp或在5.6.5 此限制源于遗留实现的关注,这些限制需要对当前的_timestamp功能进行特定的实现。 创建表`foo`( `Productid` int(10)unsigned not n...
    编程 发布于2025-04-04
  • HTML格式标签
    HTML格式标签
    HTML 格式化元素 **HTML Formatting is a process of formatting text for better look and feel. HTML provides us ability to format text without us...
    编程 发布于2025-04-04
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-04-04
  • 如何使用FormData()处理多个文件上传?
    如何使用FormData()处理多个文件上传?
    )处理多个文件输入时,通常需要处理多个文件上传时,通常是必要的。 The fd.append("fileToUpload[]", files[x]); method can be used for this purpose, allowing you to send multi...
    编程 发布于2025-04-04

免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。

Copyright© 2022 湘ICP备2022001581号-3