【CV\segmentation】基于Voronoi图的超像素分割及其在 [点标注] 弱监督学习中的应用 || 学习笔记

【start:20231118】

引言

研究动机

弱监督学习中,可以使用点标注生成 Voronoi 图和其他更丰富的注释来训练分割网络:

对于弱监督的细胞分割,Voronoi 边界(Aurenhammer,1991)在该领域发挥着至关重要的作用,因为它可以生成仅带有点注释的负标签。分割方法通常使用 Voronoi 边界和从点生成的更丰富的注释来训练分割网络,然后应用细化方法。

For weakly-supervised cell segmentation, the Voronoi boundary (Aurenhammer, 1991) plays a crucial role in this area since it can generate negative labels with only point annotations. Segmentation methods often train segmentation networks with the Voronoi boundary and richer annotations generated from points, then apply methods for refinement. For example, the method of Qu et al. (2019a) produces pseudo labels for nuclei segmentation from clustering and Voronoi diagrams by using an improved U-Net.
(这里的“伪标签”指的是“簇标签”,是由聚类方法得到的,然后,可以以点标注的 Voronoi 边界附近的簇区域作为背景、点标注结果附近的簇区域作为前景,生成更丰富的注释来训练分割网络)
·
[1] GUO R, XIE K, PAGNUCCO M, 等. SAC-Net: Learning with weak and noisy labels in histopathology image segmentation[J/OL]. Medical Image Analysis, 2023, 86: 102790[2023-11-13]. https://linkinghub.elsevier.com/retrieve/pii/S1361841523000518. DOI:10.1016/j.media.2023.102790.

简介:Voronoi 图

Voronoi 图(沃罗诺伊图,也称为Voronoi diagram、Voronoi tessellation或Voronoi partition)是一种空间分割的方法,它将空间划分为多个区域,使得每个区域内的点都离该区域内的特定点最近。

Voronoi 图是一个具有许多多边形区域的图形,每个区域都由一个种子点和到该点最近的其他种子点之间的距离确定。这种图形的美好之处在于,它根据种子点的分布自然地适应局部空间的特征

Voronoi 图在计算几何学、图形学、地理信息系统、生物学、物理学等领域都有广泛的应用。在图像处理和计算机视觉中,Voronoi 图常用于图像分割、对象识别和特征提取。

简介:超像素分割

超像素分割是一种图像处理技术,旨在将图像分割成具有语义信息的更大块的区域,这些区域被称为超像素;与传统的像素级分割相比,这种方法在一些基于区域的图像分割应用中可能是有用的,因为它可以提供更连续、紧凑的区域,有助于保留图像中的结构信息,并减少计算复杂性。

在某些情况下,Voronoi图可以用于生成图像的超像素分割:通过在图像中的数据点处构建Voronoi图,可以生成一组区域,每个区域可以被视为一个超像素。

简介:点标注弱监督学习

例如,(QU H, 2019) 等人在《Weakly Supervised Deep Nuclei Segmentation using Points Annotation in Histopathology Images》中提到,可以以点标注的 Voronoi 边界附近的簇区域作为背景、点标注结果附近的簇区域作为前景,生成更丰富的注释来训练分割网络。

(QU H, 2019) 等人的模型和方法的流程图:

在这里插入图片描述

(QU H, 2019) 等人的模型所需的gt标签的展示:

在这里插入图片描述

[1] QU H, WU P, HUANG Q, 等. Weakly Supervised Deep Nuclei Segmentation using Points Annotation in Histopathology Images[J]. 2019.
·
【摘要】细胞核分割是组织病理图像分析的一项基本任务。通常,这样的分割任务需要大量的工作来手动生成像素级注释,以进行完全监督的训练。为了减少手工标注的工作量,本文提出了一种新的方法,即只使用点标注。从点标注中得到两种具有互补信息的粗标签,然后利用它们来训练深度神经网络。利用全连通条件随机场损失进一步细化模型,而不会在推理过程中引入额外的计算复杂度。在两个核分割数据集上的实验结果表明,与完全监督的核分割方法和最先进的核分割方法相比,该方法能够获得具有竞争力的性能,同时所需的注释工作量大大减少。我们的代码是公开可用的。

参考资料

【ref】【浅入浅出】教你实现最简单的Voronoi图 - Shawn的文章 - 知乎

