6

I am so confused with image Normalization, and image Range, and image Scaling. I am using an algorithm (I have upload the algorithm in my Previous Question), and after applying the algorithm I am using this formula from wikipedia to normalize the images:

enter image description here

using getrangefromclass(filtImag1{i}) from MATLAB, the range of matrices before applying the algorithm is [0 255] and after applying the algorithm the range is [0 1].

the problem is I need to find a reference to find out if the normalization formula is correct or not? also I have 5 stacks of images each containing 600 images. I have applied the algorithm for each stack, and because the result of algorithm is 10 images for each stack, I will end up with 50 images that I need to analysis and compare them together. I find the max and the min of the 50 images , and then pass each image into the formula to normalize the image.

although the range of the images is [0 1] but the max of the image is : max = 3.6714e+004

why? shouldn't it be 1? is this the right way of normalization? how can I apply scaling ? do I need to do it?

here is the normalization code :

%%%%%%%%%%%%%%Find Min and Max between the results%%%%%%%%%%%%%%%%%%%%%%% 
pre_max = max(filtImag1{1}(:));
for i=1:10
   new_max = max(filtImag1{i}(:));
    if (pre_max<new_max)
        pre_max=max(filtImag1{i}(:));
    end
end
new_max = pre_max;

pre_min = min(filtImag1{1}(:));
for i=1:10
   new_min = min(filtImag1{i}(:));
    if (pre_min>new_min)
        pre_min = min(filtImag1{i}(:));
    end
end
new_min = pre_min;

%%%%%%%%%%%%%%normalization %%%%%%%%%%%%%%%%%%%%%%%
 for i=1:10
 temp_imag = filtImag1{i}(:,:);
 x=isnan(temp_imag);
 temp_imag(x)=0;
 t_max = max(max(temp_imag));
 t_min = min(min(temp_imag));
 temp_imag = (double(temp_imag-t_min)).*((double(new_max)-double(new_min))/double(t_max-t_min))+(double(new_min));
 imag_test2{i}(:,:) = temp_imag;
 end

EDIT I have change the code based on suggested answers but the result is black image

