-
Notifications
You must be signed in to change notification settings - Fork 143
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
Histogram Equalisation #458
Conversation
@bjarthur For Histogram Equalisation, I will need the maximum value for each datatype. For eg. in 8 bit Uint it would be 255 so I will have bins from 0-255 for the histogram. What is the best way to find this for all the types of Images?
Update I did not know I could use the FixedPointNumbers datatype directly. It works now. |
This was an excellent choice for a first pull request: it's a simple function, which gives you a chance to learn more about julia, Images, and the process of contributing to packages. 👍 for style. I'll comment on the details in the code. (I was preparing a response to your previous version, and I noticed you just pushed a new version that addressed some of my concerns. Good timing!) |
The histogram is calculated on the flattened image. For multi dimensional images, use the function | ||
separately on each channel to obtain a histogram for each. | ||
""" | ||
function imhist{T}(img::AbstractArray{T,2}, nbins::Integer) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a strong reason to limit this to 2d? Why couldn't I supply a 3d grayscale image?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about an RGB image? What should this do in that case?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No reason as such. I will extend it to N dims.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For an RGB Image, there can be multiple ways. We could calculate the histogram for each channel or calculate the histogram of RGB values itself.
And now for a more general comment: do we need a separate function for this? Couldn't we just call |
(Note that if you try |
Yes. I am getting this error for Gray datatype.
I'll work on the other comments and resubmit my PR. Thanks a lot! |
So, what that error means is that you might need to define a new Base.histrange{T}(A::AbstractArray{Gray{T}}, n) = ... where One of the challenges we might face is whether to only compute histograms over |
I think we can add it to ColorVectorSpace as it has many other operations defined over the various Colors. I'll open an issue there and submit a PR. I tried the |
I was going through |
Submitted PR JuliaGraphics/ColorVectorSpace.jl#33. |
PR JuliaGraphics/ColorVectorSpace.jl#35 adds zero() function for initialising cdf. |
1eaf059
to
9b1f773
Compare
Most types require The problem with Here are some considerations: For other color types, you're right that the range might need to be different. Overall it seems best to use the gamut, but I'm not always sure how you find out what that is in all cases. (It's pretty obvious in some, but in others less so.) I suppose one option is to define |
``` | ||
|
||
""" | ||
function histeq{T,N}(img::AbstractArray{T,N}, nbins::Int) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Might want histeq{T<:Union{Real,Gray},N}
to restrict to grayscale?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see, you're doing it by conversion to grayscale, so never mind. To avoid creating too many intermediaries, you might want to dispatch to two functions:
histeq{T<:Real,N}(...
# this one calls maxfinite and minfinite, and does the scaling
histeq_rescale(imgv)
end
histeq{T<:Colorant,N}(...
imgv = [convert(Gray, p) for p in img]
histeq_rescale(imgv)
end
or something.
I am getting this error sometimes if I use the julia notebook to display images returned by the
|
There is a problem with scaling the image to values between [0-1] for the histogram. If there are intensities equal to 0, the histogram function will miss out on the 0 if we use the range 0:1/nbins:1. I feel it would be better to consider the bin centres instead i.e. take the range from 1/(2nbins):1/nbins:(1+1/(2nbins)). Is there a better way to do this? |
Bin centers seem like a natural way to solve this. If you like that strategy, go for it. If you prefer edge-based, then (given your observation) I have no objection to the "code duplication" of writing your own histogram algorithm. Your observation here is convincing incentive. So I'd say choose whichever path you like better. |
colons = ntuple(d->Colon(), ndims(img)) | ||
Y = separate(YCbCr )[colons..., 1] | ||
if maxval == zero(YCbCr) | ||
eq_Y = histeq(Y, nbins, minfinite(Y), maxfinite(Y)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of minfinite and maxfinite, I'd like to take the entire range of the Y Channel possible. This depends on the type of conversion used though, so I wanted to check with you. In this it uses the range (16,235) for the Y Channel in 8 bits. Is this the correct one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Best way to check would be to look at the convert
methods for YCbCr in Colors.jl
. This could surely use documentation, if it isn't documented already.
Finally Done! It works very well with multiple types of Images and ranges. The YCbCr conversion method used is the one from wikipedia. One slight change I have made is that while calculating the corrected intensity, it takes |
Need to add some tests now. How are things like this which are very subjective and depend on the approach used usually tested? I mean, if someone were to modify the function a bit, the values returned would be different. Should I put tests to check if the return types etc are correct instead of testing the data returned? |
hist_equalised_img = histeq(img, nbins) | ||
hist_equalised_img = histeq(img, nbins, minval, maxval) | ||
``` | ||
ColorVectorSpace. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is this line for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thats crept in by mistake when I was switching between the terminal and my editor. Updating now.
Looking very good! |
@timholy I forgot about Transparent Images. Is there a way to strip the entire alpha channel of a Colorant and then rejoin it after equalisation is done? I know about the EDIT : Found I still need something for the alpha conversion though. |
Actually, in general it looks like a better pattern would be
and define separate |
In general, lots of "convert this array to that array" operations are characteristic of high-level languages that don't have good performance: it's how you "batch" work so that the (fast) underlying C code can do the real work. In julia, there's no need for that: focus on designing a good API for handling individual elements, chain all of your operations together on the elements, and then rebuild arrays as the "outermost" step. |
@timholy I've made the changes. Please Review :) |
Sorry for the long delay, the gigantic JuliaLang/julia#16260 was all-consuming. This looks good, I'm merging. At some point we should add some tests, though. |
This commit adds a histogram function to help with histogram equalisation.