”工欲善其事,必先利其器。“—孔子《论语.录灵公》
首页 > 编程 > 在 Python 中使用标准化剪切 (NCut) 进行无监督图像分割的指南

在 Python 中使用标准化剪切 (NCut) 进行无监督图像分割的指南

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

A Guide to Unsupervised Image Segmentation using Normalized Cuts (NCut) in Python

介绍

图像分割在理解和分析视觉数据方面起着至关重要的作用,而归一化剪切(NCut)是一种广泛使用的基于图的分割方法。在本文中,我们将探索如何使用 Microsoft Research 的数据集在 Python 中应用 NCut 进行无监督图像分割,重点是使用超像素提高分割质量。
数据集概述
用于此任务的数据集可以从以下链接下载:MSRC 对象类别图像数据库。该数据集包含原始图像及其语义分割为九个对象类(由以“_GT”结尾的图像文件表示)。这些图像被分组为主题子集,其中文件名中的第一个数字指的是类别子集。该数据集非常适合试验分割任务。

问题陈述

我们使用 NCut 算法对数据集中的图像进行图像分割。像素级分割的计算成本很高,而且通常存在噪声。为了克服这个问题,我们使用 SLIC(简单线性迭代聚类)来生成超像素,它将相似的像素分组并减少问题的大小。为了评估分割的准确性,可以使用不同的指标(例如,并集交集、SSIM、兰德指数)。

执行

1。安装所需的库
我们使用 skimage 进行图像处理,使用 numpy 进行数值计算,使用 matplotlib 进行可视化。

pip install numpy matplotlib
pip install scikit-image==0.24.0
**2. Load and Preprocess the Dataset**

下载并提取数据集后,加载图像并进行地面实况分割:

wget http://download.microsoft.com/download/A/1/1/A116CD80-5B79-407E-B5CE-3D5C6ED8B0D5/msrc_objcategimagedatabase_v1.zip -O msrc_objcategimagedatabase_v1.zip
unzip msrc_objcategimagedatabase_v1.zip
rm msrc_objcategimagedatabase_v1.zip

现在我们准备开始编码了。

from skimage import io, segmentation, color, measure
from skimage import graph
import numpy as np
import matplotlib.pyplot as plt

# Load the image and its ground truth
image = io.imread('/content/MSRC_ObjCategImageDatabase_v1/1_16_s.bmp')
ground_truth = io.imread('/content/MSRC_ObjCategImageDatabase_v1/1_16_s_GT.bmp')

# show images side by side
fig, ax = plt.subplots(1, 2, figsize=(10, 5))
ax[0].imshow(image)
ax[0].set_title('Image')
ax[1].imshow(ground_truth)
ax[1].set_title('Ground Truth')
plt.show()

3.使用 SLIC 生成超像素并创建区域邻接图

我们在应用 NCut 之前使用 SLIC 算法来计算超像素。使用生成的超像素,我们基于平均颜色相似度构建区域邻接图(RAG):

from skimage.util import img_as_ubyte, img_as_float, img_as_uint, img_as_float64

