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)).
Related
I have to process a very large image ( say 10 MB image file or even more).I have to remove artifacts and dead pixels in MATLAB
I have read about Block Processing of Large Images, but have no idea how to apply it to a 16 bit image.
I am referring to removal of pixels which have highest value into the average value of surrounding pixel .my code is not working on my image which is 80 MB of size
numIterations = 30;
avgPrecisionSize = 16; % smaller is better, but takes longer
% Read in the image grayscale:
originalImage = double(rgb2gray(imread('C:\Documents and Settings\admin\Desktop\TM\image5.tif')));
% get the bad pixels where = 0 and dilate to make sure they get everything:
badPixels = (originalImage == 0);
badPixels = imdilate(badPixels, ones(12));
%# Create a big gaussian and an averaging kernel to use:
G = fspecial('gaussian',[1 1]*100,50);
H = fspecial('average', [1,1]*avgPrecisionSize);
%# User a big filter to get started:
newImage = imfilter(originalImage,G,'same');
newImage(~badPixels) = originalImage(~badPixels);
% Now average to
for count = 1:numIterations
newImage = imfilter(newImage, H, 'same');
newImage(~badPixels) = originalImage(~badPixels);
end
%% Plot the results
figure(123);
clf;
% Display the mask:
subplot(1,2,1);
imagesc(badPixels);
axis image
title('Region Of the Bad Pixels');
% Display the result:
subplot(1,2,2);
imagesc(newImage);
axis image
set(gca,'clim', [0 255])
title('Infilled Image');
colormap gray
newImage2 = roifill(originalImage, badPixels);
figure(44);
clf;
imagesc(newImage2);
colormap gray
You are doing a few things which are obvious problems (but it might depend specifically on how far you can get into the code before you run out of memory)
1) You are immediately converting the whole image to double
2) You are identifying certain pixels which you want to replace, but passing the whole image to imfilter and then throwing away (presumably) most of the output:
newImage = imfilter(originalImage,G,'same'); % filter across the entire image
newImage(~badPixels) = originalImage(~badPixels); % replace all the good pixels!
Without converting to double, why not first check where the bad pixels are, do your processing on subregions of the appropriate size around those pixels (the subregions can be converted to double and back), and then reassemble the image at the end?
blockproc may work if you can write your filtering option as a function which takes in an image area and returns the correct area - you'll have to use the border_size option appropriately and make sure your function just returns the original image without bothering to do any filtering if it hits a block with no bad pixels in. You can even have it write out to file as well.
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 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].
I am trying to plot a set of data in grayscale. However, the image i get seems to be always blue.
I have a set of data, albedo that ranges from [0, 0.068], which is a 1X1 double.
My code is:
for all px,py
albedoMax = 0.0679; albedoMin = 0;
out_im(px,py) = 1/(albedoMax-albedoMin)*(albedo - albedoMin);
imshow(out_im);
drawnow;
end
Basically px,py are the image coordinates that i have to iterate over, and the formula is trying to map the input range of [0, 0.068] to [0 1]. However, by running this code, i notice that the output is always blueish. I was wondering what went wrong.
Thanks for the help.
Can't you make use of the rgb2gray function?
What you are making is one layer of the RGB image.
If you are creating a homogeneous blue image with constant color then the normalization is wrong. But if it is just the matter of being blue instead of being gray then just convert it using :
ImGray = rgb2gray(Im);
Do not forget to distribute the pixels like a grid/mesh, to fill all the image not just a part of it.
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);