Алгоритм сегментации по морфологическим водоразделам
В этой демонстрации мы сегментируем изображение с помощью алгоритма морфологических водоразделов и узнаем, как он сегментирует изображения. Мы используем пакет 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.