compactness=30 
n_segments=100 
labels = segmentation.slic(image, compactness=compactness, n_segments=n_segments, enforce_connectivity=True)
image_with_boundaries = segmentation.mark_boundaries(image, labels, color=(0, 0, 0))
image_with_boundaries = img_as_ubyte(image_with_boundaries)
pixel_labels = color.label2rgb(labels, image_with_boundaries, kind='avg', bg_label=0

紧凑性控制形成超像素时像素的颜色相似度和空间接近度之间的平衡。它决定了对保持超像素紧凑(在空间方面更接近)与确保它们按颜色更均匀分组的重视程度。
较高的值:较高的紧凑度值会导致算法优先创建空间紧凑且大小均匀的超像素,而较少关注颜色相似性。这可能会导致超像素对边缘或颜色渐变不太敏感。
较低的值:较低的紧凑度值允许超像素在空间尺寸上变化更大,以便更准确地考虑颜色差异。这通常会导致超像素更紧密地遵循图像中对象的边界。

n_segments 控制 SLIC 算法尝试在图像中生成的超像素(或段)的数量。本质上,它设置了分割的分辨率。
较高的值:较高的 n_segments 值会创建更多的超像素,这意味着每个超像素会更小,分割会更细粒度。当图像具有复杂纹理或小对象时,这非常有用。
较低的值:较低的 n_segments 值会产生更少、更大的超像素。当您想要对图像进行粗分割,将较大的区域分组为单个超像素时,这非常有用。

4。应用标准化剪切 (NCut) 并可视化结果

# using the labels found with the superpixeled image
# compute the Region Adjacency Graph using mean colors
g = graph.rag_mean_color(image, labels, mode='similarity')

# perform Normalized Graph cut on the Region Adjacency Graph
labels2 = graph.cut_normalized(labels, g)
segmented_image = color.label2rgb(labels2, image, kind='avg')
f, axarr = plt.subplots(nrows=1, ncols=4, figsize=(25, 20))

axarr[0].imshow(image)
axarr[0].set_title("Original")

#plot boundaries
axarr[1].imshow(image_with_boundaries)
axarr[1].set_title("Superpixels Boundaries")

#plot labels
axarr[2].imshow(pixel_labels)
axarr[2].set_title('Superpixel Labels')

#compute segmentation
axarr[3].imshow(segmented_image)
axarr[3].set_title('Segmented image (normalized cut)')

5。评估指标
无监督分割的关键挑战是 NCut 不知道图像中类别的确切数量。 NCut 找到的分段数量可能超过实际的地面实况区域数量。因此,我们需要强大的指标来评估细分质量。

并集交集 (IoU) 是一种广泛使用的评估分割任务的指标,特别是在计算机视觉领域。它测量预测分割区域和地面真实区域之间的重叠。具体来说,IoU 计算预测分割和真实数据之间的重叠面积与其并集面积的比率。

结构相似性指数 (SSIM) 是一种用于通过比较两个图像的亮度、对比度和结构来评估图像感知质量的指标。

要应用这些指标,我们需要预测和地面实况图像具有相同的标签。为了计算标签,我们在地面上计算一个掩模,并在预测时为图像上找到的每种颜色分配一个 ID
然而,使用 NCut 进行分割可能会发现比地面实况更多的区域,这会降低准确性。

def compute_mask(image):
  color_dict = {}

  # Get the shape of the image
  height,width,_ = image.shape

  # Create an empty array for labels
  labels = np.zeros((height,width),dtype=int)
  id=0
  # Loop over each pixel
  for i in range(height):
      for j in range(width):
          # Get the color of the pixel
          color = tuple(image[i,j])
          # Check if it is in the dictionary
          if color in color_dict:
              # Assign the label from the dictionary
              labels[i,j] = color_dict[color]
          else:
              color_dict[color]=id
              labels[i,j] = id
              id =1

  return(labels)
def show_img(prediction, groundtruth):
  f, axarr = plt.subplots(nrows=1, ncols=2, figsize=(15, 10))

  axarr[0].imshow(groundtruth)
  axarr[0].set_title("groundtruth")
  axarr[1].imshow(prediction)
  axarr[1].set_title(f"prediction")
prediction_mask = compute_mask(segmented_image)
groundtruth_mask = compute_mask(ground_truth)

#usign the original image as baseline to convert from labels to color
prediction_img = color.label2rgb(prediction_mask, image, kind='avg', bg_label=0)
groundtruth_img = color.label2rgb(groundtruth_mask, image, kind='avg', bg_label=0)

show_img(prediction_img, groundtruth_img)

现在我们计算准确度分数

from sklearn.metrics import jaccard_score
from skimage.metrics import structural_similarity as ssim

ssim_score = ssim(prediction_img, groundtruth_img, channel_axis=2)
print(f"SSIM SCORE: {ssim_score}")

jac = jaccard_score(y_true=np.asarray(groundtruth_mask).flatten(),
                        y_pred=np.asarray(prediction_mask).flatten(),
                        average = None)

# compute mean IoU score across all classes
mean_iou = np.mean(jac)
print(f"Mean IoU: {mean_iou}")

结论

标准化剪切是一种强大的无监督图像分割方法,但它也面临着过度分割和调整参数等挑战。通过合并超像素并使用适当的指标评估性能,NCut 可以有效地分割复杂图像。 IoU 和 Rand 指数指标为分割质量提供了有意义的见解,尽管需要进一步细化才能有效处理多类场景。
最后,我的笔记本中提供了一个完整的示例。

版本声明 本文转载于:https://dev.to/sopralapanca/a-guide-to-unsupervised-image-segmentation-using-normalized-cuts-ncut-in-python-13pk?1如有侵犯,请联系[email protected]删除
最新教程 更多>
  • \“(1)vs.(;;):编译器优化是否消除了性能差异?\”
    \“(1)vs.(;;):编译器优化是否消除了性能差异?\”
    答案: 在大多数现代编译器中,while(1)和(1)和(;;)之间没有性能差异。编译器: perl: 1 输入 - > 2 2 NextState(Main 2 -E:1)V-> 3 9 Leaveloop VK/2-> A 3 toterloop(next-> 8 last-> 9 ...
    编程 发布于2025-03-17
  • PHP阵列键值异常:了解07和08的好奇情况
    PHP阵列键值异常:了解07和08的好奇情况
    PHP数组键值问题,使用07&08 在给定数月的数组中,键值07和08呈现令人困惑的行为时,就会出现一个不寻常的问题。运行print_r($月)返回意外结果:键“ 07”丢失,而键“ 08”分配给了9月的值。此问题源于PHP对领先零的解释。当一个数字带有0(例如07或08)的前缀时,PHP将其...
    编程 发布于2025-03-17
  • 对象拟合:IE和Edge中的封面失败,如何修复?
    对象拟合:IE和Edge中的封面失败,如何修复?
    To resolve this issue, we employ a clever CSS solution that solves the problem:position: absolute;top: 50%;left: 50%;transform: translate(-50%, -50%)...
    编程 发布于2025-03-17
  • 如何从PHP中的数组中提取随机元素?
    如何从PHP中的数组中提取随机元素?
    从阵列中的随机选择,可以轻松从数组中获取随机项目。考虑以下数组:; 从此数组中检索一个随机项目,利用array_rand( array_rand()函数从数组返回一个随机键。通过将$项目数组索引使用此键,我们可以从数组中访问一个随机元素。这种方法为选择随机项目提供了一种直接且可靠的方法。
    编程 发布于2025-03-17
  • 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-03-17
  • 为什么我会收到MySQL错误#1089:错误的前缀密钥?
    为什么我会收到MySQL错误#1089:错误的前缀密钥?
    mySQL错误#1089:错误的前缀键错误descript [#1089-不正确的前缀键在尝试在表中创建一个prefix键时会出现。前缀键旨在索引字符串列的特定前缀长度长度,可以更快地搜索这些前缀。了解prefix keys `这将在整个Movie_ID列上创建标准主键。主密钥对于唯一识别...
    编程 发布于2025-03-17
  • Java是否允许多种返回类型:仔细研究通用方法?
    Java是否允许多种返回类型:仔细研究通用方法?
    在Java中的多个返回类型:一种误解类型:在Java编程中揭示,在Java编程中,Peculiar方法签名可能会出现,可能会出现,使开发人员陷入困境,使开发人员陷入困境。 getResult(string s); ,其中foo是自定义类。该方法声明似乎拥有两种返回类型:列表和E。但这确实是如此吗...
    编程 发布于2025-03-17
  • 如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    如何为PostgreSQL中的每个唯一标识符有效地检索最后一行?
    postgresql:为每个唯一标识符提取最后一行,在Postgresql中,您可能需要遇到与在数据库中的每个不同标识相关的信息中提取信息的情况。考虑以下数据:[ 1 2014-02-01 kjkj 在数据集中的每个唯一ID中检索最后一行的信息,您可以在操作员上使用Postgres的有效效率: ...
    编程 发布于2025-03-17
  • 如何使用不同数量列的联合数据库表?
    如何使用不同数量列的联合数据库表?
    合并列数不同的表 当尝试合并列数不同的数据库表时,可能会遇到挑战。一种直接的方法是在列数较少的表中,为缺失的列追加空值。 例如,考虑两个表,表 A 和表 B,其中表 A 的列数多于表 B。为了合并这些表,同时处理表 B 中缺失的列,请按照以下步骤操作: 确定表 B 中缺失的列,并将它们添加到表的末...
    编程 发布于2025-03-17
  • 为什么不使用CSS`content'属性显示图像?
    为什么不使用CSS`content'属性显示图像?
    在Firefox extemers属性为某些图像很大,&& && && &&华倍华倍[华氏华倍华氏度]很少见,却是某些浏览属性很少,尤其是特定于Firefox的某些浏览器未能在使用内容属性引用时未能显示图像的情况。这可以在提供的CSS类中看到:。googlepic { 内容:url(&#...
    编程 发布于2025-03-17
  • 如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    如何从Python中的字符串中删除表情符号:固定常见错误的初学者指南?
    从python import codecs import codecs import codecs 导入 text = codecs.decode('这狗\ u0001f602'.encode('utf-8'),'utf-8') 印刷(文字)#带有...
    编程 发布于2025-03-17
  • 在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    在Java中使用for-to-loop和迭代器进行收集遍历之间是否存在性能差异?
    For Each Loop vs. Iterator: Efficiency in Collection TraversalIntroductionWhen traversing a collection in Java, the choice arises between using a for-...
    编程 发布于2025-03-17
  • 如何使用PHP从XML文件中有效地检索属性值?
    如何使用PHP从XML文件中有效地检索属性值?
    从php $xml = simplexml_load_file($file); foreach ($xml->Var[0]->attributes() as $attributeName => $attributeValue) { echo $attributeName,...
    编程 发布于2025-03-17
  • Python读取CSV文件UnicodeDecodeError终极解决方法
    Python读取CSV文件UnicodeDecodeError终极解决方法
    在试图使用已内置的CSV模块读取Python中时,CSV文件中的Unicode Decode Decode Decode Decode decode Error读取,您可能会遇到错误的错误:无法解码字节 在位置2-3中:截断\ uxxxxxxxx逃脱当CSV文件包含特殊字符或Unicode的路径逃...
    编程 发布于2025-03-17
  • 如何干净地删除匿名JavaScript事件处理程序?
    如何干净地删除匿名JavaScript事件处理程序?
    删除匿名事件侦听器将匿名事件侦听器添加到元素中会提供灵活性和简单性,但是当要删除它们时,可以构成挑战,而无需替换元素本身就可以替换一个问题。 element? element.addeventlistener(event,function(){/在这里工作/},false); 要解决此问题,请考虑...
    编程 发布于2025-03-17

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

Copyright© 2022 湘ICP备2022001581号-3