Voronoi图-基础

Voronoi图的概念

简单来说,Voronoi 图的边界是由每对种子点之间的垂直平分线组成的;

对于每一对种子点(蓝色),Voronoi 图的边缘是垂直平分这两个点之间直线的直线(直线交汇处标记为橘色),这也意味着沿边界上的任何点到最近的两个种子点的距离相等。

在这里插入图片描述

Voronoi图的绘制

Voronoi 图(沃洛诺伊图,Voronoi diagram,又叫泰森多边形)是一种空间分割的方法,它将空间划分为多个区域,使得每个区域内的点都离该区域内的特定点最近。这个特定点被称为种子点(或生成点、控制点)。

Voronoi 图的生成过程如下:

  1. 选择种子点: 在空间中选择一组种子点,这些点是由用户定义或根据数据分布生成的。

  2. 进行区域划分: 对于每个种子点,Voronoi 图将空间划分为一个区域,该区域内的点到该种子点的距离比到其他种子点的距离更近。这样的区域被称为 Voronoi 区域。

边界: Voronoi 图的边界是相邻区域之间的分界线,通常是由于到两个种子点距离相等的点构成。

返回的结果是一个具有许多多边形区域的图形,每个区域都由一个种子点和到该点最近的其他种子点之间的距离确定。这种图形的美好之处在于,它根据种子点的分布自然地适应局部空间的特征

选择种子点(关键)

在构建Voronoi图时,种子点的选择对结果影响很大。以下是一些选择种子点的常见方式:

  1. 均匀分布: 在图像或空间中均匀分布的选择种子点。这种方法适用于希望得到相对均匀分布的Voronoi区域的情况。

  2. 随机选择: 随机选择种子点,可以通过在图像或空间中生成随机坐标来实现。这种方法适用于一些随机分布的情况,或者当你希望具有随机性的Voronoi图。

  3. 基于密度的选择: 在图像中根据某种密度分布选择种子点。这种方法可以使得Voronoi区域在密度较大的区域更加细致,而在密度较小的区域较为简单。

  4. 基于特征点的选择: 根据图像中的特征点,如角点或边缘点,选择种子点。这种方法可以保留图像中的一些重要特征。

  5. 根据感兴趣区域选择: 在特定的感兴趣区域内选择种子点,以确保Voronoi图在该区域内有更好的表现。这适用于对特定区域有更高要求的场景。

  6. 基于已知区域的选择: 如果你已经有一些先验知识,比如某些区域应该属于特定的Voronoi区域,可以在这些区域内选择种子点。

无论选择哪种方式,种子点的分布通常会影响到最终Voronoi图的形状。在实际应用中,可以根据具体问题和需求灵活选择适合的种子点选择方式。

进行区域划分

Voronoi图的区域划分方式是通过将平面分割成以种子点为中心的多边形区域来实现的。一旦选择了种子点,Voronoi图的区域划分方式如下:

  1. 根据距离确定归属: 对于平面上的每个点,确定它与所有种子点的距离,然后将该点分配给最近的种子点所在的区域。这确保了每个点都属于离它最近的种子点的Voronoi区域。

  2. 通过构建Voronoi边确定区域: 这是一种更直观的方法。通过构建Voronoi图的边,每个边定义了两个相邻的Voronoi区域。这样,平面上的点会根据它们与Voronoi边的关系被分配到相应的区域。

  3. Delaunay 三角剖分: Voronoi图与Delaunay三角剖分之间存在一一对应的关系。因此,可以先进行Delaunay三角剖分,然后通过连接三角形的外心来构建Voronoi图。Voronoi区域就是通过相邻三角形外心之间的连线所形成的。

  4. 通过拓扑关系判定: 根据Voronoi图的拓扑关系,可以判定每个点所属的Voronoi区域。这需要处理Voronoi图的数据结构,如边、顶点等。

一般来说,构建Voronoi图的库或工具会提供已经实现好的算法,无需手动实现上述步骤——例如,Python中的scipy库中有scipy.spatial.Voronoi类可以用于构建Voronoi图。使用这样的工具,只需要提供种子点的坐标,工具会自动处理区域的划分,代码如下:

import numpy as np
from scipy.spatial import Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt

# 生成一些种子点
points = np.random.rand(20, 2)

# 构建Voronoi图
vor = Voronoi(points)

