deprecate otsu_threshold and yen_threshold#897
Conversation
| # delete in Images v1.0.0 | ||
| @deprecate otsu_threshold(img, bins=256) begin | ||
| edges, counts = ImageContrastAdjustment.build_histogram(img, bins) | ||
| eltype(img)(HistogramThresholding.find_threshold(Otsu(), counts[1:end], edges)) |
There was a problem hiding this comment.
This difference raises a decision to be made: should we make the result of find_threshold always be eltype(img) type?
I feel it would be relatively good to restrict it as raw numbers (the status quo of HistogramThresholding) since it would always be a scalar in practice; there's no need to display it.
There was a problem hiding this comment.
Is this a step backwards in usability? Could we create a version of find_threshold that takes the image as an input?
There was a problem hiding this comment.
In #841 we aim to introduce ImageBinarization to Images, which means a user will be able to pass an image, choose Otsu as the thresholding algorithm, and obtain the binary image as a result.
The HistogramThresholding does the actual thresholding selection, and operates at the level of histograms so that one can use these algorithms outside the context of image processing.
The find_threshold methods takes an AbstractArray which it interprets as a histogram. If we want to make it work at the level of an images, do we just add another method which dispatches if the eltype of the array is a subtype of Gray?
There was a problem hiding this comment.
I hadn't looked at the find_threshold implementation, don't all the implementations in https://github.com/zygmuntszpak/HistogramThresholding.jl require two one-dimensional arrays (the counts and edges arrays)? In which case, wouldn't passing a single array be unambiguous? If not, then we should consider keyword variant, e.g. find_threshold(Otsu(), image=img). It's better to avoid dispatching on eltype wherever possible, as it decreases the generality of the code. We're expunging some of that code in ImageCore now: JuliaImages/ImageCore.jl#131. (It's fine for dispatching to optimized implementations, but changing behavior based on eltype should be considered carefully.)
Let me be clear that I think the new implementations are huge improvements from the standpoint of code organization and design. My only concern is that they have a tendency to lean towards the reduce(+, a) and away from sum(a) territory, and we need to be aware that some users will view this as an increased cognitive load even though others will appreciate the generality. I am not sure how to solve it, and maybe I am just reacting to the visual appearance of a single function call being converted into something substantially larger.
There was a problem hiding this comment.
At the moment they all take an AbstractArray as input, so if I understood you correctly I just need to refactor those functions so that they take an AbstractVector as input instead. Then the images ecosystem can define an AbstractArray dispatch which builds the necessary histogram. The user can then just type find_threshold(img, Otsu()), for example.
There was a problem hiding this comment.
Most of JuliaImages supports 1d images---these are sometimes useful for debugging and algorithm development. So giving different meaning to different array dimensionalities isn't ideal.
But I'm still confused:
julia> methods(HistogramThresholding.find_threshold)
# 10 methods for generic function "find_threshold":
[1] find_threshold(algorithm::Otsu, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/otsu.jl:93
[2] find_threshold(algorithm::MinimumError, histogram::AbstractArray{T,N} where N, edges::AbstractRange) where T<:Int64 in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/minimum_error.jl:112
[3] find_threshold(algorithm::MinimumError, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/minimum_error.jl:85
[4] find_threshold(algorithm::UnimodalRosin, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/unimodal.jl:71
[5] find_threshold(algorithm::Moments, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/moments.jl:90
[6] find_threshold(algorithm::MinimumIntermodes, histogram::AbstractArray, edges::AbstractRange; maxiter) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/minimum.jl:63
[7] find_threshold(algorithm::Intermodes, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/intermodes.jl:63
[8] find_threshold(algorithm::Balanced, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/balancedthreshold.jl:87
[9] find_threshold(algorithm::Yen, histogram::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/yen.jl:85
[10] find_threshold(algorithm::Entropy, counts::AbstractArray, edges::AbstractRange) in HistogramThresholding at /home/tim/.julia/packages/HistogramThresholding/2ZlJN/src/entropy_thresholding.jl:91Unless I'm just overlooking something, all 10 of these require edges. If you pass in the image, will you also pass in edges? Or I should say, I guess that will be an option? The interface I'm proposing is to support
find_threshold(Otsu(), img; nbins=256)That only has one input array, which can safely be interpreted as the image.
There was a problem hiding this comment.
I guess this usage is inspired by MATLAB's otsuthresh?
% matlab
[counts,x] = imhist(I,16);
T = otsuthresh(counts);
BW = imbinarize(I,T);I also think find_threshold(img, Otsu()) would be more convenient, though.
Codecov Report
@@ Coverage Diff @@
## master #897 +/- ##
==========================================
- Coverage 76.38% 75.88% -0.51%
==========================================
Files 9 9
Lines 720 705 -15
==========================================
- Hits 550 535 -15
Misses 170 170
Continue to review full report at Codecov.
|
|
I approve of the goal here. |
|
Closed by #1030. |
closes #886
Blocking:
cc: @zygmuntszpak