Документация Engee

Алгоритм сегментации по морфологическим водоразделам

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

contour1

dist 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
xlueoid

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)
hgrxqsc

Здесь мы используем IndirectArray для хранения индексированного изображения. Дополнительные сведения см. в руководстве Индексированное изображение за 5 минут.


Эта страница была создана с помощью DemoCards.jl и Literate.jl.