I am having 60 images of size 250x250x3 . Now I want to add it as a stack of images.
ie, I want to create a 4-D array, which holds all the images in the form of a mat file. So, it should be of size 250 x 250 x 3 x 60 .
I have tried the following. But when I displays the image it is full of white with some small marks only. This was the code .
X=zeros(250,250,3,60)
for i=1:60
X(:,:,:,i)=image1 and so on on every every loop.
Any way to create this mat.
The problem:
It seems like yout images are stored as uint8 type. When you pre-allocated your X you defined it as double (by default).
When Matlab displays an image there is a difference between a uint8 type image and double type image: for uint8 Matlab expects the intensities to range between [0..255]. However, when it comes to double type images Matlab expects the values to range between [0..1]. Thus, assigning uint8 image values to double type you have a double type image with values in the range [0..255] - which Matlab displays as white.
Solutions:
There are several ways you can solve your problem:
Define X as a uint8 type
X = zeros( [255, 255, 3, 60], 'uint8' )
This will save memory as uint8 takes single byte whereas double takes 8.
Alternatively, you can cast your images to double using im2double function that changes the data type and the range of intensities to [0..1].
Related
I have just started learning image processing by myself, and I am using MATLAB. I have been getting myself familiarized with basic image operations. When I read the below image(res: 225x300), which is supposed to be an 8-bit color image, I expected the resultant matrix to have 3 dimensions with one each for RGB. A simple web search about 8-bit color image led me to Wikipedia with the following information:
The simplest form of quantization frequently called 8-bit truecolor is to simply assign 3 bits to red, 3 to green and 2 to blue (the human eye is less sensitive to blue light) to create a 3-3-2.
Therefore, I expected the image matrix to have 225x300x3 dimensions with the above distribution of bits b/w RGB. But after I checked the dimensions of the matrix of the image, I found it to be 225x300 unit8, which is what one expects from an 8-bit grayscale image. But the image is a color image, as seen by any image viewer. So what is that I lack in knowledge or doing wrong? Is the problem with how I read the image?
Also, it occurred to me that uint8 is the smallest unsigned integer class. So how can we have colored images of 4,8,10, etc., bits represented and created?
My code:
>> I_8bit = imread('input_images\8_bit.png');
>> size(I_8bit)
ans =
225 300
>> class(I_8bit)
ans =
'uint8'
>> I_24bit = imread('input_images\24_bit.png');
>> size(I_24bit)
ans =
225 300 3
>> class(I_24bit)
ans =
'uint8'
(source: https://en.wikipedia.org/wiki/Color_depth#/media/File:8_bit.png)
Matlab supports several types of images, including
RGB images, which allow arbitrary colors, stored in terms of R,G,B components. The image is defined by a 3D m×n×3 array
Indexed images, in which each pixel is defined by an index to a colormap. The image is defined by a 2D m×n array and a c×3 colormap, where c si the number of colors.
It looks like the image you are loading is indexed. So you need the two-output version of imread to get the 2D array and the colormap:
[I_8bit, cmap] = imread('input_images\8_bit.png');
To display the image you need to specify the 2D array and the colormap:
imshow(I_8bit, cmap)
You can see the effect of changing the colormap, for example
cmap_wrong = copper(size(cmap, 1)); % different colormap with the same size
imshow(I_8bit, cmap_wrong)
To convert to an RGB image, use ind2rgb:
I_8bit_RGB = ind2rgb(I_8bit, cmap);
which then you can display as
imshow(I_8bit_RGB)
I'm new to Matlab so this should be an easy question. I have an image with a few specific pixels that I need to get the red RGB components from, sum them, and store the result into a variable. By default, these values are of type uint8, so the sum can't exceed 255. I've tried using every combination of double() to convert the R value to a double, but nothing seems to be working. Here's exactly what's happening, copied from the terminal: (All pixels have R values above 200)
img = imread('img.png');
r = img(64,64,1)
r =
224
r = r + double(img(64,65,1))
r =
255
r = r + double(img(64,66,1))
r =
255
What am I doing wrong? Am I not able to convert these values to double?
For image processing, most of the times it is a good idea to use the im2double function to convert the image read into a double array between 0-1 as such:
img = im2double(imread('img.png'));
Then you don't need to worry about data type any more in the same program.
The data type conversion with double() alone almost never do what you intended to images, since uint8 and double images differ in both data type and data range.
What's happening in the line r = r + double(img(64,65,1)) is that the img(64,65,1) value is being converted to double, but then immediately being converted back into class(r) because r is an integer class and has precedence in operations. Observe that class(int64(10)+10) gives back int64. The key here is, as beaker commented, to convert r itself to double first.
You may not have to worry about using double() to do the conversion; doubles can represent integers up to 2^53-1, which is way higher than 255. So if you're just doing simple pixel-summing operations or things like that, you're not going to lose any precision in the calculations. Of course, if you need to put it back into an image, then anything about 255 will saturate. So, it might make more sense depending on what you're doing to rescale things to be between 0 and 1; in that case, as Mingjing suggested, it's best to use im2double.
I am trying to open a .pgm image file in MATLAB, run a manipulation with a for loop and then save as another .pgm file. Before doing the manipulation I was testing to see if I could recreate the image:
clear
picture = imread('Picture.pgm');
sizePic = size(picture);
sizeX = sizePic(1);
sizeY = sizePic(2);
newPicture = zeros(sizeX,sizeY);
for i = 1:sizeX
for j = 1:sizeY
newPicture(i,j) = picture(i,j);
end
end
imwrite(newPicture, 'NewPicture.pgm');
However, the new image is almost all white with some black splotches (not the original). Shouldn't this just give me back the original image?
By default, picture created from imread(XXX.pgm) is either a uint8 or uint16 array, meaning the pixel values are in the range of [0 255] or [0 65535]. On the other hand, newPicture created from zeros is a double array, the expected pixel value for which is only [0 1]. Any value greater than 1 will be interpreted as 1 (white) in the saved image. When you assign a [0 255] value to such a double array, since most of the pixel values in picture is 1 and above, of course you will get mostly white pixels
When you work with images, always check the type of the image array. For example, it may be a good idea to always work with double type by explicitly converting the image returned by imread as such:
pictures=im2double(imread(xxx)).
I'm trying to show the negative of an image and as you know it has a very simple code.
This is the original image:
When I use the code:
Out = 255-img;
%Out = uint8(OutNeg);
imshow(Out);
The result will be:
But using the code:
OutNeg = 255-img;
Out = uint8(OutNeg);
imshow(Out);
Will make the right answer:
Now I am wondering
1 - what does the function uint8() does in fact?
2 - Do these codes make the same results? In fact what is the usage of uint8?
Code1:
img2 = uint8(img1);
imshow(img2);
Code2:
imshow(img1,[0 255]);
3 - Do I need to normalize the image before showing it with the following code?
img2 = 255/(max(max(img1))-min(min(img1)))*(img1-min(min(img1)));
Or using uint8 or [0 255] does the same thing and no need to normalize??
4- what is the difference between normalizing, using uint8 and using [0 255]??????
please consider transformations like Log and power-low in your answers.
From help imshow:
If your grayscale image is single or double, the default display range is
[0 1]. If your image's data range is much larger or smaller than the default
display range, you may need to experiment with setting the display range to
see features in the image that would not be visible using the default
display range. For all grayscale images having integer types, the default
display range is [intmin(class(I)) intmax(class(I))].
By making your data an 8-bit unsigned integer (uint8) array, the data is expected by imshow to be on [0 255]. RTM.
I have a small problem in saving data in a array. I want to save data in the form 10001010 <- 8 bits in a 2d array containing 100 rows and 100 columns. what i do now is
a = rand(100,100);
a = a * 127; // <<- this is done to make it 8 bits
To confirm what i have done i did a imshow to display the image.
When a is multiplied by 127 most of the grayscale pixels has turned to white but before the multiplication step it showed a nice grayscale image.
a = rand(100,100); after a = a * 127;
If you want 8-bit representation it's actually 0->255 since image intensities are unsigned. Matlab checks which class the image is when using imshow, if it's a double, the range 0->1 is expected. Hence you need to cast the image to uint8 after multiplying for it to show properly.
a = rand(100,100);
a = a*255;
a = uint8(a);
imshow(a);