# 绘制Voronoi图
voronoi_plot_2d(vor)
plt.show()

在这个例子中,points是种子点的坐标,Voronoi类会计算Voronoi图,并使用voronoi_plot_2d函数绘制出来。这样就可以直观地看到区域的划分。

在这里插入图片描述

参考资料

【paper】一种基于Voronoi划分的超像素分割方法
【author】测绘与地理科学学院 贾淑涵

针对现有技术的不足,本发明提供一种基于Voronoi划分的超像素分割方法。将 Voronoi 划分子区域视为一个超像素,使位于地物边界处的超像素其局部边缘与该目标边界吻合,生成的超像素形状相对规则。由于唯一决定Voronoi 划分的就是种子点的位置,因此可将超像素分割问题转化为种子点确定问题,即,通过不断移动种子点位置,使Voronoi 划分的每一个子区域满足超像素要求。

Voronoi图的仿真

用Unity Shader绘制Voronoi图

【ref】一篇搞定Unity Shader入门精要 (更新中)

在Unity中使用Shader绘制Voronoi图可以通过计算每个像素到种子点的距离,并根据最近的种子点确定颜色。

Voronoi图的应用

Voronoi 图在许多领域中都有广泛的应用,以下是一些常见的应用领域:

  1. 计算几何学: Voronoi 图可以用于计算几何学中的许多问题,例如最近点问题、最短路径问题和区域分割。

  2. 图像处理和计算机视觉: 在图像处理中,Voronoi 图可以用于图像分割、对象识别和特征提取。在计算机视觉中,Voronoi 图可用于检测关键点和描述图像中的对象形状。

  3. 地理信息系统(GIS): 在GIS中,Voronoi 图用于表示地理空间中不同点之间的最近邻关系,或者用于区域分割,例如栅格单元的分割。

  4. 自然资源管理: Voronoi 图可用于优化资源分配,例如农田规划、林业管理和水资源管理。

  5. 生物学: 在生物学中,Voronoi 图可以用于分析细胞分布、生态学模型以及基因表达数据的空间分布。

  6. 网络规划: Voronoi 图可用于规划无线通信网络、城市基础设施建设,以及最优路径的规划。

  7. 数学和计算科学: Voronoi 图是许多数学和计算几何算法的基础,用于解决各种问题,如 Delaunay 三角剖分、最近邻搜索等。

  8. 物理学: 在物理学中,Voronoi 图可以用于模拟晶体结构、粒子排列和相变等问题。

Voronoi图与图像分割

在图像分割中,Voronoi 图的应用通常涉及将图像分割成具有相似特征的区域。以下是一些图像分割中使用 Voronoi 图的常见应用:

  1. 图像区域分割: Voronoi 图可以将图像分割成由不同区域组成的多边形,其中每个区域包含与图像中的某个特定点最接近的像素。这种方法可以用于图像的分割和区域标记。

  2. 对象识别: 在图像中标记对象时,Voronoi 图可以用于将图像分割成以对象中心为基础的区域。这有助于提取对象的特征并进行识别。

  3. 边缘检测: 通过将图像中的点与 Voronoi 图相关联,可以实现边缘检测。边缘将出现在 Voronoi 图的边界上,这有助于将图像分割成具有明显边缘的区域。

  4. 文本检测: 在文本检测中,Voronoi 图可用于将图像分割成包含文本的区域。这对于识别文本区域和提取文本特征很有帮助。

  5. 医学图像分析: 在医学图像中,Voronoi 图可用于分割组织区域,帮助医生定位和分析特定的生物结构,如细胞、器官等。

  6. 图像修复和插值: 利用 Voronoi 图的分割性质,可以对图像中缺失或损坏的部分进行插值和修复。

  7. 形状分析: Voronoi 图可以用于分析图像中不同形状的分布和特征,帮助理解图像中的几何结构。

  8. 风格转移: 在计算机图形学中,Voronoi 图可以用于图像的风格转移,通过对图像中的特定区域进行着色和纹理转移。

Voronoi图-绘制(超像素分割)

简介

超像素分割是一种图像处理技术,旨在将图像分割成具有语义信息的更大块的区域,这些区域被称为超像素;与传统的像素级分割相比,这种方法在一些基于区域的图像分割应用中可能是有用的,因为它可以提供更连续、紧凑的区域,有助于保留图像中的结构信息,并减少计算复杂性。

