imread altering image in Matlab? - image

I am having an issue reading a single image of a stacked tiff in using imread. The tiff is 128-by-126. It reads in just fine with ImageJ, but I try reading it into Matlab for some processing and it creates an odd streak in the center of the image. With the origin of the image in the top left, rows 63 and 64 are repeated as rows 65 and 66, and the last two rows of the image, 125 and 126 are cut off. I can tell this is happening by visual comparison of the image displayed in matlab to the image displayed in ImageJ.
If I take the same tiff stack, and save the first frame in ImageJ, I don't have this issue. Even when displaying the outputted matlab image using ImageJ, I see the same issue. However, I would like to automate the process to save images from several tiff stacks as single tiff files, which I can't do in ImageJ, so I turned to Matlab and ran into this issue. I have included my code below. I tried reading the tiff in two different ways and got the same error. It seems to be related to the tiff stack and how matlab reads in the tiffs. I am using Matlab R2012b.
I have included links below to the static ImageJ image I am seeing and the static matlab image I am seeing. I have also included a link for loading the stacked tiff file that is generating these issues for me.
Note: When I have ImageJ output each frame as an individual tiff and I open the first frame from that output in matlab using the same code below, the image is correctly displayed. The error only occurs when reading in the first frame from the image stack in Matlab.
StackOverflow doesn't support embedding TIFF files, but you can view and download them from these links:
Stacked Tiff File - Data I am working with
What the first frame should look like - ImageJ
What I am seeing when loading the first frame in MATLAB
Code Used to Generate the Image
fname='C:\FileLocation\pcd144_012.tif';
im1=imread(fname,1)
imagesc(im1);
axis image; colormap gray;
I tried reading in the image as a tiff object to see if it solved the problem and this didn't work either. The image has two strips, and the last two lines of the first strip are the same as the first two lines of the last strip, which is why the middle lines seem to be repeated. It seems matlab is indexing reading my image in wrong, likely because it is not a square image. Am I just doing something wrong, or does matlab have a bug with respect to reading in non-square tiffs? Any ideas or suggestions for improvement?

First of, I kinda agree with horchler, that is, there is something wrong in your header.
We can easily observe that the StripByteCounts (15872) does not match width*height (128*126). This could be the reason you see the repetition in row 63 - 64 and 65 - 66.
Since the RowPerStrip = 64 and StripOffsets = [8,15880] may indicate that you have a 128*124 graph, Matlab perhaps uses last two rows in the first 64 rows to pad the missing rows at the beginning of the rest of the rows. So the total row can be filled up to 126. Well, this is just my guess for how Matlab handles the disagreement between dimension and ByteCounts.
After all, to your question, imread indeed alters image in Matlab when reading TIFF without issuing any warning. Bad job in imread reading TIFF, Matlab.
After observing your TIFF frames in one of your links, the TIFF seems to actually have image data with dimension 128*126. So if you trust the dimension indicating in the header, you would probably use fread to read the frames in your TIFF instead of using shaky imfread.
fname='pcd144_012.tif';
tiffInfo = imfinfo(fname);
framIndex = 1;
tiffWidth = tiffInfo(framIndex).Width; % image width
tiffHeight = tiffInfo(framIndex).Height; % image height
tiffStartOffset = tiffInfo(framIndex).StripOffsets(1); % Image data offset start point
tiffEndOffset = tiffInfo(framIndex).StripOffsets(2); % Image data offset end point
fid = fopen(fname);
fseek(fid,tiffStartOffset,'bof');
im1 = fread(fid,tiffWidth*tiffHeight,'*uint16'); % We knew this from BitsPerSample
fclose(fid);
im1 = reshape(im1,tiffWidth,tiffHeight); % Reshape the image data array
figure
imagesc(im1);
colormap gray;
axis xy;
axis image;
Now, while this may solve the weird Matlab imread behavior, however, the above result still does not match the picture you showed in your second link. According to the picture in the second link, it has 300 frames but the one you attached in your first link only has 30 frames. Maybe we are all looking at the wrong picture?

Related

How to find images with a variable sized grey rectangle (JPEG corruption) in them?

I had to recover a hard drive and a lot of photos in it came out corrupted. I'm talking about 200.000 photos. I already wrote a script that finds corrupted JPEGs. But some of these images are not corrupted on a file format level. Yet they appear as the example I am showing. The grey part i suspect is data missing from the file. The grey part size is variable and sometimes it has an incomplete line in it.
So I'm thinking I could write or find a script that finds grey rectangles in these images.
How do I do this? Something that opens the image data and looks for this giant grey rectangle? I have no idea where to start. I can code in a bunch of languages.
Any help/examples, is much appreciated.
I was thinking that the grey rectangle is always the same colour, so I created a function to see if that grey is one of the top 10 most frequent
colours.
If the colour had changed, then I would have adjusted the code accordingly to check if the top colour is at least 10x more frequent than the second most frequent colour.
Didn't have to learn feature detection this time. Shame. :(
from collections import Counter
from PIL import Image
# Open the image file
image = Image.open(file)
# Convert the image to RGB format (if it's not already)
image = image.convert('RGB')
# Get a list of all the pixels in the image
pixels = list(image.getdata())
# Count the number of pixels with each RGB value
counts = Counter(pixels)
most_common_colors = counts.most_common(10)
return (128,128,128) in [t[0] for t in most_common_colors]

imshow shows image as noisy even though its not in windows image viewer

Im trying to learn a segmentation network using CNN, my network is producing very poor results. I looked at the images and I'm wondering if this is the reason. My input images are stack of images in a .tif file. In Windows image viewer below is what I get:
I am trying to detect and segment the bright spots shown above
But when I open the same in Matlab using imshow() I get
All the information is basically lost. However when I use imagesc() I get the following:
Which is much better, but why are my images not working with my network? I am getting very very unpredictable losses and accuracy even with tried and tested networks.
Is it because my image is reading in the version shown in imshow()?
In MATLAB, the following convention is used for images:
uint8: pixels are in the range [0,255].
double: pixels are in the range [0,1].
When using imshow on a double image, values between 0 and 1 are mapped to a color scale (typically black to white). Any value above 1 is also mapped to white. This is what is happening to you: most of your pixels are shown as white.
It is likely that the CNN you are using makes the same assumptions and therefore clips your data.
The solution is to properly scale your images when you read them in. See for example im2double.
Neither imshow nor imagesc is designed to handle tiff stacks. They are for viewing, not reading image data. You may see a warning along the lines of the following, also:
"Can only display one frame from this multiframe file"
You can use imread to read in each of the frames in the file separately, as per this answer, or tiff which is a Matlab gateway to LibTiff library routines and provides more detailed control of how you read in your images if imread doesn't hack it.

saving a very large image in MATLAB

I know that this question has been asked before. But, I could not find a clear answer for it. I have data for a very high resolution colorful image with the size of 50,000 by 60,000 with the data type unit8. I cannot save the entire image by using imwrite. I have gotten the error that says:
"Images must contain fewer than 2^32 - 1 bytes of data"
Is there a way to save the entire image in MATLAB?
right now, I have to break the data into smaller pieces (sub-images) and then use imwrite to write each piece to a png file. The output format of the file is not important.
Your image occupies 8*50000*60000*3 = 7.2000e+10 bytes of data that is 16.7638 times more than MATLAB image size limit. Why no to split it in 20 pieces, save them and then merge them manually? If you split your image into 6 8x50000x3000x3 pieces, they would all fit into 2^32 limit.
I am sure OP has enough aptitude to do this, but I'll explain the procedure anyway. Convert your image into 50000x60000x3 array and do the following:
x = 0:3000:60000;
for i = 1:length(x)-1
imwrite(A(:,x(i)+1:x(i+1),:),strcat('image',num2str(i),'.png'),'png');
end
This would create 20 images for you with names 'image1.png', 'image2.png' and so on. Then, you can merge these images manually using this first google search result. Perhaps, there is some fancier way to do this, but I think this is the easiest one.
Another question has an answer which worked for me: if your image is stored as a double matrix, convert to uint8 with im2uint8(img), then save.

