1、介绍
图像分割是将图像划分为具有相似属性的区域的过程。图像分割具有多种应用,例如医学图像分割、图像压缩,并用作对象检测和光流等更高级别视觉任务中的预处理步骤。该包是用 Julia 编写的图像分割算法的集合。
2、安装
Pkg.add("ImageSegmentation")
3、例子
图像分割不是一个数学上明确定义的问题:例如,输入图像的唯一无损表示是每个像素都是其自己的片段。然而,这并不符合我们自己的直觉观念,即某些像素自然地分组在一起。因此,许多算法需要参数,通常是某种阈值
,表示您愿意容忍单个片段内像素之间一定量的变化。
让我们看一个有关如何使用此包中的分段算法的示例。我们将尝试将下图中的马、地面和天空分开。我们将探索两种算法 - 种子区域生长
和 felzenszwalb
。种子区域生长需要我们事先知道片段的数量以及每个片段上的一些点,而 felzenszwalb 使用更抽象的参数来控制片段内相似度。
3.1 加载原始图像
horse.jpg
是本地图像,可以去这里下载
using Images, ImageView
img = load("images/horse.jpg")
imshow(img)
3.2 分割图像
最简单的方式是将鼠标悬停
在要分割的不同对象上,然后读出每个对象内一个或多个点的坐标。我们将把种子点存储为元组向量,并与记录的种子点一起(seed position, label)
使用。
seeds = [(CartesianIndex(126,81),1), (CartesianIndex(93,255),2), (CartesianIndex(213,97),3)]
segments = seeded_region_growing(img, seeds)
# 我们可以使用每个片段的平均颜色来可视化:
imshow(map(i->segment_mean(segments,i), labels_map(segments)));
可以看到,该算法在分割三个对象方面做的还不错。唯一明显的错误是“马”的边框和天空元素最终与地面组合在了一起。这是因为seeded_region_growing总是返回连接的区域,并且没有将天空的这些部分连接到更大图像的路径。
如果我们在这些区域添加一些额外的种子点(鼠标悬停,多选择几个点),并给它们提供与天空其余部分相同的标签2
,我们将得到或多或少完美的结果。
3.3 felzenszwalb 算法分割该图像
felzenszwalb只需要一个k控制段大小的参数。更大k将导致更大的细分。
using Images, ImageSegmentation
img = load("images/horse.jpg")
segments = felzenszwalb(img, 100)
segments2 = felzenszwalb(img, 10)
imshow(map(i->segment_mean(segments,i), labels_map(segments)));
imshow(map(i->segment_mean(segments2,i), labels_map(segments2)));
我们只得到了两个“主要”部分k = 100。设置k = 10导致片段较小但有很多噪点。felzenzwalb还带有一个可选参数min_size
它删除所有小于min_size像素的段。 (大多数方法在其核心算法中不会删除小片段。我们可以使用该prune_segments方法对分割结果进行后处理并删除小片段。)
segments = felzenszwalb(img, 10, 100) # 删除小于100像素的片段
imshow(map(i->segment_mean(segments,i), labels_map(segments)))
4、结果
segments = felzenszwalb(img, 10, 100)
println(segments)
# 输出结果
Segmented Image with:
labels map: 240×360 Matrix{Int64}
number of labels: 59
所有分段算法(模糊 C 均值除外)都返回一个结构体SegmentedImage作为其输出。SegmentedImage包含有关段的所有必要信息。以下函数可用于获取有关段的信息:
labels_map:
返回一个数组,其中包含分配给每个像素的标签。segment_labels:
返回所有分配的标签的列表。segment_mean:
返回所提供标签的平均强度。segment_pixel_count:
返回分配给所提供标签的像素计数。
5、种子域算法
种子区域生长根据一些用户定义的种子分割图像。每个种子都是一个(position, label)
元组,其中position
是CartesianIndex
,label
是正整数。每个标签对应于图像的唯一分区。该算法尝试将这些标签分配给每个剩余的点。如果多个点具有相同的标签,那么它们将贡献于同一段。
using Images, ImageSegmentation
img = load("images/worm.jpg")
seeds = [(CartesianIndex(104, 48), 1), (CartesianIndex( 49, 40), 1),
(CartesianIndex( 72,131), 1), (CartesianIndex(109,217), 1),
(CartesianIndex( 28, 87), 2), (CartesianIndex( 64,201), 2),
(CartesianIndex(104, 72), 2), (CartesianIndex( 86,138), 2)];
segments = seeded_region_growing(img, seeds)
imshow(map(i->segment_mean(segments,i), labels_map(segments)));
打印结果:
6、未播种区域算法
该算法类似于种子区域算法,但不需要任何有关种子点的先验信息
。
using Images, ImageSegmentation
img = load("images/tree.jpg");
segments = unseeded_region_growing(img, 0.05);
imshow(map(i->segment_mean(segments,i), labels_map(segments)));
unseeded_region_growing需要图像img
及其threshold
参数。
threshold=0.05
threshold = 0.1
threshold = 0.2