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

refactor Balanced using the functor API #32

Merged
merged 4 commits into from
Jul 26, 2019
Merged

refactor Balanced using the functor API #32

merged 4 commits into from
Jul 26, 2019

Conversation

johnnychen94
Copy link
Member

@johnnychen94 johnnychen94 commented Jul 25, 2019

This is a PR-commit for PR #29 that refactors the whole codebase to use the new functor API, which
is discussed in more details in #26 and explained in my GSoC 2019 blog

Changes:

  • support Color3 input
  • move implementations into functor
  • enhance the test codes with wider test coverage

This is a PR-commit for PR
#29
that refactors the whole codebase to use the new functor API, which
is discussed in more details in
#26
and explained in my GSoC 2019 blog
https://nextjournal.com/johnnychen94/the-principles-of-imagesjl-part-i

Changes:

* move implementations into functor
* enhance the test codes with wider test coverage
@codecov
Copy link

codecov bot commented Jul 25, 2019

Codecov Report

❗ No coverage uploaded for pull request base (api@2951a80). Click here to learn what that means.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff           @@
##             api      #32   +/-   ##
======================================
  Coverage       ?   41.27%           
======================================
  Files          ?       20           
  Lines          ?      172           
  Branches       ?        0           
======================================
  Hits           ?       71           
  Misses         ?      101           
  Partials       ?        0
Impacted Files Coverage Δ
src/balanced.jl 100% <100%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 2951a80...36c8f13. Read the comment docs.

end

(f::Balanced)(out::GenericGrayImage, img::AbstractArray{<:Color3}) =
f(out, of_eltype(Gray, img))
Copy link
Member Author

@johnnychen94 johnnychen94 Jul 25, 2019

Choose a reason for hiding this comment

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

If remove this, the test would fail on RGB images. Looks like build_histogram doesn't support Color3 images yet? @zygmuntszpak