Stitching sub-images in MATLAB to form the final image

I looked thoroughly in internet to see how to stitch sub-images but none corresponds to my need. So I am in need of an explanation before I understand how the whole programming process might go.
I have taken images of a line with a camera at a fixed distance and varying the camera position along the line with steps of 5mm and taking always an image. I continue until I take the final image of the end of the line.
I have the images stored in Excel as files (35files). I have already converted the files (images) into an array of 2D matrices.
So my question now is:
How do I stitch the images from the first sub-image to the last sub-image in MATLAB to get the final exact image of the line? How do I treat the different sub-images? I do not understand just the basics of stitching! How does the dimensions of the line gets preserved on the final image?

Strange/Magical Image visualization with Matlab

I have an Image of double, I want to show it with unsigned int 16 bit, so I do:
I = im2uint16(I);
figure;imshow(I);title('Image being saved')
This shows this (with its normal noise):
Now I want to write this image with .png with Bit Depth 16 Bit. I do:
imwrite(I,'image.png','BitDepth',16);
And now the image, opened with Photoshop CS5, or Windows Photo Viwer looks like this: (the noise is magically disappeared):
Can someone explain this strange behaviour ?
How to Reproduce this error
Download in C:\test\ the image I used here:
Now run this script:
I = im2double(imread('C:\test\test_matlab.tif'));
% Add gaussian noise with variance = 0.0012
I = imnoise(I,'gaussian',0,0.0012);
figure,imshow(I);
imwrite(I,'C:\test\withNoise.tif');
And compare the figure in matlab versus the file saved
It's difficult to say because you didn't give enough data to reproduce, but I'd guess the problem is related to a display issue: the image is larger than you physical display window, hence some downsampling must be applied to display it. Depending on how that resampling is done, the result can be -in this scenario- very different, visually.
Suppose that matlab applies a nearest-neighbour resampling for its display, that would explain why the image looks very noisy; instead, if another image viewer applies a bilinear interpolation or something similar, that would amount to a local average that practically filters out the white noise.
To test this, try the same with a small image. Or try zooming the apparently clean image, to see it at real size (100% : one image pixel = one display pixel)
Update: See also here
Here's what I did:
%# read the image (why is it so big?)
I = im2double(imread('https://p7o1zg.bay.livefilestore.com/y1pcQVsmssygbS4BLW24_X1E09BKt_Im-2yAxXBqWesC47gpv5bdFZf962T4it1roSaJkz5ChLBS0cxzQe6JfjDNrF7x-Cc12x8/test_matlab.tif?psid=1'));
%# add noise
I = imnoise(I,'gaussian',0,0.0012);
%# write tiff
imwrite(I,'withNoise.tif');
%# read the tiff again
I2 = imread('withNoise.tif');
class(I2) %# -- oopsie, it's uint8 now!
%# convert to uint16 as in original post
I = im2uint16(I);
%# writ again
imwrite(I,'withNoise16.png','bitDepth',16);
%# read it
I2 = imread('withNoise16.png');
%# compare
all(all(I==I2)) %# everything is equal
So there is no funky stuff going on in writing/reading the image (though you lose some information in the bit conversion - your original image only takes up about a third of the dynamic range, so you'll lose more information that if you stretched the contrast before conversion).
However, the image is 2k-by-2k. When I only look at the top right corner of the image (taking 500-by-500 pix), it is displayed the same in Matlab and other graphics programs. So I bet it's a matter of resampling your image that Matlab does differently from other programs. As #leonbloy suggests, Matlab may be doing nearest-neighbor resampling, while other programs would do interpolation.

Resources