Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Morphology][Tasks] introduce generic fillholes algorithm #119

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ThomasRetornaz
Copy link
Collaborator

Todos:

  • speedup binary implem

Copy link
Member

@mkitti mkitti left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the contribution. Could you look over my comments and suggestions?

# Usage:
# julia benchmark/run_benchmarks.jl
Usage:
julia benchmark/run_benchmarks.jl
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove the hashes?

@@ -24,6 +24,7 @@ include("connected.jl")
include("clearborder.jl")
include("extreme_filter.jl")
include("extremum.jl")
include("filholes.jl")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be fillholes.jl?

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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a test where the 0s at the border are not a single connected component? Also the case where there are no zeros on the border m. Also add a test for multiple interior holes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that we could say nothing for "holes" in the border, anyway we don't have acess to underlyting image domain, are these really holes
So as other image processing framework we don't fill hole touching the borders

src/filholes.jl Outdated
@@ -0,0 +1,58 @@
"""
fillhole(img; [dims])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change the name of the file to match the base of the function, please

src/filholes.jl Outdated
return _fillhole!(out, img, se)
end

function _fillhole!(out, img, se)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should consider typing the arguments here and extracting the number of dimensions and element type from the AbstractArray{T,N}.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree i could but why?
The function is generic, the speedup of binary cases could be to specialize mreconstruct for binary cases
Do you want to specialize this function at fillhole level ?


# in place
out = similar(img)
out = fillhole!(out, img)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need the left side assignment here?

@@ -130,15 +131,22 @@ export
#feature_transform.jl
feature_transform,
distance_transform,

#clearborder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments seem redundant

@@ -130,15 +131,22 @@ export
#feature_transform.jl
feature_transform,
distance_transform,

#clearborder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#clearborder

clearborder,

#fillhole
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#fillhole

src/filholes.jl Outdated
end

function fillhole!(out, img, se)
return _fillhole!(out, img, se)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need the underscore prefix? Could we combine the function below and this one to a single signature?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The prefix correspon to the most internal call, you will see this pattern in the whole project, something like "private" implem
But yes you're right in this special case its not relevant

* fix naming
* add more tests
Copy link
Member

@johnnychen94 johnnychen94 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know the algorithm details, but how the codes are written is exactly what I would do by myself. The approval is for this.

Extensive test cases are appreciated -- I always believe that tests are the only final guards for long-term correctness.

outerrange = CartesianIndices(map(i -> 1:i, dimensions))
innerrange = CartesianIndices(map(i -> (1 + 1):(i - 1), dimensions))
for i in EdgeIterator(outerrange, innerrange)
tmp[i] = 0
Copy link
Member

@johnnychen94 johnnychen94 Feb 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For generic programming: tmp[i] = zero(T) where I assume T = eltype(img)

The difference is very small but noteworthy:

  • tmp[i] = 0 would be valid if there's a conversion from 0 (Int) to eltype(tmp)
  • tmp[i] = zero(T) would be valid as long as zero(T) is defined (which is true for almost all number-like types)

Why we should prefer the zero(T) version is that: not all types (should) support (implicit) conversion from Int. The following is an JuliaImages example, but you can quickly come up with many like it:

julia> using ImageCore

julia> zero(HSV)
HSV{Float32}(0.0f0,0.0f0,0.0f0)

julia> HSV(0)
ERROR: in ccolor, no automatic conversion from Int64 and HSV
Stacktrace:
 [1] ccolor(#unused#::Type{HSV}, #unused#::Type{Int64})
   @ ColorTypes ~/.julia/packages/ColorTypes/1dGw6/src/traits.jl:410
 [2] convert(#unused#::Type{HSV}, c::Int64)
   @ ColorTypes ~/.julia/packages/ColorTypes/1dGw6/src/conversions.jl:74
 [3] HSV(x::Int64)
   @ ColorTypes ~/.julia/packages/ColorTypes/1dGw6/src/types.jl:464
 [4] top-level scope
   @ REPL[3]:1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants