Skip to content

Adds build_histogram(Equalization(),...)#761

Closed
zygmuntszpak wants to merge 1 commit intoJuliaImages:masterfrom
zygmuntszpak:master
Closed

Adds build_histogram(Equalization(),...)#761
zygmuntszpak wants to merge 1 commit intoJuliaImages:masterfrom
zygmuntszpak:master

Conversation

@zygmuntszpak
Copy link
Copy Markdown
Member

Removed the dependence on searchsortedlast from build_histogram to improve the performance of histogram construction. Added a fresh implementation of histogram equalization which does not require _histeq_pixel_rescale.

Removed the dependence on `searchsortedlast` from `build_histogram` to improve the performance of histogram construction. Added a fresh implementation of histogram equalization which  does not require `_histeq_pixel_rescale`.
Comment thread src/exposure.jl
end

function transform_density!(img::AbstractArray,edges::AbstractArray, histogram::AbstractArray, cdf::AbstractArray)
o = Base.Order.Forward
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Forgot to remove this.

@codecov
Copy link
Copy Markdown

codecov bot commented Oct 24, 2018

Codecov Report

Merging #761 into master will decrease coverage by 0.05%.
The diff coverage is 95.23%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #761      +/-   ##
==========================================
- Coverage   95.85%   95.79%   -0.06%     
==========================================
  Files          10       10              
  Lines         699      714      +15     
==========================================
+ Hits          670      684      +14     
- Misses         29       30       +1
Impacted Files Coverage Δ
src/Images.jl 100% <ø> (ø) ⬆️
src/exposure.jl 99.4% <95.23%> (-0.6%) ⬇️

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 3e28699...5fdca27. Read the comment docs.

Comment thread src/exposure.jl
function adjust_histogram(operation::Equalization, img::AbstractArray{T}, nbins::Integer, minval::RealLike = 0, maxval::RealLike = 1) where {T<:AbstractRGB}
yiq = convert.(YIQ, img)
yiq_view = channelview(yiq)
yeq = adjust_histogram!(Equalization(),view(yiq_view,1,:,:),nbins,minval,maxval)
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Don't need to declare yeq since adjust_histogram! modifies its argument. I forgot to remove the yeq after refactoring my initial implementation.

@zygmuntszpak zygmuntszpak requested a review from timholy October 25, 2018 00:48
Copy link
Copy Markdown
Member

@timholy timholy left a comment

Choose a reason for hiding this comment

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

This looks lovely, many thanks for doing this.

Comment thread src/exposure.jl
lb = first(axes(edges,1))-1
ub = last(axes(edges,1))
first_edge = first(edges)
step_size = edges.step.hi
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This seems to assume a TwicePrecision element. But I can construct an AbstractRange as 0:11 or StepRangeLen(0.0, 0.1, 11).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Thanks. I think I've handled the general case in the new version of the code.

Comment thread src/exposure.jl
"""
function adjust_histogram(operation::Equalization, img::AbstractArray{T}, nbins::Integer, minval::RealLike = 0, maxval::RealLike = 1) where {T<:AbstractRGB}
yiq = convert.(YIQ, img)
yiq_view = channelview(yiq)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Better would be something like y = map(c->YIQ(c).y, img) (untested).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I actually need not only the y value, but also the i and q values since I need to reconstruct the original colour image. That's why I convert to YIQ and pass the Y as a view to be equalised.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Good. But wouldn't it still be better to access the fields you want directly rather than using channelview? To me the meaning of A[i,j].y seems much more evident than A[1,i,j].

Comment thread src/exposure.jl
See also: [histmatch](@ref),[clahe](@ref), [build_histogram](@ref) and [adjust_gamma](@ref).

"""
function adjust_histogram(operation::Equalization, img::AbstractArray{T}, nbins::Integer, minval::RealLike = 0, maxval::RealLike = 1) where {T<:AbstractRGB}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Does it have to be AbstractRGB or does any Color3 suffice?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Color3 is what we want. I occasionally have trouble determining what the most abstract types are---sorry.

Comment thread src/exposure.jl
end

function build_histogram(img::AbstractArray, edges::AbstractRange)
Base.has_offset_axes(edges) && throw(ArgumentError("edges must be indexed starting with 1"))
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Seems generic so not sure this is necessary (but I have no objection to including it, either).

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's not quite generic yet. The manner in which I calculate the index currently still assumes that edges start from 1.

Comment thread src/exposure.jl
map!(img,img) do val
if val >= edges[end]
newval = cdf[end]
else
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

do you need to check val < first(edges) here too?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Yes I do :D.

Comment thread test/exposure.jl
else
edges, counts = build_histogram(0:1/255:1,4,128/255,192/255)
img = collect(0:1/255:1)
edges, counts = build_histogram(T.(img),4,128/255,192/255)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just curious, what's the reason for this change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I wanted to convert the img to all the different types T that we loop over in the outer loop. That was my original intention but I had forgotten to actually convert the img to type T in the previous commit.

Comment thread src/exposure.jl
```

Returns a histogram equalised image with a granularity of approximately `nbins`
number of bins.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Can you remind me the reason for the "approximately"?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is a copy/paste mistake. I copied the description from imhist. I recently added the word approximately to imhist because imhist doesn't guarantee that the number of bins that the user specifies actually are utilised in the construction of the histogram. Thanks for spotting this---I've fixed it in the latest version.

@zygmuntszpak
Copy link
Copy Markdown
Member Author

@timholy I got myself a bit tangled with my branching. I've made a new pull-request which updates this work. This pull-requested listed here was from the master branch of my fork. The new pull-request was from a branch I created for this work. Sorry for the confusion. We should probably close this pull-request and move the conversation to the other one.

@timholy
Copy link
Copy Markdown
Member

timholy commented Oct 26, 2018

No problem about the new branch, I know how it goes. I will close this but note some responses above.

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