I have an image I which pixel intensities fall within the range of 0-1. I can calculate the image histogram by normalizing it but I found the curves is not exactly the same as the histogram of raw data. This will cause some issue for the later peaks finding process(See attached two images).
My question is in Matlab, is there any way I can plot the image histogram without normalization the data so that I can keep the curve shape unchanged? This will benefit for those raw images when their pixel intensities are not within 0-1 ranges. Currently, I cannot calculate their histogram if I don't normalize the data.
The Matlab code for normalization and histogram calculation is attached. Any suggestion will be appreciated!
h = imhist(mat2gray(I));
Documentation of imhist tells us that the function checks the data type of the input and scale the values accordingly. Therefore, without testing with your attached data, this may work:
h = imhist(uint8(I));
An alternatively you may scale the integer-representation to floating-representation, by either using argument of mat2gray
h = imhist(mat2gray(I, [0,255]));
or just divide it.
h = imhist(I/255);
The imhist answer in this thread describing normalizing or casting is completely correctly. Alternatively, you could use the histogram function in MATLAB which will work with unnormalized floating point data:
A = 255*rand(500,500);
histogram(A);
Related
I want to compute the standard deviation and expected value of the given histogram.
Which matlab function will help me to do that?
My code:
I = imread('download.bmp');
imshow(I);title('Input Image');
imhist(I(:));title('Histogram of input image');
Not quite sure, whether I am getting your question properly.
By expected value of the histogram, do you mean the mean intensity value of the image, so basically which intensity you are most likely to draw if you draw a random pixel?
This you could simply get by doing
m_wholeImage = mean(I(:));
s_wholeImage = std(double(I(:)));
s_wholeImage then gives you the standard deviation of all pixel values.
I would suggest this reference :
Gonzalez., R., Eddins., S. and Woods, R. (2009). Digital image processing using MATLAB. 2nd ed. Gatesmark Publishing, pp.644-654.
It mentions code for quantifying texture in an image, and that involves finding mean and standard deviation of the image histogram.
I found the code online :
http://fourier.eng.hmc.edu/e161/dipum/statxture.m
http://fourier.eng.hmc.edu/e161/dipum/statmoments.m
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
Please explain as to what happens to an image when we use histeq function in MATLAB? A mathematical explanation would be really helpful.
Histogram equalization seeks to flatten your image histogram. Basically, it models the image as a probability density function (or in simpler terms, a histogram where you normalize each entry by the total number of pixels in the image) and tries to ensure that the probability for a pixel to take on a particular intensity is equiprobable (with equal probability).
The premise behind histogram equalization is for images that have poor contrast. Images that look like they're too dark, or if they're too washed out, or if they're too bright are good candidates for you to apply histogram equalization. If you plot the histogram, the spread of the pixels is limited to a very narrow range. By doing histogram equalization, the histogram will thus flatten and give you a better contrast image. The effect of this with the histogram is that it stretches the dynamic range of your histogram.
In terms of the mathematical definition, I won't bore you with the details and I would love to have some LaTeX to do it here, but it isn't supported. As such, I defer you to this link that explains it in more detail: http://www.math.uci.edu/icamp/courses/math77c/demos/hist_eq.pdf
However, the final equation that you get for performing histogram equalization is essentially a 1-to-1 mapping. For each pixel in your image, you extract its intensity, then run it through this function. It then gives you an output intensity to be placed in your output image.
Supposing that p_i is the probability that you would encounter a pixel with intensity i in your image (take the histogram bin count for pixel intensity i and divide by the total number of pixels in your image). Given that you have L intensities in your image, the output intensity at this location given the intensity of i is dictated as:
g_i = floor( (L-1) * sum_{n=0}^{i} p_i )
You add up all of the probabilities from pixel intensity 0, then 1, then 2, all the way up to intensity i. This is familiarly known as the Cumulative Distribution Function.
MATLAB essentially performs histogram equalization using this approach. However, if you want to implement this yourself, it's actually pretty simple. Assume that you have an input image im that is of an unsigned 8-bit integer type.
function [out] = hist_eq(im, L)
if (~exist(L, 'var'))
L = 256;
end
h = imhist(im) / numel(im);
cdf = cumsum(h);
out = (L-1)*cdf(double(im)+1);
out = uint8(out);
This function takes in an image that is assumed to be unsigned 8-bit integer. You can optionally specify the number of levels for the output. Usually, L = 256 for an 8-bit image and so if you omit the second parameter, L would be assumed as such. The first line computes the probabilities. The next line computes the Cumulative Distribution Function (CDF). The next two lines after compute input/output using histogram equalization, and then convert back to unsigned 8-bit integer. Note that the uint8 casting implicitly performs the floor operation for us. You'll need to take note that we have to add an offset of 1 when accessing the CDF. The reason why is because MATLAB starts indexing at 1, while the intensities in your image start at 0.
The MATLAB command histeq pretty much does the same thing, except that if you call histeq(im), it assumes that you have 32 intensities in your image. Therefore, you can override the histeq function by specifying an additional parameter that specifies how many intensity values are seen in the image just like what we did above. As such, you would do histeq(im, 256);. Calling this in MATLAB, and using the function I wrote above should give you identical results.
As a bit of an exercise, let's use an image that is part of the MATLAB distribution called pout.tif. Let's also show its histogram.
im = imread('pout.tif');
figure;
subplot(2,1,1);
imshow(im);
subplot(2,1,2);
imhist(im);
As you can see, the image has poor contrast because most of the intensity values fit in a narrow range. Histogram equalization will flatten the image and thus increase the contrast of the image. As such, try doing this:
out = histeq(im, 256); %//or you can use my function: out = hist_eq(im);
figure;
subplot(2,1,1);
imshow(out);
subplot(2,1,2);
imhist(out);
This is what we get:
As you can see the contrast is better. Darker pixels tend to move towards the darker end, while lighter pixels get pushed towards the lighter end. Successful result I think! Bear in mind that not all images will give you a good result when you try and do histogram equalization. Image processing is mostly a trial and error thing, and so you put a mishmash of different techniques together until you get a good result.
This should hopefully get you started. Good luck!
I'm trying to transform my original gray image to mapped gray image using grey-scale mapping function. I have no idea how to get any two minima correspond to the grey-scale range [a,b] of the original histogram so that I can use these values for the equations below to get the mapped gray image.
f(x,y)=0 if [0,a),
f(x,y)=(255/(a-b))-a for [a,b],
f(x,y)=255 if (b,255]
Thank you!
So essentially you want to scale the histogram of your image to range from 0 - 255. All you need is the max and the min. The easiest way to find them is
a = min(I(:));
b = max(I(:));
Also I suspect you middle equation should actually be
f(x,y)=(255/(a-b))*(f(x,y)-a) for [a,b]
however that would eliminate the need for your first two equations. So it's possible that a and b are not the extrema in your case but that you are actually trying to accentuate some range of intensities that sit in the middle of your images histogram (and essentially discard all information outside of that range). In this case you have not given us enough information to suggest values for either a or b.
I couldn't find an answer for RGB image.
How can someone get a value of SD,mean and Entropy of RGB image using MATLAB?
From http://airccse.org/journal/ijdms/papers/4612ijdms05.pdf TABLE3, it seems he got one answer so did he get the average of the RGB values?
Really in need of any help.
After reading the paper, because you are dealing with colour images, you have three channels of information to access. This means that you could alter one of the channels for a colour image and it could still affect the information it's trying to portray. The author wasn't very clear on how they were obtaining just a single value to represent the overall mean and standard deviation. Quite frankly, because this paper was published in a no-name journal, I'm not surprised how they managed to get away with it. If this was attempted to be published in more well known journals (IEEE, ACM, etc.), this would probably be rejected outright due to that very ambiguity.
On how I interpret this procedure, averaging all three channels doesn't make sense because you want to capture the differences over all channels. Doing this averaging will smear that information and those differences get lost. Practically speaking, if you averaged all three channels, should one channel change its intensity by 1, and when you averaged the channels together, the reported average would be so small that it probably would not register as a meaningful difference.
In my opinion, what you should perhaps do is treat the entire RGB image as a 1D signal, then perform the mean, standard deviation and entropy of that image. As such, given an RGB image stored in image_rgb, you can unroll the entire image into a 1D array like so:
image_1D = double(image_rgb(:));
The double casting is important because you want to maintain floating point precision when calculating the mean and standard deviation. The images will probably be of an unsigned integer type, and so this casting must be done to maintain floating point precision. If you don't do this, you may have calculations that get saturated or clamped beyond the limits of that data type and you won't get the right answer. As such, you can calculate the mean, standard deviation and entropy like so:
m = mean(image_1D);
s = std(image_1D);
e = entropy(image_1D);
entropy is a function in MATLAB that calculates the entropy of images so you should be fine here. As noted by #CitizenInsane in his answer, entropy unrolls a grayscale image into a 1D vector and applies the Shannon definition of entropy on this 1D vector. In a similar token, you can do the same thing with a RGB image, but we have already unrolled the signal into a 1D vector anyway, and so the input into entropy will certainly be well suited for the unrolled RGB image.
I have no idea how the author actually did it. But what you could do, is to treat the image as a 1D-array of size WxHx3 and then simply calculate the mean and standard deviation.
Don't know if table 3 is obtain in the same way but at least looking at entropy routine in image toolbox of matlab, RGB values are vectorized to single vector:
I = imread('rgb'); % Read RGB values
I = I(:); % Vectorization of RGB values
p = imhist(I); % Histogram
p(p == 0) = []; % remove zero entries in p
p = p ./ numel(I); % normalize p so that sum(p) is one.
E = -sum(p.*log2(p));
I have real world 3D points which I want to project on a plane. The most of intensity [0-1] values fall in lower region (near zero).
Please see image 'before' his attched below.
I tried to normalize values
Col_=Intensity; % before
max(Col_)=0.46;min(Col_)=0.06;
Col=(Col_-min(Col_))/(max(Col_)-min(Col_));% after
max(Col)=1;min(Col)=0;
But still i have maximum values falling in lower region (near zero).
Please see second fig after normalization.
Result is still most of black region.Any suggestion. How can I strech my intensity information.
regards,!
It looks like you have already normalized as much as you can with linear scaling. If you want to get more contrast, you will have to give up preserving the original scaling and use a non-linear equalization.
For example: http://en.wikipedia.org/wiki/Histogram_equalization
If you have the image processing toolbox, matlab will do it for you:
http://www.mathworks.com/help/toolbox/images/ref/histeq.html
It looks like you have very few values outside the first bin, if you don't need to preserve the uniqueness of the intensities, you could just scale by a larger amount and clip the few that exceed 1.
When I normalize intensities I do something like this:
Col = Col - min(Col(:));
Col = Col/max(Col(:));
This will normalize your data points to the range [0,1].
Now, since you have many small values, you might be able to make out small changes better through log scaling.
Col_scaled = log(1+Col);
Linear scaling with such data rarely works for me. Using the log function is akin to tweaking gamma for visualization purposes.
I think the only thing you can do here is reduce the range.
After normalization do the following:
t = 0.1;
Col(Col > t) = t;
This will simply truncate the range of the data, which may be sufficient for what you are doing. Then you can re-normalize again if you wish.