Справка
Структурирующий элемент
#
ImageMorphology.StructuringElements.strel
— Function
strel([T], X::AbstractArray)
Преобразует структурирующий элемент (СЭ) X
в соответствующий формат представления с типом элементов T
. Это полезный инструмент для создания СЭ, которые принимают большинство функций ImageMorphology.
ImageMorphology в настоящее время поддерживает два распространенных представления:
-
T=CartesianIndex
: смещения относительно центральной точки. Тип вывода —Vector{CartesianIndex{N}}
. -
T=Bool
: маска связи, гдеtrue
означает наличие связи с центральной точкой. Тип вывода —BitArray{N}
.
julia> se_mask = centered(Bool[1 1 0; 1 1 0; 0 0 0]) # маска связи
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
1 1 0
1 1 0
0 0 0
julia> se_offsets = strel(CartesianIndex, se_mask) # смещения относительно центральной точки
3-element Vector{CartesianIndex{2}}:
CartesianIndex(-1, -1)
CartesianIndex(0, -1)
CartesianIndex(-1, 0)
julia> se = strel(Bool, se_offsets)
3×3 OffsetArray(::BitMatrix, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
1 1 0
1 1 0
0 0 0
Конструкторы СЭ для двух особых случаев см. также в описании функций strel_diamond
и strel_box
.
#
ImageMorphology.StructuringElements.strel_chain
— Function
strel_chain(A, B, ...)
strel_chain(As)
Объединяет два структурирующих элемента одинаковой размерности для построения структурирующего элемента большего размера.
Выходное измерение такое же, как входные. См. также функцию strel_product
, которая возвращает декартово произведение СЭ.
Для некоторых морфологических операций |
julia> img = rand(512, 512);
julia> se1, se2 = [centered(rand(Bool, 3, 3)) for _ in 1:2];
julia> se = strel_chain(se1, se2);
julia> out_se = dilate(img, se);
julia> out_pipe = dilate(dilate(img, se1), se2);
julia> out_se[2:end-1, 2:end-1] == out_pipe[2:end-1, 2:end-1] # граница исключается
true
#
ImageMorphology.StructuringElements.strel_product
— Function
strel_product(A, B, ...)
strel_product(se_list)
Декартово произведение нескольких структурирующих элементов; выходное измерение ndims(out) == sum(ndims, se_list)
.
См. также описание функции strel_chain
, которая объединяет СЭ в одном измерении.
julia> strel_product(strel_diamond((5, 5)), centered(Bool[1, 1, 1]))
5×5×3 SEChainArray{3, OffsetArrays.OffsetArray{Bool, 3, BitArray{3}}} with indices -2:2×-2:2×-1:1:
[:, :, -1] =
0 0 1 0 0
0 1 1 1 0
1 1 1 1 1
0 1 1 1 0
0 0 1 0 0
[:, :, 0] =
0 0 1 0 0
0 1 1 1 0
1 1 1 1 1
0 1 1 1 0
0 0 1 0 0
[:, :, 1] =
0 0 1 0 0
0 1 1 1 0
1 1 1 1 1
0 1 1 1 0
0 0 1 0 0
#
ImageMorphology.StructuringElements.strel_box
— Function
strel_box(A; r=1)
strel_box(size; r=size .÷ 2)
Создает N-мерный структурирующий элемент (СЭ), все элементы которого в локальном окне связаны.
Если предоставлено изображение A
, то СЭ будет иметь размер (2r+1, 2r+1, ...)
с половинным размером по умолчанию r=1
. Если предоставлено значение size
, r
по умолчанию будет равно size .÷ 2
. В dims
по умолчанию будут содержаться все измерения, то есть (1, 2, ..., length(size))
.
julia> img = rand(64, 64);
julia> strel_box(img)
3×3 SEBoxArray{2, UnitRange{Int64}} with indices -1:1×-1:1:
1 1 1
1 1 1
1 1 1
julia> strel_box(img; r=2)
5×5 SEBoxArray{2, UnitRange{Int64}} with indices -2:2×-2:2:
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
julia> strel_box((5,5); r=(1,2))
5×5 SEBoxArray{2, UnitRange{Int64}} with indices -2:2×-2:2:
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
|
#
ImageMorphology.StructuringElements.strel_diamond
— Function
strel_diamond(A::AbstractArray, [dims]; r=1)
strel_diamond(size, [dims]; [r])
Создает N-мерный структурирующий элемент (СЭ) ромбовидной формы.
Если предоставлено изображение A
, то СЭ будет иметь размер (2r+1, 2r+1, ...)
с половинным размером по умолчанию r=1
. Если предоставлено значение size
, r
по умолчанию будет равно maximum(size)÷2
. В dims
по умолчанию будут содержаться все измерения, то есть (1, 2, ..., length(size))
.
julia> img = rand(64, 64);
julia> strel_diamond(img) # размер по умолчанию для входного изображения: (3, 3)
3×3 SEDiamondArray{2, 2, UnitRange{Int64}, 0} with indices -1:1×-1:1:
0 1 0
1 1 1
0 1 0
julia> strel_diamond(img; r=2) # эквивалентно `strel_diamond((5,5))`
5×5 SEDiamondArray{2, 2, UnitRange{Int64}, 0} with indices -2:2×-2:2:
0 0 1 0 0
0 1 1 1 0
1 1 1 1 1
0 1 1 1 0
0 0 1 0 0
julia> strel_diamond(img, (1,)) # маска по измерению 1
3×1 SEDiamondArray{2, 1, UnitRange{Int64}, 1} with indices -1:1×0:0:
1
1
1
julia> strel_diamond((3,3), (1,)) # маска 3×3 по измерению 1
3×3 SEDiamondArray{2, 1, UnitRange{Int64}, 1} with indices -1:1×-1:1:
0 1 0
0 1 0
0 1 0
|
#
ImageMorphology.StructuringElements.strel_type
— Function
strel_type(x)
Выводит тип структурирующего элемента для x
.
Эта функция служит для диспетчеризации специальных типов СЭ, например |
#
ImageMorphology.StructuringElements.strel_size
— Function
strel_size(x)
Вычисляет минимальный размер блока, в который вмещается структурирующий элемент. Результатом будет кортеж нечетных целых чисел.
julia> se = strel_diamond((5, 5); r=1)
5×5 SEDiamondArray{2, 2, UnitRange{Int64}, 0} with indices -2:2×-2:2:
0 0 0 0 0
0 0 1 0 0
0 1 1 1 0
0 0 1 0 0
0 0 0 0 0
julia> strel_size(se) # не равно (5, 5)
(3, 3)
julia> strel(Bool, strel(CartesianIndex, se)) # поскольку проверяется только минимальный вмещающий блок
3×3 OffsetArray(::BitMatrix, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
0 1 0
1 1 1
0 1 0
julia> se = [CartesianIndex(1, 1), CartesianIndex(-2, -2)];
julia> strel_size(se) # не равно (4, 4)
(5, 5)
julia> strel(Bool, se) # поскольку маска связи должна иметь нечетный размер
5×5 OffsetArray(::BitMatrix, -2:2, -2:2) with eltype Bool with indices -2:2×-2:2:
1 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 0
julia> se = strel_diamond((5, 5), (1, ); r=1)
5×5 SEDiamondArray{2, 1, UnitRange{Int64}, 1} with indices -2:2×-2:2:
0 0 0 0 0
0 0 1 0 0
0 0 1 0 0
0 0 1 0 0
0 0 0 0 0
julia> strel_size(se)
(3, 1)
#
ImageMorphology.StructuringElements.strel_ndims
— Function
strel_ndims(x)::Int
Выводит измерение структурирующего элемента x
.
#
ImageMorphology.StructuringElements.strel_split
— Function
upper, lower = strel_split([T], se)
Разделяет симметричный структурирующий элемент на верхнюю и нижнюю половины на основе центральной точки.
Для каждого элемента o
в strel(CartesianIndex, upper)
соответствующий отрицательный элемент -o
входит в strel(CartesianIndex, lower)
. Эта функция не является обратной функции strel_chain
.
Разделенные несимметричные части СЭ будут представлены массивом T
, где T
— это либо Bool
, либо CartesianIndex
. По умолчанию T = eltype(se)
.
julia> se = strel_diamond((3, 3))
3×3 SEDiamondArray{2, 2, UnitRange{Int64}, 0} with indices -1:1×-1:1:
0 1 0
1 1 1
0 1 0
julia> upper, lower = strel_split(se);
julia> upper
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
0 1 0
1 1 0
0 0 0
julia> lower
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
0 0 0
0 1 1
0 1 0
Если элемент se
представлен как массив смещений, то результат разделения также будет массивом смещений:
julia> se = strel(CartesianIndex, se)
4-element Vector{CartesianIndex{2}}:
CartesianIndex(0, -1)
CartesianIndex(-1, 0)
CartesianIndex(1, 0)
CartesianIndex(0, 1)
julia> upper, lower = strel_split(se);
julia> upper
2-element Vector{CartesianIndex{2}}:
CartesianIndex(0, -1)
CartesianIndex(-1, 0)
julia> lower
2-element Vector{CartesianIndex{2}}:
CartesianIndex(1, 0)
CartesianIndex(0, 1)
#
OffsetArrays.centered
— Function
centered(A, cp=center(A)) -> Ao
Смещает центральную координату / точку cp
массива A
в точку (0, 0, ..., 0)
. Внутренне это эквивалентно OffsetArray(A, .-cp)
.
Совместимость: OffsetArrays 1.9
Для этого метода требуется версия OffsetArrays не ниже 1.9. |
Примеры
julia> A = reshape(collect(1:9), 3, 3)
3×3 Matrix{Int64}:
1 4 7
2 5 8
3 6 9
julia> Ao = OffsetArrays.centered(A); # оси (-1:1, -1:1)
julia> Ao[0, 0]
5
julia> Ao = OffsetArray(A, OffsetArrays.Origin(0)); # оси (0:2, 0:2)
julia> Aoo = OffsetArrays.centered(Ao); # оси (-1:1, -1:1)
julia> Aoo[0, 0]
5
Пользователи могут передавать cp
, чтобы изменить интерпретацию «центральной точки», но значение выходного массива также должно быть переосмыслено. Например, если cp = map(last, axes(A))
, то эта функция смещает уже не центральную точку, а правую нижнюю точку в точку (0, 0, ..., 0)
. Обычно cp
используется для изменения поведения округления, когда массив имеет четное значение размера в некотором измерении:
julia> A = reshape(collect(1:4), 2, 2) # В идеале центр должен быть в точке (1.5, 1.5), но OffsetArrays поддерживают только целочисленные смещения.
2×2 Matrix{Int64}:
1 3
2 4
julia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundUp)) # задание (2, 2) в качестве центральной точки
2×2 OffsetArray(::Matrix{Int64}, -1:0, -1:0) with eltype Int64 with indices -1:0×-1:0:
1 3
2 4
julia> OffsetArrays.centered(A, OffsetArrays.center(A, RoundDown)) # задание (1, 1) в качестве центральной точки
2×2 OffsetArray(::Matrix{Int64}, 0:1, 0:1) with eltype Int64 with indices 0:1×0:1:
1 3
2 4
См. также описание функции center
.
#
OffsetArrays.center
— Function
center(A, [r::RoundingMode=RoundDown])::Dims
Возвращает координату центра заданного массива A
. Если значение size(A, k)
является четным числом, то будет применена процедура округления с режимом r
.
Совместимость: OffsetArrays 1.9
Для этого метода требуется версия OffsetArrays не ниже 1.9. |
Примеры
julia> A = reshape(collect(1:9), 3, 3)
3×3 Matrix{Int64}:
1 4 7
2 5 8
3 6 9
julia> c = OffsetArrays.center(A)
(2, 2)
julia> A[c...]
5
julia> Ao = OffsetArray(A, -2, -2); # оси (-1:1, -1:1)
julia> c = OffsetArrays.center(Ao)
(0, 0)
julia> Ao[c...]
5
Чтобы сместить центральную координату заданного массива в точку (0, 0, ...)
, можно использовать centered
.
#
ImageMorphology.StructuringElements.is_symmetric
— Function
is_symmetric(se)
Проверяет, является ли данный массив структурирующего элемента se
симметричным относительно центрального пикселя.
Говоря более строго, эта функция проверяет равенство mask[I] == mask[-I]
для любого допустимого I ∈ CartesianIndices(mask)
в представлении маски связи mask = strel(Bool, se)
.
#
ImageMorphology.StructuringElements.SEMask
— Type
SEMask{N}()
Типажный тип (чистый) для представления структурирующего элемента как маски связи. Маска связи СЭ — это массив логических значений, где true
означает, что позиция пикселя связана с центральной точкой.
julia> se = centered(Bool[0 1 0; 1 1 1; 0 1 0]) # широко известно как связь C4
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
0 1 0
1 1 1
0 1 0
julia> strel_type(se)
ImageMorphology.StructuringElements.SEMask{2}()
Сведения о представлении в виде смещений см. в описании типа SEOffset
. Дополнительные сведения можно найти на странице документации Структурирующий элемент.
#
ImageMorphology.StructuringElements.SEOffset
— Type
SEOffset{N}()
Типажный тип (чистый) для представления структурирующего элемента как смещений. Смещения СЭ — это массив CartesianIndex
, в каждом элементе которого хранится смещение от центральной точки.
julia> se = [CartesianIndex(-1, 0), CartesianIndex(0, -1), CartesianIndex(1, 0), CartesianIndex(0, 1)]
4-element Vector{CartesianIndex{2}}:
CartesianIndex(-1, 0)
CartesianIndex(0, -1)
CartesianIndex(1, 0)
CartesianIndex(0, 1)
julia> strel_type(se)
ImageMorphology.StructuringElements.SEOffset{2}()
Сведения о представлении в виде маски связи см. в описании типа SEMask
. Дополнительные сведения можно найти на странице документации Структурирующий элемент.
#
ImageMorphology.StructuringElements.SEDiamond
— Type
SEDiamond{N}(axes, [dims]; [r])
Типажный тип (чистый) для N-мерного структурирующего элемента ромбовидной формы. Это особый случай SEMask
, для которого алгоритмы ImageMorphology могут предоставлять оптимизированную реализацию.
Рекомендуется использовать strel_diamond
и strel_type
:
julia> se = strel_diamond((3, 3)) # связь C4
3×3 SEDiamondArray{2, 2, UnitRange{Int64}, 0} with indices -1:1×-1:1:
0 1 0
1 1 1
0 1 0
julia> strel_type(se)
SEDiamond{2, 2, UnitRange{Int64}}((-1:1, -1:1), (1, 2), 1)
julia> se = centered(collect(se)) # преобразование в обычный центрированный массив
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
0 1 0
1 1 1
0 1 0
julia> strel_type(se)
SEMask{2}()
#
ImageMorphology.StructuringElements.SEBox
— Type
SEBox{N}(axes; [r])
N-мерный структурирующий элемент, все элементы которого связаны. Это особый случай SEMask
, для которого алгоритмы ImageMorphology могут предоставлять оптимизированную реализацию.
Рекомендуется использовать strel_box
и strel_type
:
julia> se = strel_box((3, 3)) # связь C8
3×3 SEBoxArray{2, UnitRange{Int64}} with indices -1:1×-1:1:
1 1 1
1 1 1
1 1 1
julia> strel_type(se)
SEBox{2, UnitRange{Int64}}((-1:1, -1:1), (1, 1))
julia> se = centered(collect(se)) # преобразование в обычный центрированный массив
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
1 1 1
1 1 1
1 1 1
julia> strel_type(se)
SEMask{2}()
Морфологические операции
#
ImageMorphology.extreme_filter
— Function
extreme_filter(f, A; r=1, [dims]) -> out
extreme_filter(f, A, Ω) -> out
Фильтрует массив A
с использованием функции выбора f(x, y)
для каждой окрестности Ω. Слово extreme в названии присутствует по той причине, что в качестве функции выбора f
обычно используются min
и max
.
Для каждого пикселя p
в A
функция выбора f
применяется итеративно к его окрестности Ω следующим образом: f(...(f(f(A[p], A[p+Ω[1]]), A[p+Ω[2]]), ...)
. Например, в одномерном случае для каждого p
по умолчанию выполняется операция out[p] = f(f(A[p], A[p-1]), A[p+1])
.
Окрестность Ω определяется аргументом dims
или Ω
. Именованные аргументы r
и dims
определяют окрестность прямоугольной формы Ω
с использованием функции strel_box
. Ω
также называется структурирующим элементом (СЭ) и может быть представлено смещениями или маской в виде массива логических значений; дополнительные сведения см. в описании функции strel
.
Примеры
julia> M = [4 6 5 3 4; 8 6 9 4 8; 7 8 4 9 6; 6 2 2 1 7; 1 6 5 2 6]
5×5 Matrix{Int64}:
4 6 5 3 4
8 6 9 4 8
7 8 4 9 6
6 2 2 1 7
1 6 5 2 6
julia> extreme_filter(max, M) # фильтр максимума с использованием 4 смежных элементов по обоим измерениям
5×5 Matrix{Int64}:
8 9 9 9 8
8 9 9 9 9
8 9 9 9 9
8 8 9 9 9
6 6 6 7 7
julia> extreme_filter(max, M; dims=1) # фильтр максимума по первому измерению (столбцу)
5×5 Matrix{Int64}:
8 6 9 4 8
8 8 9 9 8
8 8 9 9 8
7 8 5 9 7
6 6 5 2 7
Ω
может быть либо массивом маски AbstractArray{Bool}
, в котором значение true
означает наличие связи, либо массивом AbstractArray{<:CartesianIndex}
, в котором каждый элемент означает смещение относительно центрального элемента.
julia> Ω_mask = centered(Bool[1 1 0; 1 1 0; 1 0 0]) # пользовательская окрестность в формате маски
3×3 OffsetArray(::Matrix{Bool}, -1:1, -1:1) with eltype Bool with indices -1:1×-1:1:
1 1 0
1 1 0
1 0 0
julia> out = extreme_filter(max, M, Ω_mask)
5×5 Matrix{Int64}:
4 8 6 9 4
8 8 9 9 9
8 8 9 9 9
7 8 8 9 9
6 6 6 5 7
julia> Ω_offsets = strel(CartesianIndex, Ω_mask) # пользовательская окрестность в виде смещений
4-element Vector{CartesianIndex{2}}:
CartesianIndex(-1, -1)
CartesianIndex(0, -1)
CartesianIndex(1, -1)
CartesianIndex(-1, 0)
julia> out == extreme_filter(max, M, Ω_offsets) # обе версии работают одинаково
true
См. также выполняемую на месте версию: extreme_filter!
. В пакете ImageFiltering есть функция, предоставляющая аналогичные возможности: ImageFiltering.mapwindow
.
#
ImageMorphology.extreme_filter!
— Function
extreme_filter!(f, out, A; [r], [dims])
extreme_filter!(f, out, A, Ω)
Выполняемая на месте версия функции extreme_filter
, где out
— это выходной массив, подлежащий изменению.
#
ImageMorphology.dilate
— Function
dilate(img; dims=coords_spatial(img), r=1)
dilate(img, se)
Применяет фильтр максимума к окрестности img
, определяемой структурирующим элементом se
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Примеры
julia> img = falses(5, 5); img[3, [2, 4]] .= true; img
5×5 BitMatrix:
0 0 0 0 0
0 0 0 0 0
0 1 0 1 0
0 0 0 0 0
0 0 0 0 0
julia> dilate(img)
5×5 BitMatrix:
0 0 0 0 0
1 1 1 1 1
1 1 1 1 1
1 1 1 1 1
0 0 0 0 0
julia> dilate(img; dims=1)
5×5 BitMatrix:
0 0 0 0 0
0 1 0 1 0
0 1 0 1 0
0 1 0 1 0
0 0 0 0 0
julia> dilate(img, strel_diamond(img)) # используем СЭ ромбовидной формы
5×5 BitMatrix:
0 0 0 0 0
0 1 0 1 0
1 1 1 1 1
0 1 0 1 0
0 0 0 0 0
Дополнительные материалы
Если элемент |
#
ImageMorphology.erode
— Function
out = erode(img; dims=coords_spatial(img), r=1)
out = erode(img, se)
Применяет фильтр минимума к окрестности img
, определяемой структурирующим элементом se
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Примеры
julia> img = trues(5, 5); img[3, [2, 4]] .= false; img
5×5 BitMatrix:
1 1 1 1 1
1 1 1 1 1
1 0 1 0 1
1 1 1 1 1
1 1 1 1 1
julia> erode(img)
5×5 BitMatrix:
1 1 1 1 1
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
1 1 1 1 1
julia> erode(img; dims=1)
5×5 BitMatrix:
1 1 1 1 1
1 0 1 0 1
1 0 1 0 1
1 0 1 0 1
1 1 1 1 1
julia> erode(img, strel_diamond(img)) # используем СЭ ромбовидной формы
5×5 BitMatrix:
1 1 1 1 1
1 0 1 0 1
0 0 0 0 0
1 0 1 0 1
1 1 1 1 1
Дополнительные материалы
Если элемент |
#
ImageMorphology.opening
— Function
opening(img; dims=coords_spatial(img), r=1)
opening(img, se)
Выполняет морфологическое открытие для img
. Операция открытия определяется как эрозия с последующим расширением: dilate(erode(img, se), se)
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Примеры
julia> img = trues(7,7); img[2, 2] = false; img[3:5, 3:5] .= false; img[4, 4] = true; img
7×7 BitMatrix:
1 1 1 1 1 1 1
1 0 1 1 1 1 1
1 1 0 0 0 1 1
1 1 0 1 0 1 1
1 1 0 0 0 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
julia> opening(img)
7×7 BitMatrix:
0 0 1 1 1 1 1
0 0 1 1 1 1 1
1 1 0 0 0 1 1
1 1 0 0 0 1 1
1 1 0 0 0 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
julia> opening(img, strel_diamond(img)) # используем СЭ ромбовидной формы
7×7 BitMatrix:
1 1 1 1 1 1 1
1 0 1 1 1 1 1
1 1 0 0 0 1 1
1 1 0 0 0 1 1
1 1 0 0 0 1 1
1 1 1 1 1 1 1
1 1 1 1 1 1 1
Дополнительные материалы
#
ImageMorphology.closing
— Function
closing(img; dims=coords_spatial(img), r=1)
closing(img, se)
Выполняет морфологическое закрытие для img
. Операция закрытия определяется как расширение с последующей эрозией: erode(dilate(img, se), se)
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Примеры
julia> img = falses(7,7); img[2, 2] = true; img[3:5, 3:5] .= true; img[4, 4] = false; img
7×7 BitMatrix:
0 0 0 0 0 0 0
0 1 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> closing(img)
7×7 BitMatrix:
1 1 0 0 0 0 0
1 1 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 1 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> closing(img, strel_diamond(img)) # # используем СЭ ромбовидной формы
7×7 BitMatrix:
0 0 0 0 0 0 0
0 1 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 1 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Дополнительные материалы
#
ImageMorphology.tophat
— Function
tophat(img; dims=coords_spatial(img), r=1)
tophat(img, se)
Выполняет морфологическое преобразование «верх шляпы» (Top Hat) для данного изображения, то есть img - opening(img, se)
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Это белое преобразование «верх шляпы» может использоваться для выделения небольших белых элементов и деталей на изображении. Для выделения черных деталей можно использовать черное преобразование «верх шляпы», также известное как преобразование «дно шляпы», bothat
.
Примеры
julia> img = falses(5, 5); img[1, 1] = true; img[3:5, 3:5] .= true; img
5×5 BitMatrix:
1 0 0 0 0
0 0 0 0 0
0 0 1 1 1
0 0 1 1 1
0 0 1 1 1
julia> Int.(tophat(img))
5×5 Matrix{Int64}:
1 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
julia> Int.(tophat(img, strel_diamond(img))) # используем СЭ ромбовидной формы
5×5 Matrix{Int64}:
1 0 0 0 0
0 0 0 0 0
0 0 1 0 0
0 0 0 0 0
0 0 0 0 0
#
ImageMorphology.bothat
— Function
bothat(img; dims=coords_spatial(img), r=1)
bothat(img, se)
Выполняет морфологическое преобразование «дно шляпы» (Bottom Hat) для данного изображения, то есть closing(img, se) - img
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Преобразование «дно шляпы», также известное как черное преобразование «верх шляпы», может использоваться для выделения небольших черных элементов и деталей на изображении. Для выделения белых деталей можно использовать белое преобразование «верх шляпы», tophat
.
Примеры
julia> img = falses(7, 7); img[3:5, 3:5] .= true; img[4, 6] = true; img[4, 4] = false; img
7×7 BitMatrix:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 0 1 1 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> Int.(bothat(img))
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 1 0 0 1
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> Int.(bothat(img, strel_diamond(img))) # используем СЭ ромбовидной формы
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 1 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
Есть также выполняемая на месте версия: bothat!
.
#
ImageMorphology.mgradient
— Function
mgradient(img; mode=:beucher, dims=coords_spatial(img), r=1)
mgradient(img, se; mode=:beucher)
Вычисляет морфологический градиент изображения в указанном режиме.
Широко применяются три режима [1]:
-
:beucher
: режим по умолчанию. Вычисляется арифметическая разность расширения и эрозии:dilate(img, se) - erode(img, se)
. -
:internal
: также называется половинным градиентом по эрозии. Вычисляется арифметическая разность исходного изображения и его эрозии:img - erode(img, se)
. -
:external
: также называется половинным градиентом по расширению. Вычисляется арифметическая разность расширения и исходного изображения:dilate(img, se) - se
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Примеры
julia> img = falses(7, 7); img[3:5, 3:5] .= true; img
7×7 BitMatrix:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 1 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> Int.(mgradient(img)) # в режиме по умолчанию :beucher всегда создается граница шириной два пикселя
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 1 1 0 1 1 0
0 1 1 1 1 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
julia> Int.(mgradient(img; mode=:internal)) # половинный градиент -- граница находится внутри исходного изображения
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> Int.(mgradient(img; mode=:external)) # половинный градиент -- граница находится вне исходного изображения
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 0 0 0 1 0
0 1 0 0 0 1 0
0 1 0 0 0 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
julia> Int.(mgradient(img, strel_diamond(img))) # используем СЭ ромбовидной формы
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 1 1 1 1 1 0
0 1 1 0 1 1 0
0 1 1 1 1 1 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
Оператор Боше является самодополняющимся в том смысле, что mgradient(img, se; mode=:beucher) == mgradient(complement.(img), se; mode=:beucher)
. При r>1
он обычно называется толстым градиентом. Если в качестве se
используется отрезок прямой, то градиент становится направленным.
Дополнительные материалы
-
mgradient!
is the in-place version of this function. -
mlaplacian
for the laplacian operator. -
ImageBase.FiniteDiff
также предоставляет несколько конечных разностных операторов, включаяfdiff
,fgradient
и другие.
Справочные материалы
-
[1] Rivest, Jean-Francois, Pierre Soille, and Serge Beucher. Morphological gradients. Journal of Electronic Imaging 2.4 (1993): 326—336.
#
ImageMorphology.mgradient!
— Function
mgradient!(out, img, buffer; [dims], [r], [mode])
mgradient!(out, img, se, buffer; [mode])
Выполняемая на месте версия mgradient
с входным изображением img
и выходным изображением out
.
В режиме :beucher
требуется массив buffer
. В режимах :internal
и :external
buffer
не требуется и может быть nothing
.
#
ImageMorphology.mlaplacian
— Function
mlaplacian(img; dims=coords_spatial(img), r=1)
mlaplacian(img, se)
Вычисляет морфологический лапласиан изображения.
Оператор морфологического лапласиана определяется как ∇⁺A - ∇⁻A
, где ∇⁺A
— внешний градиент A - erode(A, se)
, а ∇⁻A
— внутренний градиент dilate(A, se) - A
. Таким образом, он равен dilate(A, se) + erode(A, se) - 2A
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации.
Примеры
julia> img = falses(7, 7); img[3:5, 3:5] .= true; img[4, 4] = false; img
7×7 BitMatrix:
0 0 0 0 0 0 0
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 0 1 0 1 0 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
0 0 0 0 0 0 0
julia> Int.(mlaplacian(img))
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 1 1 1 1 1 0
0 1 -1 -1 -1 1 0
0 1 -1 1 -1 1 0
0 1 -1 -1 -1 1 0
0 1 1 1 1 1 0
0 0 0 0 0 0 0
julia> Int.(mlaplacian(img, strel_diamond(img))) # используем СЭ ромбовидной формы
7×7 Matrix{Int64}:
0 0 0 0 0 0 0
0 0 1 1 1 0 0
0 1 -1 -1 -1 1 0
0 1 -1 1 -1 1 0
0 1 -1 -1 -1 1 0
0 0 1 1 1 0 0
0 0 0 0 0 0 0
Дополнительные материалы
-
mlaplacian!
is the in-place version of this function. -
mgradient
for the gradient operator. -
ImageBase.FiniteDiff
также предоставляет несколько конечных разностных операторов, включаяfdiff
,fgradient
и другие.
#
ImageMorphology.mlaplacian!
— Function
mlaplacian!(out, img, buffer; [dims], [r])
mlaplacian!(out, img, se, buffer)
Выполняемая на месте версия mlaplacian
с входным изображением img
и выходным изображением out
. Промежуточный результат эрозии сохраняется в buffer
.
Геодезические операции
#
ImageMorphology.mreconstruct
— Function
mreconstruct(op, marker, mask; [dims])
mreconstruct(op, marker, mask, se)
Морфологическая реконструкция изображения marker
по операции op
.
Аргумент op
может иметь значение erode
или dilate
, означающее реконструкцию по эрозии или расширению. Аргумент mask
имеет ту же форму, что и marker
, и применяется для ограничения диапазона выходных значений.
Именованный аргумент dims
служит для указания измерения, которое должно быть обработано путем построения структурирующего элемента прямоугольной формы strel_box(marker; dims)
. Для универсального структурирующего элемента половинный размер по каждому измерению должен быть равен 0
или 1
.
По определению реконструкция выполняется путем многократного применения marker = select.(op(marker; dims), mask)
, пока не будет достигнута устойчивость. Для расширения op, select = dilate, min
, а для эрозии op, select = erode, max
.
Примеры
julia> marker = [0 0 0 0 0; 0 9 0 0 0; 0 0 0 0 0; 0 0 0 5 0; 0 0 0 0 0; 0 9 0 0 0]
6×5 Matrix{Int64}:
0 0 0 0 0
0 9 0 0 0
0 0 0 0 0
0 0 0 5 0
0 0 0 0 0
0 9 0 0 0
julia> mask = [9 0 0 0 0; 0 8 7 1 0; 0 9 0 4 0; 0 0 0 4 0; 0 0 6 5 6; 0 0 9 8 9]
6×5 Matrix{Int64}:
9 0 0 0 0
0 8 7 1 0
0 9 0 4 0
0 0 0 4 0
0 0 6 5 6
0 0 9 8 9
julia> mreconstruct(dilate, marker, mask) # эквивалентно underbuild(marker, mask)
6×5 Matrix{Int64}:
8 0 0 0 0
0 8 7 1 0
0 8 0 4 0
0 0 0 4 0
0 0 4 4 4
0 0 4 4 4
Дополнительные материалы
Выполняемая на месте версия этой функции — mreconstruct!
. Существуют также псевдонимы underbuild
для реконструкции по расширению и overbuild
для реконструкции по эрозии.
Справочные материалы
-
[1] L. Vincent. Morphological grayscale reconstruction in image analysis: applications and efficient algorithms. IEEE Trans. on Image Process., vol. 2, no. 2, pp. 176—201, Apr. 1993, doi: 10.1109/83.217222.
-
[2] P. Soille. Morphological Image Analysis. Berlin, Heidelberg: Springer Berlin Heidelberg, 2004. doi: 10.1007/978-3-662-05088-0.
#
ImageMorphology.mreconstruct!
— Function
mreconstruct!(op, out, marker, mask; [dims])
Выполняемая на месте версия морфологической реконструкции mreconstruct
.
#
ImageMorphology.underbuild
— Function
underbuild(marker, mask; [dims])
underbuild(marker, mask, se)
Реконструкция по расширению. Это псевдоним для mreconstruct
с op=dilate
.
См. также выполняемую на месте версию underbuild!
и двойственный оператор overbuild
.
#
ImageMorphology.underbuild!
— Function
underbuild!(out, marker, mask; [dims])
underbuild!(out, marker, mask, se)
Выполняемая на месте версия underbuild
с выходным изображением out
, изменяемым на месте.
#
ImageMorphology.overbuild
— Function
overbuild(marker, mask; [dims])
overbuild(marker, mask, se)
Реконструкция по эрозии. Это псевдоним для mreconstruct
с op=erode
.
См. также выполняемую на месте версию overbuild!
и двойственный оператор underbuild
.
Компоненты и сегментация
#
ImageMorphology.label_components
— Function
label = label_components(A; [dims=coords_spatial(A)], [r=1], [bkg])
label = label_components(A, se; [bkg])
Находит и маркирует связанные компоненты массива A
, где связь определяется структурирующим элементом se
. Каждому компоненту присваивается уникальное целочисленное значение в качестве метки, где 0
представляет фон, указанный в bkg
.
se
— это структурирующий элемент, определяющий окрестность изображения. Дополнительные сведения см. в описании функции strel
. Если элемент se
не указан, используется функция strel_box
с дополнительным именованным аргументом dims
, определяющим измерения для фильтрации, и половинным размером r
, определяющим размер ромба.
Примеры
julia> A = [false true false true false;
true false false true true]
2×5 Matrix{Bool}:
0 1 0 1 0
1 0 0 1 1
julia> label_components(A) # связь C4 по умолчанию ромбовидной формы
2×5 Matrix{Int64}:
0 2 0 3 0
1 0 0 3 3
julia> label_components(A; dims=2) # учитываются только строки
2×5 Matrix{Int64}:
0 2 0 3 0
1 0 0 4 4
julia> label_components(A, strel_box((3, 3))) # связь C8 прямоугольной формы
2×5 Matrix{Int64}:
0 1 0 2 0
1 0 0 2 2
Выполняемая на месте версия — label_components!
. Основные свойства маркируемых компонентов см. в описании component_boxes
, component_lengths
, component_indices
, component_centroids
.
#
ImageMorphology.label_components!
— Function
label_components!(out, A; [dims], [r] [bkg])
label_components!(out, A, se; [bkg])
Выполняемая на месте версия label_components
.
#
ImageMorphology.component_boxes
— Function
boxes = component_boxes(labeled_array)
Вычисляет минимальные ограничивающие прямоугольники для каждой метки, включая метку фона. Метки можно вычислить с помощью функции label_components
.
Каждый ограничивающий прямоугольник представлен в виде CartesianIndices
. boxes
смещается в вектор с индексацией с нуля так, что фоновый участок равен boxes[0]
.
julia> A = [2 2 2 2 2; 1 1 1 0 1; 1 0 2 1 1; 1 1 2 2 2; 1 0 2 2 2]
5×5 Matrix{Int64}:
2 2 2 2 2
1 1 1 0 1
1 0 2 1 1
1 1 2 2 2
1 0 2 2 2
julia> label = label_components(A) # четыре несмежных компонента
5×5 Matrix{Int64}:
1 1 1 1 1
2 2 2 0 4
2 0 3 4 4
2 2 3 3 3
2 0 3 3 3
julia> boxes = component_boxes(label) # получаем ограничивающие прямоугольники всех участков
5-element OffsetArray(::Vector{CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}}}, 0:4) with eltype CartesianIndices{2, Tuple{UnitRange{Int64}, UnitRange{Int64}}} with indices 0:4:
CartesianIndices((2:5, 2:4))
CartesianIndices((1:1, 1:5))
CartesianIndices((2:5, 1:3))
CartesianIndices((3:5, 3:5))
CartesianIndices((2:3, 4:5))
julia> A[boxes[1]] # обрезаем участок изображения с меткой 1
1×5 Matrix{Int64}:
2 2 2 2 2
julia> A[boxes[4]] # обрезаем участок изображения с меткой 4
2×2 Matrix{Int64}:
0 1
1 1
#
ImageMorphology.component_lengths
— Function
counts = component_lengths(labeled_array)
Подсчитывает количество каждой метки во входном маркированном массиве. counts
смещается в вектор с индексацией с нуля так, что количество фоновых пикселей равно counts[0]
.
julia> A = [2 2 2 2 2; 1 1 1 0 1; 1 0 2 1 1; 1 1 2 2 2; 1 0 2 2 2]
5×5 Matrix{Int64}:
2 2 2 2 2
1 1 1 0 1
1 0 2 1 1
1 1 2 2 2
1 0 2 2 2
julia> label = label_components(A) # четыре несмежных компонента
5×5 Matrix{Int64}:
1 1 1 1 1
2 2 2 0 4
2 0 3 4 4
2 2 3 3 3
2 0 3 3 3
julia> component_lengths(label)
5-element OffsetArray(::Vector{Int64}, 0:4) with eltype Int64 with indices 0:4:
3
5
7
7
3
Для изображений в оттенках серого метки можно вычислить с помощью функции label_components
.
#
ImageMorphology.component_indices
— Function
indices = component_indices([T], labeled_array)
Возвращает индексы каждой метки во входном маркированном массиве. indices
смещается в вектор с индексацией с нуля так, что индексы фоновых пикселей равны indices[0]
.
Необязательным типом T
, определяющим тип индексов, может быть либо Int
/IndexLinear()
, либо CartesianIndex
/IndexCartesian()
. По умолчанию используется IndexStyle(labeled_array)
.
julia> A = [2 2 2 2 2; 1 1 1 0 1; 1 0 2 1 1; 1 1 2 2 2; 1 0 2 2 2]
5×5 Matrix{Int64}:
2 2 2 2 2
1 1 1 0 1
1 0 2 1 1
1 1 2 2 2
1 0 2 2 2
julia> label = label_components(A) # четыре несмежных компонента
5×5 Matrix{Int64}:
1 1 1 1 1
2 2 2 0 4
2 0 3 4 4
2 2 3 3 3
2 0 3 3 3
julia> indices = component_indices(label)
5-element OffsetArray(::Vector{Vector{Int64}}, 0:4) with eltype Vector{Int64} with indices 0:4:
[8, 10, 17]
[1, 6, 11, 16, 21]
[2, 3, 4, 5, 7, 9, 12]
[13, 14, 15, 19, 20, 24, 25]
[18, 22, 23]
julia> indices = component_indices(CartesianIndex, label)
5-element OffsetArray(::Vector{Vector{CartesianIndex{2}}}, 0:4) with eltype Vector{CartesianIndex{2}} with indices 0:4:
[CartesianIndex(3, 2), CartesianIndex(5, 2), CartesianIndex(2, 4)]
[CartesianIndex(1, 1), CartesianIndex(1, 2), CartesianIndex(1, 3), CartesianIndex(1, 4), CartesianIndex(1, 5)]
[CartesianIndex(2, 1), CartesianIndex(3, 1), CartesianIndex(4, 1), CartesianIndex(5, 1), CartesianIndex(2, 2), CartesianIndex(4, 2), CartesianIndex(2, 3)]
[CartesianIndex(3, 3), CartesianIndex(4, 3), CartesianIndex(5, 3), CartesianIndex(4, 4), CartesianIndex(5, 4), CartesianIndex(4, 5), CartesianIndex(5, 5)]
[CartesianIndex(3, 4), CartesianIndex(2, 5), CartesianIndex(3, 5)]
Для изображений в оттенках серого метки можно вычислить с помощью функции label_components
.
#
ImageMorphology.component_centroids
— Function
centroids = component_centroids(labeled_array)
Вычисляет центроид каждой метки во входном маркированном массиве. centroids
смещается в вектор с индексацией с нуля так, что центроид фоновых пикселей равен centroids[0]
.
Центроид конечного множества X
, также называемый геометрическим центром, вычисляется как sum(X)/length(X)
. Если дана метка i
, для построения множества X
используются все (декартовы) индексы пикселей с меткой i
.
julia> A = [2 2 2 2 2; 1 1 1 0 1; 1 0 2 1 1; 1 1 2 2 2; 1 0 2 2 2]
5×5 Matrix{Int64}:
2 2 2 2 2
1 1 1 0 1
1 0 2 1 1
1 1 2 2 2
1 0 2 2 2
julia> label = label_components(A) # четыре несмежных компонента
5×5 Matrix{Int64}:
1 1 1 1 1
2 2 2 0 4
2 0 3 4 4
2 2 3 3 3
2 0 3 3 3
julia> component_centroids(label)
5-element OffsetArray(::Vector{Tuple{Float64, Float64}}, 0:4) with eltype Tuple{Float64, Float64} with indices 0:4:
(3.3333333333333335, 2.6666666666666665)
(1.0, 3.0)
(3.142857142857143, 1.5714285714285714)
(4.285714285714286, 3.857142857142857)
(2.6666666666666665, 4.666666666666667)
Для изображений в оттенках серого метки можно вычислить с помощью функции label_components
.
Дерево максимумов
#
ImageMorphology.MaxTree
— Type
Морфологическое представление изображения в виде дерева максимумов.
Подробные сведения
Рассмотрим операцию определения порога.
mask = [val ≥ threshold for val in image]
В mask
можно определить связанные компоненты (множества смежных значений true). При последовательном применении операции определения порога изображения для всех возможных порогов создается коллекция связанных компонентов, которые можно упорядочить в иерархическую структуру, называемую деревом компонентов. Рассмотрим одномерное изображение со значениями 1, 2 и 3.
2233233312223322
Связанными будут следующие компоненты:
1: AAAAAAAAAAAAAAAA 2: BBBBBBBB.CCCCCCC 3: ..DD.EEE....FF..
Здесь буквы — это метки итоговых связанных компонентов, а .
указывает, что значение пикселя ниже порога. В данном примере соответствующее дерево компонентов имеет следующий вид.
A ⭩ ⭨ B C ⭩ ⭨ ⭨ D E F
Дерево максимумов — это эффективное представление дерева компонентов. Связанный компонент на пороговом уровне представлен одним базисным пикселем с этого уровня (image[r] == t
). Он является родительским для всех остальных пикселей , а также для базисных пикселей связанных компонентов на более высоких пороговых уровнях, являющихся дочерними относительно . В нашем примере базисные пиксели (обозначенные буквой соответствующего компонента) будут следующими:
1: ........A....... 2: B........C...... 3: ..D..E......F...
То есть:
Компонент | Базисный пиксель |
---|---|
A |
9 |
B |
1 |
C |
10 |
D |
3 |
E |
6 |
F |
13 |
Таким образом, все дерево максимумов можно закодировать как вектор индексов родительских пикселей:
9 1 1 3 1 1 6 6 9 9 10 10 10 13 10 10
Дерево максимумов является основой для многих морфологических операторов, а именно для связанных операторов. В отличие от морфологических открытий и закрытий, эти операторы не требуют фиксированного структурирующего элемента. Вместо этого они действуют как гибкий структурирующий элемент, отвечающий определенному критерию.
Дополнительные материалы
Справочные материалы
-
Salembier, P., Oliveras, A., & Garrido, L. (1998). Antiextensive Connected Operators for Image and Sequence Processing. IEEE Transactions on Image Processing, 7(4), 555—570.
-
Berger, C., Geraud, T., Levillain, R., Widynski, N., Baillard, A., Bertin, E. (2007). Effective Component Tree Computation with Application to Pattern Recognition in Astronomical Imaging. In International Conference on Image Processing (ICIP), 41—44.
-
Najman, L., Couprie, M. (2006). Building the component tree in quasi-linear time. IEEE Transactions on Image Processing, 15(11), 3531—3539.
-
Carlinet, E., Geraud, T. (2014). A Comparative Review of Component Tree Computation Algorithms. IEEE Transactions on Image Processing, 23(9), 3885—3895.
#
ImageMorphology.areas
— Function
areas(maxtree::MaxTree) -> Array{Int}
Вычисляет площади всех компонентов maxtree
.
Возвращаемые значения
Массив той же формы, что и у исходного изображения. i
-й элемент — это площадь (в пикселях) компонента, представленного базисным пикселем с индексом i
.
Дополнительные материалы
#
ImageMorphology.boundingboxes
— Function
boundingboxes(maxtree::MaxTree) -> Array{NTuple{2, CartesianIndex}}
Вычисляет минимальные ограничивающие прямоугольники всех компонентов maxtree
.
Возвращаемые значения
Массив той же формы, что и у исходного изображения. i
-й элемент — это кортеж из минимального и максимального декартовых индексов ограничивающего прямоугольника для компонента, представленного базисным пикселем с индексом i
.
Дополнительные материалы
#
ImageMorphology.diameters
— Function
diameters(maxtree::MaxTree) -> Array{Int}
Вычисляет «диаметры» всех компонентов maxtree
.
«Диаметр» связанного компонента дерева максимумов — это длина самой широкой стороны ограничивающего прямоугольника компонента.
Возвращаемые значения
Массив той же формы, что и у исходного изображения. i
-й элемент — это «диаметр» компонента, представленного базисным пикселем с индексом i
.
Дополнительные материалы
#
ImageMorphology.area_opening
— Function
area_opening(image, [maxtree]; min_area=64, connectivity=1) -> Array
Выполняет открытие по площади для image
.
Операция открытия по площади заменяет все яркие компоненты изображения, имеющие площадь менее min_area
, более темным значением из первого компонента-потомка (в представлении image
в виде дерева максимумов) с площадью не менее min_area
.
Подробные сведения
Открытие по площади сходно с морфологическим открытием (см. описание функции opening
), но вместо использования фиксированного структурирующего элемента (например, диска) применяются небольшие (менее min_area
) компоненты дерева максимумов. Следовательно, area_opening
с min_area = 1
— тождественное преобразование.
В двоичном случае открытие по площади эквивалентно remove_small_objects
; таким образом, этот оператор распространяется на полутоновые изображения.
Аргументы
-
image::GenericGrayImage
: -мерное входное изображение. -
min_area::Number=64
: наименьший размер (в пикселях) компонента изображения, который должен оставаться без изменений. -
connectivity::Integer=1
: смежная связь. Максимальное количество ортогональных шагов для достижения смежного элемента пикселя. В двухмерном случае равно 1 для связи с 4 смежными элементами и 2 для связи с 8 смежными элементами. -
maxtree::MaxTree
: необязательное предварительно построенное дерево максимумов. Учтите, что необязательные параметрыmaxtree
иconnectivity
являются взаимоисключающими.
Возвращаемые значения
Массив того же типа и той же формы, что и image
.
Дополнительные материалы
Справочные материалы
-
Vincent, L. (1993). Grayscale area openings and closings, their efficient implementation and applications, Proc. of EURASIP Workshop on Mathematical Morphology and its Applications to Signal Processing, Barcelona, Spain, 22—27
-
Soille, P. (2003). Chapter 6 Geodesic Metrics of Morphological Image Analysis: **Principles and Applications, 2nd edition, Springer.
-
Salembier, P., Oliveras, A., & Garrido, L. (1998). Antiextensive Connected Operators for Image and Sequence Processing. IEEE Transactions on Image Processing, 7(4), 555—570.
-
Najman, L., Couprie, M. (2006). Building the component tree in quasi-linear time. IEEE Transactions on Image Processing, 15(11), 3531—3539.
-
Carlinet, E., Geraud, T. (2014). A Comparative Review of Component Tree Computation Algorithms. IEEE Transactions on Image Processing, 23(9), 3885—3895.
Примеры
Создание тестового изображения f
(квадратичная функция с максимумом в центре и еще 4 локальными максимумами):
julia> w = 12;
julia> f = [20 - 0.2*((x - w/2)^2 + (y-w/2)^2) for x in 0:w, y in 0:w];
julia> f[3:4, 2:6] .= 40; f[3:5, 10:12] .= 60; f[10:12, 3:5] .= 80;
julia> f[10:11, 10:12] .= 100; f[11, 11] = 100;
julia> f_aopen = area_opening(f, min_area=8, connectivity=1);
Пики с поверхностью менее 8 удалены.
#
ImageMorphology.area_opening!
— Function
area_opening!(output, image, [maxtree];
min_area=64, connectivity=1) -> output
Выполняет открытие по площади для image
на месте и сохраняет результат в output
. Подробное описание метода см. в разделе, посвященном функции area_opening
.
#
ImageMorphology.area_closing
— Function
area_closing(image, [maxtree]; min_area=64, connectivity=1) -> Array
Выполняет закрытие по площади для image
.
Операция закрытия по площади заменяет все темные компоненты изображения, имеющие площадь менее min_area
, более ярким значением из первого компонента-потомка (в представлении image
в виде дерева максимумов) с площадью не менее min_area
.
Подробные сведения
Закрытие по площади является двойственной операцией по отношению к открытию по площади (см. описание функции area_opening
). Оно сходно с морфологическим закрытием (см. описание функции closing
), но вместо использования фиксированного структурирующего элемента (например, диска) применяются небольшие (менее min_area
) компоненты дерева максимумов. Следовательно, area_closing
с min_area = 1
— тождественное преобразование.
В двоичном случае закрытие по площади эквивалентно remove_small_holes
; таким образом, этот оператор распространяется на полутоновые изображения.
Аргументы
-
image::GenericGrayImage
: -мерное входное изображение. -
min_area::Number=64
: наименьший размер (в пикселях) компонента изображения, который должен оставаться без изменений. -
connectivity::Integer=1
: смежная связь. Максимальное количество ортогональных шагов для достижения смежного элемента пикселя. В двухмерном случае равно 1 для связи с 4 смежными элементами и 2 для связи с 8 смежными элементами. -
maxtree::MaxTree
: необязательное предварительно построенное дерево максимумов. Учтите, что необязательные параметрыmaxtree
иconnectivity
являются взаимоисключающими.
Возвращаемые значения
Массив того же типа и той же формы, что и image
.
Дополнительные материалы
Справочные материалы
-
Vincent, L. (1993). Grayscale area openings and closings, their efficient implementation and applications, Proc. of EURASIP Workshop on Mathematical Morphology and its Applications to Signal Processing, Barcelona, Spain, 22—27
-
Soille, P. (2003). Chapter 6 Geodesic Metrics of Morphological Image Analysis: **Principles and Applications, 2nd edition, Springer.
-
Salembier, P., Oliveras, A., & Garrido, L. (1998). Antiextensive Connected Operators for Image and Sequence Processing. IEEE Transactions on Image Processing, 7(4), 555—570.
-
Najman, L., Couprie, M. (2006). Building the component tree in quasi-linear time. IEEE Transactions on Image Processing, 15(11), 3531—3539.
-
Carlinet, E., Geraud, T. (2014). A Comparative Review of Component Tree Computation Algorithms. IEEE Transactions on Image Processing, 23(9), 3885—3895.
Примеры
Создание тестового изображения f
(квадратичная функция с минимумом в центре и еще 4 локальными минимумами):
julia> w = 12;
julia> f = [180 + 0.2*((x - w/2)^2 + (y-w/2)^2) for x in 0:w, y in 0:w];
julia> f[3:4, 2:6] .= 40; f[3:5, 10:12] .= 60; f[10:12, 3:5] .= 80;
julia> f[10:11, 10:12] .= 100; f[11, 11] = 100;
julia> f_aclose = area_closing(f, min_area=8, connectivity=1);
Все небольшие минимумы удаляются, так что остаются только минимумы размером не менее 8.
#
ImageMorphology.area_closing!
— Function
area_closing!(output, image, [maxtree];
min_area=64, connectivity=1) -> output
Выполняет закрытие по площади для image
на месте и сохраняет результат в output
. Подробное описание метода см. в разделе, посвященном функции area_closing
.
#
ImageMorphology.diameter_opening
— Function
diameter_opening(image, [maxtree]; min_diameter=8, connectivity=1) -> Array
Выполняет открытие по диаметру для image
.
Операция открытия по диаметру заменяет все яркие структуры изображения, имеющие диаметр (длину самой широкой стороны ограничивающего прямоугольника) менее min_diameter
, более темным значением из первого компонента-потомка (в представлении image
в виде дерева максимумов) с диаметром не менее min_diameter
.
Этот оператор также называется открытием по ограничивающему прямоугольнику. На практике результат аналогичен морфологическому открытию, но длинные и узкие структуры не удаляются.
Аргументы
-
image::GenericGrayImage
: -мерное входное изображение. -
min_diameter::Number=8
: минимальная длина (в пикселях) самой широкой стороны ограничивающего прямоугольника компонента изображения, который должен оставаться без изменений. -
connectivity::Integer=1
: смежная связь. Максимальное количество ортогональных шагов для достижения смежного элемента пикселя. В двухмерном случае равно 1 для связи с 4 смежными элементами и 2 для связи с 8 смежными элементами. -
maxtree::MaxTree
: необязательное предварительно построенное дерево максимумов. Учтите, что необязательные параметрыmaxtree
иconnectivity
являются взаимоисключающими.
Возвращаемые значения
Массив того же типа и той же формы, что и image
.
Дополнительные материалы
Справочные материалы
-
Walter, T., Klein, J.-C. (2002). Automatic Detection of Microaneurysms in Color Fundus Images of the Human Retina by Means of the Bounding Box Closing. In A. Colosimo, P. Sirabella, A. Giuliani (Eds.), Medical Data Analysis. Lecture Notes in Computer Science, vol 2526, 210—220. Springer Berlin Heidelberg.
-
Carlinet, E., Geraud, T. (2014). A Comparative Review of Component Tree Computation Algorithms. IEEE Transactions on Image Processing, 23(9), 3885—3895.
Примеры
Создание тестового изображения f
(квадратичная функция с максимумом в центре и еще 4 локальными максимумами):
julia> w = 12;
julia> f = [20 - 0.2*((x - w/2)^2 + (y-w/2)^2) for x in 0:w, y in 0:w];
julia> f[3:4, 2:6] .= 40; f[3:5, 10:12] .= 60; f[10:12, 3:5] .= 80;
julia> f[10:11, 10:12] .= 100; f[11, 11] = 100;
julia> f_dopen = diameter_opening(f, min_diameter=3, connectivity=1);
Пики с максимальным диаметром 2 или менее удаляются. У оставшихся пиков самая широкая сторона ограничивающего прямоугольника имеет длину не менее 3.
#
ImageMorphology.diameter_opening!
— Function
diameter_opening!(output, image, [maxtree];
min_diameter=8, connectivity=1) -> output
Выполняет открытие по диаметру для image
на месте и сохраняет результат в output
. Подробное описание метода см. в разделе, посвященном функции diameter_opening
.
#
ImageMorphology.diameter_closing
— Function
diameter_closing(image, [maxtree]; min_diameter=8, connectivity=1) -> Array
Выполняет закрытие по диаметру для image
.
Операция закрытия по диаметру заменяет все темные структуры изображения, имеющие диаметр (длину самой широкой стороны ограничивающего прямоугольника) менее min_diameter
, более ярким значением из первого компонента-потомка (в представлении image
в виде дерева максимумов) с диаметром не менее min_diameter
.
Аргументы
-
image::GenericGrayImage
: -мерное входное изображение. -
min_diameter::Number=8
: минимальная длина (в пикселях) самой широкой стороны ограничивающего прямоугольника компонента изображения, который должен оставаться без изменений. -
connectivity::Integer=1
: смежная связь. Максимальное количество ортогональных шагов для достижения смежного элемента пикселя. В двухмерном случае равно 1 для связи с 4 смежными элементами и 2 для связи с 8 смежными элементами. -
maxtree::MaxTree
: необязательное предварительно построенное дерево максимумов. Учтите, что необязательные параметрыmaxtree
иconnectivity
являются взаимоисключающими.
Возвращаемые значения
Массив того же типа и той же формы, что и image
.
Дополнительные материалы
Справочные материалы
-
Walter, T., Klein, J.-C. (2002). Automatic Detection of Microaneurysms in Color Fundus Images of the Human Retina by Means of the Bounding Box Closing. In A. Colosimo, P. Sirabella, A. Giuliani (Eds.), Medical Data Analysis. Lecture Notes in Computer Science, vol 2526, 210—220. Springer Berlin Heidelberg.
-
Carlinet, E., Geraud, T. (2014). A Comparative Review of Component Tree Computation Algorithms. IEEE Transactions on Image Processing, 23(9), 3885—3895.
Примеры
Создание тестового изображения f
(квадратичная функция с минимумом в центре и еще 4 локальными минимумами):
julia> w = 12;
julia> f = [180 + 0.2*((x - w/2)^2 + (y-w/2)^2) for x in 0:w, y in 0:w];
julia> f[3:4, 2:6] .= 40; f[3:5, 10:12] .= 60; f[10:12, 3:5] .= 80;
julia> f[10:11, 10:12] .= 100; f[11, 11] = 100;
julia> f_dclose = diameter_closing(f, min_diameter=3, connectivity=1);
Все небольшие минимумы с диаметром 2 или менее удаляются. У оставшихся минимумов самая широкая сторона ограничивающего прямоугольника имеет длину не менее 3.
#
ImageMorphology.diameter_closing!
— Function
diameter_closing!(output, image, [maxtree];
min_diameter=8, connectivity=1) -> output
Выполняет закрытие по диаметру для image
на месте и сохраняет результат в output
. Подробное описание метода см. в разделе, посвященном функции diameter_closing
.
#
ImageMorphology.local_maxima!
— Function
local_maxima!(output, image, [maxtree]; connectivity=1) -> output
Находит локальные максимумы изображения image
и сохраняет результат в output
. Подробное описание метода см. в разделе, посвященном функции local_maxima
.
#
ImageMorphology.local_maxima
— Function
local_maxima(image, [maxtree]; connectivity=1) -> Array
Находит и маркирует все локальные максимумы изображения image
.
Подробные сведения
Локальный максимум определяется как связанное множество пикселей с одинаковым значением, большим чем значения всех пикселей, смежных со множеством.
Технически реализация основана на представлении изображения в виде дерева максимумов. Эта функция полезна, если дерево максимумов уже вычислено; в противном случае эффективнее будет функция ImageFiltering.findlocalmaxima
.
Аргументы
-
image::GenericGrayImage
: -мерное входное изображение. -
connectivity::Integer=1
: смежная связь. Максимальное количество ортогональных шагов для достижения смежного элемента пикселя. В двухмерном случае равно 1 для связи с 4 смежными элементами и 2 для связи с 8 смежными элементами. -
maxtree::MaxTree
: необязательное предварительно построенное дерево максимумов. Учтите, что необязательные параметрыmaxtree
иconnectivity
являются взаимоисключающими.
Возвращаемые значения
Целочисленный массив той же формы, что и image
. Пиксели, не являющиеся локальными максимумами, имеют значение 0. Пиксели, относящиеся к одному локальному максимуму, имеют одинаковое положительное значение (идентификатор локального максимума).
Дополнительные материалы
MaxTree
, local_maxima!
, local_minima
, ImageFiltering.findlocalmaxima
Примеры
Создание f
(квадратичная функция с максимумом в центре и еще 4 константными максимумами):
julia> w = 10;
julia> f = [20 - 0.2*((x - w/2)^2 + (y-w/2)^2) for x in 0:w, y in 0:w];
julia> f[3:5, 3:5] .= 40; f[3:5, 8:10] .= 60; f[8:10, 3:5] .= 80; f[8:10, 8:10] .= 100;
julia> f_maxima = local_maxima(f); # Получаем все локальные максимумы `f`
Итоговое изображение содержит 4 маркированных локальных максимума.
#
ImageMorphology.local_minima!
— Function
local_minima!(output, image, [maxtree]; connectivity=1) -> output
Находит локальные минимумы изображения image
и сохраняет результат в output
. Подробное описание метода см. в разделе, посвященном функции local_minima
.
#
ImageMorphology.local_minima
— Function
local_minima(image, [maxtree]; connectivity=1) -> Array
Находит и маркирует все локальные минимумы изображения image
.
Подробные сведения
Локальный минимум определяется как связанное множество пикселей с одинаковым значением, меньшим чем значения всех пикселей, смежных со множеством.
Технически реализация основана на представлении изображения в виде дерева максимумов. Эта функция полезна, если дерево максимумов уже вычислено; в противном случае эффективнее будет функция ImageFiltering.findlocalminima
.
Аргументы
-
image::GenericGrayImage
: -мерное входное изображение. -
connectivity::Integer=1
: смежная связь. Максимальное количество ортогональных шагов для достижения смежного элемента пикселя. В двухмерном случае равно 1 для связи с 4 смежными элементами и 2 для связи с 8 смежными элементами. -
maxtree::MaxTree
: необязательное предварительно построенное дерево максимумов. Учтите, что необязательные параметрыmaxtree
иconnectivity
являются взаимоисключающими.
Возвращаемые значения
Целочисленный массив той же формы, что и image
. Пиксели, не являющиеся локальными минимумами, имеют значение 0. Пиксели, относящиеся к одному локальному минимуму, имеют одинаковое положительное значение (идентификатор локального минимума).
Дополнительные материалы
MaxTree
, local_minima!
, local_maxima
, ImageFiltering.findlocalminima
Примеры
Создание f
(квадратичная функция с минимумом в центре и еще 4 константными минимумами):
julia> w = 10;
julia> f = [180 + 0.2*((x - w/2)^2 + (y-w/2)^2) for x in 0:w, y in 0:w];
julia> f[3:5, 3:5] .= 40; f[3:5, 8:10] .= 60; f[8:10, 3:5] .= 80; f[8:10, 8:10] .= 100;
julia> f_minima = local_minima(f); # Вычисляем все локальные минимумы `f`
Итоговое изображение содержит маркированные локальные минимумы.
#
ImageMorphology.rebuild!
— Function
rebuild!(maxtree::MaxTree, image::GenericGrayImage,
neighbors::AbstractVector{CartesianIndex}) -> maxtree
Повторно строит maxtree
для image
с использованием neighbors
в качестве спецификации связи пикселей.
Подробные сведения
Пиксели в связанных компонентах, создаваемых методом, должны быть связаны друг с другом через соседние пиксели. Пиксели и являются соседними, если массив neighbors
содержит такое, что .
Дополнительные материалы
#
ImageMorphology.filter_components!
— Function
filter_components!(output::GenericGrayImage, image::GenericGrayImage,
maxtree::MaxTree, attrs::AbstractVector,
min_attr, all_below_min) -> output
Фильтрует связанные компоненты image
и сохраняет результат в output
.
— это копия за исключением связанных компонентов, значение атрибута которых менее min_attr
. То есть пиксели исключаемого компонента сбрасываются в значение базисного пикселя его первого допустимого предка (связанного компонента со значением атрибута не менее min_attr
).
Аргументы
-
maxtree::MaxTree
: предварительно построенное представлениеimage
в виде дерева максимумов -
attrs::AbstractVector
:attrs[i]
— это значение атрибута для -го компонента дерева (где — линейный индекс его первого базисного пикселя) -
all_below_min
: значение, которым заполняетсяoutput
, если все атрибуты всех компонентов (включая корневой) меньшеmin_attr
Подробные сведения
Эта функция является основой для area_opening
, diameter_opening
и аналогичных преобразований. Например, для area_opening
атрибутом является площадь компонентов. В этом случае компоненты дерева максимумов output
имеют площадь не менее min_attr
пикселей.
Метод предполагает, что значения атрибута монотонны относительно иерархии компонентов, то есть <= attrs[maxtree.parentindices[i]]] для каждого i
.
Преобразование признаков
#
ImageMorphology.FeatureTransform.feature_transform
— Function
feature_transform(img::AbstractArray{Bool, N};
weights=nothing, nthreads=Threads.nthreads()) -> F
Вычисляет преобразование признаков для двоичного изображения I
, находя «ближайший» признак (позиции, где I
имеет значение true
) для каждой позиции в I
. В частности, F[i]
— это объект CartesianIndex
, кодирующий ближайшую к i
позицию, для которой I[F[i]]
имеет значение true
. В случае если два или более признаков в I
находятся на одинаковом расстоянии от i
, один из них выбирается произвольным образом. Если в I
нет значений true
, все позиции сопоставляются с индексом, каждая координата которого равна typemin(Int)
.
При необходимости можно указать вес w
для каждой координаты. Например, если I
соответствует изображению с анизотропными вокселами, весом w
может быть интервал между вокселами по каждой координатной оси. Значение по умолчанию nothing
эквивалентно w=(1,1,...)
.
См. также описание функции distance_transform
.
Цитирование
-
[1] Maurer, Calvin R., Rensheng Qi, and Vijay Raghavan. A linear time algorithm for computing exact Euclidean distance transforms of binary images in arbitrary dimensions. IEEE Transactions on Pattern Analysis and Machine Intelligence 25.2 (2003): 265—270.
#
ImageMorphology.FeatureTransform.distance_transform
— Function
distance_transform(F::AbstractArray{CartesianIndex}, [w=nothing]) -> D
Вычисляет преобразование расстояний для F
, где каждый элемент F[i]
представляет местоположение «цели» или «признака», присвоенное i
. В частности, D[i]
— это расстояние между i
и F[i]
. При необходимости можно указать вес w
для каждой координаты. Значение по умолчанию nothing
эквивалентно w=(1,1,...)
.
См. также описание функции feature_transform
.
#
ImageMorphology.clearborder
— Function
cleared_img = clearborder(img)
cleared_img = clearborder(img, width)
cleared_img = clearborder(img, width, background)
Возвращает копию исходного изображения после очистки объектов, связанных с его границей. Параметры:
-
img = входное изображение (двоичное или в оттенках серого)
-
width = ширина анализируемой границы (значение по умолчанию: 1)
-
background = значение, которое присваивается очищаемым пикселями или элементам (по умолчанию 0)
Прочее
#
ImageMorphology.convexhull
— Function
chull = convexhull(img)
Вычисляет выпуклую оболочку двоичного изображения и возвращает ее вершины в виде массива элементов типа CartesianIndex.
#
ImageMorphology.isboundary
— Function
isboundary(img::AbstractArray; background = 0, dims = coords_spatial(A), kwargs...)
Находит границы внутри каждого объекта. background
— это скалярное значение фоновых пикселей, которые не будут помечаться как границы. Именованные аргументы передаются в extremefilt!
, включая аргумент dims
с измерениями, по которым должны определяться границы.
Существует также выполняемая на месте версия isboundary!
и альтернативная версия, которая находит толстые границы, isboundary_thick
.
Примеры
DocTestSetup = quote import ImageMorphology: isboundary end
julia> A = zeros(Int64, 16, 16); A[4:8, 4:8] .= 5; A[4:8, 9:12] .= 6; A[10:12,13:15] .= 3; A[10:12,3:6] .= 9; A
16×16 Matrix{Int64}:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 9 9 9 9 0 0 0 0 0 0 3 3 3 0
0 0 9 9 9 9 0 0 0 0 0 0 3 3 3 0
0 0 9 9 9 9 0 0 0 0 0 0 3 3 3 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary(A)
16×16 Matrix{Int64}:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary(A .!= 0)
16×16 BitMatrix:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary(A .!= 0; dims = 1)
16×16 BitMatrix:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary(A .!= 0; dims = 2)
16×16 BitMatrix:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 1 0 0 0 0 0 0 0 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
#
ImageMorphology.isboundary!
— Function
isboundary!(img::AbstractArray; background = 0, dims = coords_spatial(A), kwargs...)
Находит границы внутри каждого объекта и заменяет исходное изображение. background
— это скалярное значение фоновых пикселей, которые не будут помечаться как границы. Именованные аргументы передаются в extreme_filter
, включая аргумент dims
с измерениями, по которым должны определяться границы.
Примеры см. в описании версии isboundary
, выполняемой не на месте.
#
ImageMorphology.isboundary_thick
— Function
isboundary_thick(img::AbstractArray; dims = coords_spatial(img), kwargs...)
Находит толстые границы, которые находятся сразу вне объектов и внутри них. Результатом является объединение внутренних и внешних границ. Именованный аргумент dims
указывает измерения, по которым ищутся границы. Этот аргумент dims
и дополнительные именованные аргументы kwargs
передаются в extreme_filter
.
См. также описание функции isboundary
, которая возвращает только внутренние границы.
Примеры
DocTestSetup = quote import ImageMorphology: isboundary_thick end
julia> A = zeros(Int64, 16, 16); A[4:8, 4:8] .= 5; A[4:8, 9:12] .= 6; A[10:12,13:15] .= 3; A[10:12,3:6] .= 9; A
16×16 Matrix{Int64}:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 5 5 5 5 5 6 6 6 6 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 9 9 9 9 0 0 0 0 0 0 3 3 3 0
0 0 9 9 9 9 0 0 0 0 0 0 3 3 3 0
0 0 9 9 9 9 0 0 0 0 0 0 3 3 3 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary_thick(A)
16×16 BitMatrix:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0
0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0
0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0
0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0
0 0 1 1 0 0 0 1 1 0 0 1 1 0 0 0
0 0 1 1 1 1 1 1 1 1 1 1 1 0 0 0
0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1
0 1 1 0 0 1 1 0 0 0 0 1 1 0 1 1
0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1
0 1 1 1 1 1 1 0 0 0 0 1 1 1 1 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary_thick(A) .& (A .!= 0)
16×16 BitMatrix:
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 1 0 0 0 1 1 0 0 1 0 0 0 0
0 0 0 1 1 1 1 1 1 1 1 1 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0
0 0 1 1 1 1 0 0 0 0 0 0 1 1 1 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
julia> isboundary_thick(A) == isboundary(A; background = -1)
true
julia> isboundary_thick(A) .& (A .!= 0) == isboundary(A) # внутренние границы
true
julia> isboundary_thick(A .!= 0) .& (A .== 0) == isboundary(A .== 0) # внешние границы
true