Алгоритм сегментации по морфологическим водоразделам
В этой демонстрации мы сегментируем изображение с помощью алгоритма морфологических водоразделов и узнаем, как он сегментирует изображения. Мы используем пакет ImageSegmentation.jl, в котором реализовано несколько алгоритмов сегментации изображений.
using Images
using ImageSegmentation, TestImages
using IndirectArrays
img = testimage("blobs")
img_example = zeros(Gray, 5, 5)
img_example[2:4,2:4] .= Gray(0.6)
bw = Gray.(img) .> 0.5
bw_example = img_example .> 0.5
5×5 BitMatrix:
0 0 0 0 0
0 1 1 1 0
0 1 1 1 0
0 1 1 1 0
0 0 0 0 0
bw_transform = feature_transform(bw)
bw_transform_example = feature_transform(bw_example)
5×5 Matrix{CartesianIndex{2}}:
CartesianIndex(2, 2) CartesianIndex(2, 2) … CartesianIndex(2, 4)
CartesianIndex(2, 2) CartesianIndex(2, 2) CartesianIndex(2, 4)
CartesianIndex(3, 2) CartesianIndex(3, 2) CartesianIndex(3, 4)
CartesianIndex(4, 2) CartesianIndex(4, 2) CartesianIndex(4, 4)
CartesianIndex(4, 2) CartesianIndex(4, 2) CartesianIndex(4, 4)
Функция feature_transform
позволяет выполнять преобразование признаков для двоичного изображения bw
. Она находит «ближайший» признак (позиции, где bw
имеет значение true
) для каждой позиции в bw
. В частности, F[i]
— это объект CartesianIndex
, кодирующий ближайшую к i
позицию, для которой bw[F[i]]
имеет значение true
. В случае если два или более признаков в bw
находятся на одинаковом расстоянии от i
, один из них выбирается произвольным образом. Если в bw
нет значений true
, все позиции сопоставляются с индексом, каждая координата которого равна typemin(Int)
.
Например, ближайшее к bw_example[1,1]
значение true
находится в позиции CartesianIndex(2, 2)
, поэтому присваивается CartesianIndex(2, 2)
. Для остальных позиций в bw_example
обработка производится аналогично.
dist = 1 .- distance_transform(bw_transform)
dist_example = 1 .- distance_transform(bw_transform_example)
5×5 Matrix{Float64}:
-0.414214 0.0 0.0 0.0 -0.414214
0.0 1.0 1.0 1.0 0.0
0.0 1.0 1.0 1.0 0.0
0.0 1.0 1.0 1.0 0.0
-0.414214 0.0 0.0 0.0 -0.414214
Dist(дистанционное преобразование img) | Dist(дистанционное преобразование img_example) |
---|---|
Дистанционное преобразование (distance transform
) для bw_transform
, где каждый элемент F[i]
в массиве представляет местоположение «цели» или «признака», присвоенное i
. В частности, D[i]
— это расстояние между i
и F[i]
. При необходимости можно указать вес w
для каждой координаты. Значение по умолчанию nothing
эквивалентно w=(1,1,...)
.
В bw_transform
элемент в [1,1] имеет позицию CartesianIndex(2, 2)
, и D[i]
будет расстоянием между CartesianIndex(1, 1)
и CartesianIndex(2, 2)
, равным sqrt(2)
.
dist_trans = dist .< 1
markers = label_components(dist_trans)
markers_example = label_components(dist_example .< 0.5)
Gray.(markers/32.0) # каждое из пятен немного по-разному маркируется label_components в диапазоне от 1 до 64
label_components
находит связанные компоненты в двоичном массиве dist_trans
. Вы можете предоставить список измерений, которые должны использоваться для определения связности. Например, при region = [1,3]
соседних элементов по измерению 2 не будут проверяться связность. Это соответствует проверке только ближайших соседних элементов, то есть связности 4 в двухмерном случае и связности 6 в трехмерном случае. По умолчанию используется region = 1:ndims(A)
. Результат label
представляет собой целочисленный массив, где 0 используется для фоновых пикселей, а каждой связанной области присваивается свой целочисленный индекс.
segments = watershed(dist, markers)
segments_example = watershed(dist_example , markers_example)
Segmented Image with:
labels map: 5×5 Matrix{Int64}
number of labels: 1
Метод watershed
сегментирует изображение с использованием преобразования по морфологическим водоразделам. Каждый бассейн, образованный путем преобразования по морфологическим водоразделам, соответствует сегменту. Для получения сегментов предоставляются dist
и markers
, причем каждому маркеру области присваивается индекс, начиная с 1. Ноль означает, что это не маркер. Если у двух маркеров одинаковый индекс, их области объединяются в одну область.
labels = labels_map(segments)
colored_labels = IndirectArray(labels, distinguishable_colors(maximum(labels)))
masked_colored_labels = colored_labels .* (1 .- bw)
mosaic(img, colored_labels, masked_colored_labels; nrow=1)
Здесь мы используем IndirectArray
для хранения индексированного изображения. Дополнительные сведения см. в руководстве Индексированное изображение за 5 минут.
Эта страница была создана с помощью DemoCards.jl и Literate.jl.