在某些情况下,Voronoi图可以用于生成图像的超像素分割:通过在图像中的数据点处构建Voronoi图,可以生成一组区域,每个区域可以被视为一个超像素。

在构建Voronoi图时,种子点的选择对结果影响很大,如果已有种子点,那么直接就可以绘制Voronoi图了;但是如果没有的话,就要用特定的方法寻找——下面,我们将会以寻找种子点为主要研究难点,对不同场景下的Voronoi图的绘制方法进行介绍。

场景:直接用点标注gt绘制Voronoi图

可以直接把每个点标注视为Voronoi图的种子点

from scipy.spatial import Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt

point_annotations_gt_points = ......

# 可以直接把每个点标注视为Voronoi图的种子点
points = point_annotations_gt_points

# 构建Voronoi图
vor = Voronoi(points)

# 绘制Voronoi图
voronoi_plot_2d(vor)
plt.show()

场景:在实例分割掩码中绘制Voronoi图

直接求实例分割掩码的质心,即可作为Voronoi图的种子点

代码:由实例分割掩码生成centroids

'''
由实例分割掩码生成质心图

注意:
需要提供准确格式centroids(比如第一列是x,第二列是y),否则Voronoi的坐标轴的比例尺会错乱
'''
import numpy as np
import matplotlib.pyplot as plt
from skimage import io
from scipy.ndimage import label, center_of_mass
from scipy.spatial import Voronoi, voronoi_plot_2d

# 读取图像
image_path = '/home/linxq/code/cell_seg_workflow/src_important/preprocess/cv_preprocess/img/cell_00001_label.tiff'
image = io.imread(image_path)

# 将非零部分转为1
binary_image = np.where(image > 0, 1, 0)

# 标记连通区域
labeled_image, num_features = label(binary_image)

# 获取每个连通区域的质心坐标
centroids = [center_of_mass(binary_image, labeled_image, i) for i in range(1, num_features + 1)]

# 将质心坐标转为整数
centroids = np.array(centroids, dtype=int)

# 交换第一列和第二列
# 如果不换的话Voronoi的坐标轴的比例尺会错乱
centroids[:, [0, 1]] = centroids[:, [1, 0]]

plt.figure(figsize=(10,5))
# 显示原始图像、生成的质心二值图和Voronoi图
plt.subplot(1, 2, 1)
plt.imshow(binary_image, cmap='gray')
plt.title('Binary Image')

plt.subplot(1, 2, 2)
plt.imshow(binary_image, cmap='gray')
plt.scatter(centroids[:, 0], centroids[:, 1], c='red', marker='o', s=50)  # 绘制质心点
plt.title('Centroid Image')

在这里插入图片描述

代码:由centroids生成Voronoi图

'''
由centroids生成Voronoi图

注意:
可能需要手动调整坐标轴,改变原点位置(Voronoi默认坐标轴的原点在左下角)
'''
# 生成Voronoi图
vor = Voronoi(centroids)

# 调整坐标轴范围,将原点设置在左上角
# Voronoi默认坐标轴的原点在左下角,可能需要手动调整
plt.figure(figsize=(10,5))
voronoi_image = voronoi_plot_2d(vor, show_vertices=False, line_colors='red', line_width=2, line_alpha=0.6, point_size=10, show_points=True)
plt.title('Voronoi Diagram')
plt.xlim(0, binary_image.shape[1])  # 设置x轴范围
plt.ylim(binary_image.shape[0], 0)  # 设置y轴范围

plt.show()

在这里插入图片描述

代码:绘制叠加原图的Voronoi图(完整流程)

'''
绘制叠加原图的Voronoi图(完整流程)
'''
import numpy as np
import matplotlib.pyplot as plt
from skimage import io
from scipy.ndimage import label, center_of_mass
from scipy.spatial import Voronoi, voronoi_plot_2d

# 读取图像
image_path = '/home/linxq/code/cell_seg_workflow/src_important/preprocess/cv_preprocess/img/cell_00001_label.tiff'
image = io.imread(image_path)

# 将非零部分转为1
binary_image = np.where(image > 0, 1, 0)

# 标记连通区域
labeled_image, num_features = label(binary_image)