diff --git a/src/balanced.jl b/src/balanced.jl
index a72291b..52a6ba9 100644
--- a/src/balanced.jl
+++ b/src/balanced.jl
@@ -80,7 +80,8 @@ img_binary = binarize(Balanced(), img)
 """
 struct Balanced <: AbstractImageBinarizationAlgorithm end

-function (f::Balanced)(out::GenericGrayImage, img::GenericGrayImage)
+function (f::Balanced)(out::GenericGrayImage,
+                       img::AbstractArray{T, 2}) where T<:Union{Number, Colorant}
     edges, counts = build_histogram(img,  256)
     t = find_threshold(HistogramThresholding.Balanced(), counts[1:end], edges)
     for i in CartesianIndices(img)
@@ -88,6 +89,3 @@ function (f::Balanced)(out::GenericGrayImage, img::GenericGrayImage)
     end
     out
 end
-
-(f::Balanced)(out::GenericGrayImage, img::AbstractArray{<:Color3}) =
-    f(out, of_eltype(Gray, img))
The error message
Types: Error During Test at /home/jc/Documents/Julia/ImageBinarization.jl/test/balanced.jl:35
  Got exception outside of a @test
  TypeError: in keyword argument minval, expected Union{Real, Color{T,1} where T}, got RGB{Float32}
  Stacktrace:
   [1] (::getfield(ImageContrastAdjustment, Symbol("#kw##build_histogram")))(::NamedTuple{(:minval, :maxval),Tuple{RGB{Float32},RGB{Float32}}}, ::typeof(ImageContrastAdjustment.build_histogram), ::Array{RGB{Float32},2}, ::Int64) at ./none:0
   [2] build_histogram(::Array{RGB{Float32},2}, ::Int64) at /home/jc/.julia/packages/ImageContrastAdjustment/RY6r2/src/contrastadjustment.jl:150
   [3] (::Balanced)(::Array{Gray{Float32},2}, ::Array{RGB{Float32},2}) at /home/jc/Documents/Julia/ImageBinarization.jl/src/balanced.jl:85
   [4] #binarize!#1(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Array{Gray{Float32},2}, ::Array{RGB{Float32},2}, ::Balanced) at /home/jc/Documents/Julia/ImageBinarization.jl/src/BinarizationAPI/binarize.jl:24
   [5] binarize!(::Array{Gray{Float32},2}, ::Array{RGB{Float32},2}, ::Balanced) at /home/jc/Documents/Julia/ImageBinarization.jl/src/BinarizationAPI/binarize.jl:24
   [6] #binarize#3(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Type{Gray{Float32}}, ::Array{RGB{Float32},2}, ::Balanced) at /home/jc/Documents/Julia/ImageBinarization.jl/src/BinarizationAPI/binarize.jl:41
   [7] binarize(::Type{Gray{Float32}}, ::Array{RGB{Float32},2}, ::Balanced) at /home/jc/Documents/Julia/ImageBinarization.jl/src/BinarizationAPI/binarize.jl:40
   [8] #binarize#4(::Base.Iterators.Pairs{Union{},Union{},Tuple{},NamedTuple{(),Tuple{}}}, ::Function, ::Array{RGB{Float32},2}, ::Balanced) at /home/jc/Documents/Julia/ImageBinarization.jl/src/BinarizationAPI/binarize.jl:47
   [9] binarize(::Array{RGB{Float32},2}, ::Balanced) at /home/jc/Documents/Julia/ImageBinarization.jl/src/BinarizationAPI/binarize.jl:47
   [10] top-level scope at /home/jc/Documents/Julia/ImageBinarization.jl/test/balanced.jl:53
   [11] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Test/src/Test.jl:1083
   [12] top-level scope at /home/jc/Documents/Julia/ImageBinarization.jl/test/balanced.jl:37
   [13] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Test/src/Test.jl:1083
   [14] top-level scope at /home/jc/Documents/Julia/ImageBinarization.jl/test/balanced.jl:2
   [15] include at ./boot.jl:326 [inlined]
   [16] include_relative(::Module, ::String) at ./loading.jl:1038
   [17] include(::Module, ::String) at ./sysimg.jl:29
   [18] include(::String) at ./client.jl:403
   [19] top-level scope at /home/jc/Documents/Julia/ImageBinarization.jl/test/runtests.jl:13
   [20] top-level scope at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/Test/src/Test.jl:1083
   [21] top-level scope at /home/jc/Documents/Julia/ImageBinarization.jl/test/runtests.jl:10
   [22] include at ./boot.jl:326 [inlined]
   [23] include_relative(::Module, ::String) at ./loading.jl:1038
   [24] include(::Module, ::String) at ./sysimg.jl:29
   [25] include(::String) at ./client.jl:403
   [26] top-level scope at none:0
   [27] eval at ./boot.jl:328 [inlined]
   [28] repleval(::Module, ::Expr) at /home/jc/.julia/packages/Atom/BXRAC/src/repl.jl:135
   [29] (::getfield(Atom, Symbol("##168#170")){Module})() at /home/jc/.julia/packages/Atom/BXRAC/src/repl.jl:157
   [30] with_logstate(::getfield(Atom, Symbol("##168#170")){Module}, ::Base.CoreLogging.LogState) at ./logging.jl:395
   [31] with_logger at ./logging.jl:491 [inlined]
   [32] evalrepl(::Module, ::String) at /home/jc/.julia/packages/Atom/BXRAC/src/repl.jl:148
   [33] top-level scope at /home/jc/.julia/packages/Atom/BXRAC/src/repl.jl:190
   [34] eval(::Module, ::Any) at ./boot.jl:328
   [35] eval_user_input(::Any, ::REPL.REPLBackend) at /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.1/REPL/src/REPL.jl:85
   [36] run_backend(::REPL.REPLBackend) at /home/jc/.julia/packages/Revise/agmgx/src/Revise.jl:949
   [37] (::getfield(Revise, Symbol("##75#77")){REPL.REPLBackend})() at ./task.jl:259

Copy link
Member

Choose a reason for hiding this comment

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

Currently the build_histogram method converts an image to a single channel (Gray) before it computes the histogram. If one wants to compute the histogram for an RGB image one would need to call build_histogram for each channel separately.

It looks like I forgot to make sure that the image is converted to Grayscale when the user specifies the minval option. For example, I currently have

function build_histogram(img::AbstractArray, nbins::Integer = 256)
    build_histogram(img, nbins, minval =  minfinite(img), maxval = maxfinite(img))
end

function build_histogram(img::AbstractArray{T}, edges::AbstractRange) where {T<:Color3}
    build_histogram(Gray.(img),edges)
end

I forgot to add something like

function build_histogram(img::AbstractArray, nbins::Integer = 256) where {T<:Color3}
    img_gray = Gray.(img)
    build_histogram(img_gray, nbins, minval =  minfinite(img_gray), maxval = maxfinite(img_gray))
end

@johnnychen94
Copy link
Member Author

@zygmuntszpak the test passed so we can safely merge them.

All the following PRs are created in this pattern so that you can review them easily. For non-trivial cases that worth attention, I'll add a comment to them like in this PR.

There can be some further changes on the codebase, but at least for now, I'd like to keep changes relatively small in these sequences of PRs which simply wrap the implementations in the functor.

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.

2 participants