Skip to content

Commit

Permalink
Merge pull request #661 from juliohm/image-morphology
Browse files Browse the repository at this point in the history
Add ImageMorphology as a dependency
  • Loading branch information
timholy authored Aug 14, 2017
2 parents 7c8a791 + 66f8653 commit 23358eb
Show file tree
Hide file tree
Showing 3 changed files with 3 additions and 103 deletions.
1 change: 1 addition & 0 deletions REQUIRE
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ FixedPointNumbers 0.3.0
ImageCore
ImageTransformations 0.2.2
ImageFiltering
ImageMorphology
AxisArrays
ImageAxes
ImageMetadata
Expand Down
1 change: 1 addition & 0 deletions src/Images.jl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ const is_little_endian = ENDIAN_BOM == 0x04030201
@reexport using ImageAxes
@reexport using ImageMetadata
@reexport using ImageFiltering
@reexport using ImageMorphology

import ImageTransformations: restrict
using ImageMetadata: ImageMetaAxis
Expand Down
104 changes: 1 addition & 103 deletions src/algorithms.jl
Original file line number Diff line number Diff line change
Expand Up @@ -607,109 +607,7 @@ function imROF(img::AbstractArray, lambda::Number, iterations::Integer)
end


### Morphological operations

# Erode and dilate support 3x3 regions only (and higher-dimensional generalizations).
"""
```
imgd = dilate(img, [region])
```
perform a max-filter over nearest-neighbors. The
default is 8-connectivity in 2d, 27-connectivity in 3d, etc. You can specify the
list of dimensions that you want to include in the connectivity, e.g., `region =
[1,2]` would exclude the third dimension from filtering.
"""
dilate(img::ImageMeta, region=coords_spatial(img)) = shareproperties(img, dilate!(copy(data(img)), region))
"""
```
imge = erode(img, [region])
```
perform a min-filter over nearest-neighbors. The
default is 8-connectivity in 2d, 27-connectivity in 3d, etc. You can specify the
list of dimensions that you want to include in the connectivity, e.g., `region =
[1,2]` would exclude the third dimension from filtering.
"""
erode(img::ImageMeta, region=coords_spatial(img)) = shareproperties(img, erode!(copy(data(img)), region))
dilate(img::AbstractArray, region=coords_spatial(img)) = dilate!(copy(img), region)
erode(img::AbstractArray, region=coords_spatial(img)) = erode!(copy(img), region)

dilate!(maxfilt, region=coords_spatial(maxfilt)) = extremefilt!(maxfilt, max, region)
erode!(minfilt, region=coords_spatial(minfilt)) = extremefilt!(minfilt, min, region)
function extremefilt!(A::AbstractArray, select::Function, region=coords_spatial(A))
inds = indices(A)
for d = 1:ndims(A)
if size(A, d) == 1 || !in(d, region)
continue
end
Rpre = CartesianRange(inds[1:d-1])
Rpost = CartesianRange(inds[d+1:end])
_extremefilt!(A, select, Rpre, inds[d], Rpost)
end
A
end

@noinline function _extremefilt!(A, select, Rpre, inds, Rpost)
# TODO: improve the cache efficiency
for Ipost in Rpost, Ipre in Rpre
# first element along dim
i1 = first(inds)
a2, a3 = A[Ipre, i1, Ipost], A[Ipre, i1+1, Ipost]
A[Ipre, i1, Ipost] = select(a2, a3)
# interior along dim
for i = i1+2:last(inds)
a1, a2 = a2, a3
a3 = A[Ipre, i, Ipost]
A[Ipre, i-1, Ipost] = select(select(a1, a2), a3)
end
# last element along dim
A[Ipre, last(inds), Ipost] = select(a2, a3)
end
A
end

"""
`imgo = opening(img, [region])` performs the `opening` morphology operation, equivalent to `dilate(erode(img))`.
`region` allows you to control the dimensions over which this operation is performed.
"""
opening(img::AbstractArray, region=coords_spatial(img)) = opening!(copy(img), region)
opening!(img::AbstractArray, region=coords_spatial(img)) = dilate!(erode!(img, region),region)

"""
`imgc = closing(img, [region])` performs the `closing` morphology operation, equivalent to `erode(dilate(img))`.
`region` allows you to control the dimensions over which this operation is performed.
"""
closing(img::AbstractArray, region=coords_spatial(img)) = closing!(copy(img), region)
closing!(img::AbstractArray, region=coords_spatial(img)) = erode!(dilate!(img, region),region)

"""
`imgth = tophat(img, [region])` performs `top hat` of an image,
which is defined as the image minus its morphological opening.
`region` allows you to control the dimensions over which this operation is performed.
"""
tophat(img::AbstractArray, region=coords_spatial(img)) = img - opening(img, region)

"""
`imgbh = bothat(img, [region])` performs `bottom hat` of an image,
which is defined as its morphological closing minus the original image.
`region` allows you to control the dimensions over which this operation is performed.
"""
bothat(img::AbstractArray, region=coords_spatial(img)) = closing(img, region) - img

"""
`imgmg = morphogradient(img, [region])` returns morphological gradient of the image,
which is the difference between the dilation and the erosion of a given image.
`region` allows you to control the dimensions over which this operation is performed.
"""
morphogradient(img::AbstractArray, region=coords_spatial(img)) = dilate(img, region) - erode(img, region)

"""
`imgml = morpholaplace(img, [region])` performs `Morphological Laplacian` of an image,
which is defined as the arithmetic difference between the internal and the external gradient.
`region` allows you to control the dimensions over which this operation is performed.
"""
morpholaplace(img::AbstractArray, region=coords_spatial(img)) = dilate(img, region) + erode(img, region) - 2img
# what are these `extr` functions? TODO: documentation

extr(order::ForwardOrdering, x::Real, y::Real) = max(x,y)
extr(order::ForwardOrdering, x::Real, y::Real, z::Real) = max(x,y,z)
Expand Down

0 comments on commit 23358eb

Please sign in to comment.