# 获取每个连通区域的质心坐标
centroids = [center_of_mass(binary_image, labeled_image, i) for i in range(1, num_features + 1)]

# 将质心坐标转为整数
centroids = np.array(centroids, dtype=int)

# 交换第一列和第二列
centroids[:, [0, 1]] = centroids[:, [1, 0]]

# 生成Voronoi图
vor = Voronoi(centroids)

# 创建一个新的图形
plt.figure(figsize=(10, 5))

# 显示原始图像
plt.imshow(binary_image, cmap='gray')
plt.title('Binary Image')

# 绘制Voronoi图的边界
voronoi_plot_2d(vor, show_vertices=False, line_colors='red', line_width=2, line_alpha=0.6, point_size=10, ax=plt.gca())

# 调整坐标轴范围,将原点设置在左上角
plt.xlim(0, binary_image.shape[1])  # 设置x轴范围
plt.ylim(binary_image.shape[0], 0)  # 设置y轴范围

plt.show()

在这里插入图片描述

场景:在真实图像中绘制Voronoi图

真实图像比较复杂,选择种子点的方法很多,我们就以下几种方法展开介绍:

代码:用findContours法找种子点

'''
用findContours方法,由真实图像生成Voronoi图

findContours是OpenCV中用于查找图像轮廓的函数。该函数通过在二进制图像中查找白色区域的连通分量,从而找到图像中的轮廓。

在Voronoi图的构建中,findContours可以用于找到图像中的细胞或物体的边缘轮廓,将这些轮廓点作为Voronoi图的种子点。
'''
import numpy as np
import cv2
from scipy.spatial import Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('/home/linxq/code/cell_seg_workflow/src_important/preprocess/cv_preprocess/img/wsi.png', cv2.IMREAD_GRAYSCALE)

# 二值化处理
_, thresh = cv2.threshold(image, 128, 255, cv2.THRESH_BINARY)

# 查找轮廓
contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# 提取轮廓的点集合
points = []
for contour in contours:
    points.extend(contour.reshape(-1, 2))

# 使用Voronoi图
vor = Voronoi(points)

# 绘制Voronoi图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

# 在第一个子图(ax1)中显示原图
ax1.imshow(image, cmap='gray')
ax1.set_title('Original Image')

# 在第二个子图(ax2)中显示叠加了Voronoi图的图像
voronoi_plot_2d(vor, ax=ax2)
ax2.imshow(thresh, extent=[0, image.shape[1], 0, image.shape[0]], origin='upper', cmap='gray', alpha=0.5)
ax2.set_title('Voronoi Overlay')

# 设置坐标轴
ax2.set_xlim([0, image.shape[1]])
ax2.set_ylim([image.shape[0], 0])

plt.show()

在这里插入图片描述

代码:用SIFT(尺度不变特征变换)算法找种子点

'''
用SIFT(尺度不变特征变换)算法,由真实图像生成Voronoi图

使用SIFT(尺度不变特征变换)算法检测图像的特征点或关键点作为种子点
'''
import cv2
from scipy.spatial import Voronoi, voronoi_plot_2d
import matplotlib.pyplot as plt

# 读取图像
image = cv2.imread('/home/linxq/code/cell_seg_workflow/src_important/preprocess/cv_preprocess/img/wsi.png', cv2.IMREAD_GRAYSCALE)

# 使用SIFT算法检测关键点
sift = cv2.SIFT_create()
keypoints, _ = sift.detectAndCompute(image, None)

# 提取关键点的坐标
points = np.array([kp.pt for kp in keypoints])

# 使用Voronoi图
vor = Voronoi(points)

# 绘制Voronoi图
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(12, 6))

# 在第一个子图(ax1)中显示原图
ax1.imshow(image, cmap='gray')
ax1.set_title('Original Image')

# 在第二个子图(ax2)中显示叠加了Voronoi图的图像
voronoi_plot_2d(vor, ax=ax2)
ax2.imshow(thresh, extent=[0, image.shape[1], 0, image.shape[0]], origin='upper', cmap='gray', alpha=0.5)
ax2.scatter(points[:, 0], points[:, 1], c='red', marker='o', s=10)  # 显示关键点
ax2.set_title('Voronoi Overlay')

# 设置坐标轴
ax2.set_xlim([0, image.shape[1]])
ax2.set_ylim([image.shape[0], 0])

plt.show()

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值