%find the max and min between them pre_max = max(sTStack{1}(:)); for i=1:40 newMax = max(sTStack{i}(:)); if (pre_max

pre_min = min(sTStack{1}(:)); for i=1:40 newMin = min(sTStack{i}(:)); if (pre_min>newMin) pre_min = min(sTStack{i}(:)); end end t_min = pre_min;

%%%%%%%%%%%%%%%%%%%%%%% Normalize the Image:%%%%%%%%%%%%%%%%%%%%%%%%%%%%

for i=1:40 NTstack{i} = (sTStack{i} - t_min)/(t_max-t_min); end

for i=10:10:40 figure,imshow(NTstack{i}); colorbar colormap jet end

Community
  • 1
  • 1
user261002
  • 2,182
  • 10
  • 46
  • 73
  • Where's your code? How can someone answer your question without seeing what you did? – Eitan T Jun 24 '12 at 16:58
  • @EitanT I have already upload it in my previous link in stackoverfow:http://stackoverflow.com/questions/10863734/image-processing-algorithm-in-matlab/ – user261002 Jun 24 '12 at 17:28
  • @user261002 It looks like in you don't use pre_max or pre_min in your normalization coode. Is this intentional? – Steve Jun 24 '12 at 19:42

3 Answers3

7

The Wikipedia snippet you provide is correct and can be used to normalize an image using the following MATLAB code:

%% Create an Example Image:
rand('seed', 1982);
n = 16;
myImg= rand(n,n)*.2 + .5;

%% Normalize the Image:
myRange = getrangefromclass(myImg(1));
newMax = myRange(2);
newMin = myRange(1);

myImgNorm = (myImg - min(myImg(:)))*(newMax - newMin)/(max(myImg(:)) - min(myImg(:))) + newMin;

The problem with some images is that although they only occupy a small range of possible values. If your values can range between 0 and 1 then black would be 0 and white would be 1. However, if your darkest spot in the image is .5 and your brightest is .7 then it might look washed out to your processing or to the user when is is visualized (note that MATLAB's imagesc automatically normlizes the image before display for this very reason).

If you look at the histogram of the image using hist(myImg(:)) you can tell how must of the allowed values the image is actually using. In a normalized image, the smallest value will be 0 and the largest will be 1 (or whatever range you use).

A common error in implementing this equation is to not properly place your parenthesis, not subtract off the min of your image before scaling, or not adding back in "newMin".

You can see everything together in the following code and image. Note how the original image (1) uses only a small portion of the space (2), so it looks washed out when we don't let imagesc autoscale the clim parameter. Once we normalize (3), however, the image has both very dark and very light values and the histogram stretches all the way from 0 to 1 (4). While it's not exactly clear what your code is or isn't doing, comparing it to this example should solve your problem.

%% Create an Example Image:
rand('seed', 1982);
n = 16;
myImg= rand(n,n)*.2 + .5;

%% Normalize the Image:
myRange = getrangefromclass(myImg(1));
newMax = myRange(2);
newMin = myRange(1);

myImgNorm = (myImg - min(myImg(:)))*(newMax - newMin)/(max(myImg(:)) - min(myImg(:))) + newMin;

%% Display the Image:
figure(42);
clf;

% Display the original:
subplot(2,2,1);
imagesc(myImg);
set(gca, 'clim', [0,1]);;
title('(1) Original Image');

% Display the hist of the original:
subplot(2,2,3);
hist(myImg(:))
xlim([0,1]);
title('(2) Histogram Of Original Image');

% Display the normalized image:
subplot(2,2,2);
imagesc(myImgNorm);
title('(3) Normalized Image');

% Display the hist of the normalized image:
subplot(2,2,4);
hist(myImgNorm(:))
title('(4) Histogram of Normalized Image');
xlim([0,1]);

colormap gray

enter image description here

EDIT:

Additionally, there are some important points to notes to make on how getrangefromclass(...) will work on your problem. This function returns the "default display range of image based on its class"---that is, it returns what MATLAB believes is a reasonable range of values is for that data type to represent a picture. For uint8 data, this is [0, 255]. For int16 this is [-32768, 32767]. For your case, double, the range is [0, 1] not because that's the minimum and maximum value but because that is conventional and double data types have a special representation that make this range quite reasonable. Note that is range has nothing to do with what your data actually is. If you have data is small or larger than the min and max will be quite different than what MATLAB thinks is good for pictures. In the case of double or single your value could be much larger. To normalize the values to between [0, 1] we can use the code we have been discussing.

In this case we create a random image that has big positive and negative values, but we will scale them all to be between zero and one. That is, we make the darkest color 0 and the lighted color 1---whereas before the smallest was negative thousands and the largest was positive thousands. However, note how the histogram shape stays the same while the x-axis values change to 0,1. This should demonstrate why the MATLAB range is [0,1] but your min/max is different----that is fine and your normalization code will fix everything between zero and one.

randn('seed', 1982);
myImg = randn(n,n)*1000;
% Normalize the Image:
myRange = getrangefromclass(myImg(1));
newMax = myRange(2);
newMin = myRange(1);

myImgNorm = (myImg - min(myImg(:)))*(newMax - newMin)/(max(myImg(:)) - min(myImg(:))) + newMin;

% Display the Image:
figure(42);
clf;

% Display the original:
subplot(2,2,1);
imagesc(myImg);
% set(gca, 'clim', [0,1]);;
title('(1) Original Image');
colorbar
% Display the hist of the original:
subplot(2,2,3);
hist(myImg(:))
title('(2) Histogram Of Original Image');
axis tight;

% Display the normalized image:
subplot(2,2,2);
imagesc(myImgNorm);
title('(3) Normalized Image');
colorbar

% Display the hist of the normalized image:
subplot(2,2,4);
hist(myImgNorm(:))
title('(4) Histogram of Normalized Image');
axis tight;

colormap gray

enter image description here

Steve
  • 3,957
  • 2
  • 26
  • 50
  • thank you for your reply and the explanation, I assume the code above is only for normalization of one image, but I have 50 images and I want to make sure the normalization is amoung all of them. do you suggest anything? I am going to upload my code now, please have a look, thank you – user261002 Jun 24 '12 at 19:16
  • 2
    @user261002 Your code doesn't appear to be in error. I added some text at the end of the answer to address what getrangefromclass is returning. Have a max or min outside these bounds is okay, and normalization is going to put them back inside these bounds, exactly. – Steve Jun 25 '12 at 00:10
  • @user261002 Can you clarify what you mean by "among them"? If you are looking to normalize from the min and max of the entire stack then I suggest using pre_min and pre_max rather than t_min and t_max of your example code. – Steve Jun 25 '12 at 00:31
  • exaclty I want to normalize them from the min and max of the entire stack, thats why I put them in the loop to find the min and max, with the help of pre_min and pre_max. I am not sure what do you mean why to use pre_min and pre_max instead of t_min and t_max – user261002 Jun 25 '12 at 08:40
  • @user261002 if you want to stretch the histograms based on the min/max of the entire stack then you just set `t_min = pre_min; t_max = pre_max;` inside the loop instead of what they are now. – Steve Jun 25 '12 at 15:20
  • I just used it and it make my image balck – user261002 Jun 25 '12 at 15:56
  • 1
    @user261002 If you see a black frame, it is possible that one image in your stack has large values compared to all the others. This can make all the other normalizations forced the "small" values into a very small range close to zero and look black. If so, you should see one "good" looking frame or an all-white frame in the stack after normalization. Is this so? If so, you could either discard this single frame and run again, or go back to normalization for each image independently. – Steve Jun 25 '12 at 16:19
3

Having answered your previous question, I think I understand your confusion.

First of all, the input images were of type uint8 (thus the range [0,255]), and since we needed to perform processing on the signals (Butterworth filtering), it was necessary to convert to double data type to avoid having the values being truncated.

Now at the end of the processing, the resulting "images" were of type double but have arbitrary ranges (they represented average energy in signals). Now if we want to display those images or even perform image-processing on them (you were attempting to apply medfilt2 in your original code), MATLAB expects images of type double to be in the [0,1] range.

The formula I used in the code and the one you just provided are compatible, its just that I am normalizing to the range of [0,1], thus newMax = 1 and newMin = 0 and the equation end up simply as I described it before:

 img = ( img - min(img(:)) ) ./ ( max(img(:)) - min(img(:)) );

Just remember that you should be normalizing each image on its own, i.e compute the min/max in the formula for the image itself, not from the entire group of images. If you look back at the solution I proposed, the images were stored in a cell array, and the computation was done using CELLFUN to get min/max of each image separately:

Tf = cellfun(@(x)reshape((x-min(x))./range(x),sz), Tf, 'Uniform',false);

obviously the signals were stored as linearized vectors (each in a cell), thus we normalized each to [0,1] range, then we reshaped it into a proper image matrix.

Now if you like to go back to uint8 images after that, a simple call to im2uint8 would suffice.

I should add that the type of linear transformation we performed above is called min/max normalization, but it's certainly not the only kind (see this answer for other examples). One might also look into other contrast-enhancement techniques (think histogram equalization and the like)

Community
  • 1
  • 1
Amro
  • 123,847
  • 25
  • 243
  • 454
  • hi @Amro thank you for your answer, but I dont understand why should I need to normalize each image on its own, I need to compare and analyse my data so I need as my supervisor said I have to normalize them together, then I wont loose any data and the data will be comparable – user261002 Jun 25 '12 at 08:50
2

I usually use mat2gray from the image processing toolbox for these purposes: mat2gray. I applies exactly the same linear interpolation that you refer to above. Internally it calls imlincomb.

The problem you are refering to, makes me believe that you have somehow implemented the above equation wrongly.

Ole Thomsen Buus
  • 1,333
  • 1
  • 9
  • 24