So I ran into a weird problem with the MATLAB imread() function where it can't read old images (in this case, a bmp from 2002). Basically when I pass the image as an argument to imread(), it recognises the image as a grayscale even though it is clearly RGB.
Image is part of a standard test set available to download from here. I am using the 'boy.bmp' image.
% In Downloads folder
I_dl = imread('boy.bmp');
whos %to show current variables
OUTPUT:
Name Size Bytes Class Attributes
I_dl 512x768 393216 uint8
The image size is actually around 390KB so it's not that only one channel is getting loaded into the workspace somehow. Looks like it has to do with some older encoding system.
I ran an imshow() to check the image and this was the result.
TEMPORARY WORK-AROUND: I imported the image into GIMP, saved it as an xcf (GIMP's native format) and then exported it as a bmp. Then I did the imread() and then whos. It works.
Name Size Bytes Class Attributes
I 512x768x3 1179648 uint8
The file size expanded to 1.2MB too. Strange.
Any one else faced the same issue?
Regards.
boy.bmp contains the indexed image. You should load and use the colormap matrix:
[I_dl,cmap] = imread('boy.bmp');
imshow(I_dl,cmap);
Related
I'm trying to use low-level functions (fopen and fread) to read a grayscale image of type uint16 in TIFF format as follows:
fid = fopen(filepath,'r');
img = fread(fid,[ncolms, nrows], 'uint16=>uint16')';
The obtained image matrix is different from that obtained by simply using imread:
img = imread(filepath);
The resulting images are shown below (the left is by fread and the right is by imread):
In addition to the obvious intensity difference, one may also note that fread image has some artifacts in the top edge of image. I think this must be due to their different mechanisms of reading images.
I want to know how to use such low-level functions as fopen and fread to read images (grayscale, not binary), equivalently to using imread, if they can.
Those "artifacts" you're seeing are likely the header and tag data stored in the file before the image data. I would suggest taking a look at this TIFF File Format Summary. It will tell you exactly how to read all this extra information, if you really want to do it yourself. Note that some of this extra tag information (i.e. ImageHeight, ImageWidth, BitsPerSample, SamplesPerPixel, etc.) will be useful in determining exactly how to read the image data correctly, and thus match the image you get from the imread function.
I am using OpenCV 3.0 and whenever I read an image and write it back the result is a washed-out image.
code:
cv::Mat img = cv::imread("dir/frogImage.jpg",-1);
cv::imwrite("dir/result.jpg",img);
Does anyone know whats causing this?
Original:
Result:
You can try to increase the compression quality parameter as shown in OpenCV Documentation of cv::imwrite :
cv::Mat img = cv::imread("dir/frogImage.jpg",-1);
std::vector<int> compression_params;
compression_params.push_back(CV_IMWRITE_JPEG_QUALITY);
compression_params.push_back(100);
cv::imwrite("dir/result.jpg",img, compression_params);
Without specifying the compression quality manually, quality of 95% will be applied.
but 1. you don't know what jpeg compression quality your original image had (so maybe you might increase the image size) and 2. it will (afaik) still introduce additional minor artifacts, because after all it is a lossy compression method.
UPDATE your problem seems to be not because of compression artifacts but because of an image with Adobe RGB 1998 color format. OpenCV interprets the color values as they are, but instead it should scale the color values to fit the "real" RGB color space. Browser and some image viewers do apply the color format correctly, while others don't (e.g. irfanView). I used GIMP to verify. Using GIMP you can decide on startup how to interpret the color values by format, either getting your desired or your "washed out" image.
OpenCV definitely doesn't care about such things, since it's not a photo editing library, so neither on reading nor on writing, color format will be handled.
This is because you are saving the image as JPG. When doing this the OpenCV will compress the image.
try to save it as PNG or BMP and no difference will be exist.
However, the IMPORTANT QUESTION : I am loading the image as jpg and saving it as JPG. So, how there is a difference?!
Yes, this is because there is many not identical compression/decompression algorithms for JPG.
if you want to get into some details see this question:
Reading jpg file in OpenCV vs C# Bitmap
EDIT:
You can see what I mean exactly here:
auto bmp(cv::imread("c:/Testing/stack.bmp"));
cv::imwrite("c:/Testing/stack_OpenCV.jpg", bmp);
auto jpg_opencv(cv::imread("c:/Testing/stack_OpenCV.jpg"));
auto jpg_mspaint(cv::imread("c:/Testing/stack_mspaint.jpg"));
cv::imwrite("c:/Testing/stack_mspaint_opencv.jpg", jpg_mspaint);
jpg_mspaint=(cv::imread("c:/Testing/stack_mspaint_opencv.jpg"));
cv::Mat jpg_diff;
cv::absdiff(jpg_mspaint, jpg_opencv, jpg_diff);
std::cout << cv::mean(jpg_diff);
The Result:
[0.576938, 0.466718, 0.495106, 0]
As #Micha commented:
cv::Mat img = cv::imread("dir/frogImage.jpg",-1);
cv::imwrite("dir/result.bmp",img);
I was always annoyed when mspaint.exe did the same to jpeg images. Especially for the screenshots...it ruined them everytime.
I have grayscale satellite image which is processed from spectral data (band classifications). If i use jet colormap in imshow it will show absolute colormapped image. But if i try to imwrite in particular place it is saved like a bluish image. I saw one example in matlab central, but i didnt get. can anyone help me to write my image with colorscaled image.
Matlab central link: http://www.mathworks.in/matlabcentral/answers/25026-saving-grayscale-image-as-it-appears-in-jet-colormap-of-imagesc
there accepted answer link is : http://www.mathworks.com/matlabcentral/fileexchange/7943
I have tried many times, this will show colormaped images in plots (imshow) they didnt write anywhere with colormaped. Now i want to write my image with colormaped.
example code:
I= imread('image path');
imshow(I,'colormap',jet);
imwrite(I,'path','jpg'); /not working
or
imwrite(I,jet,'path','jpg'); /not working
Please help to solve this issue.
When you use imshow the colormap is always adjusted to the range of values in your image. imwrite however assumes your image has a value range of [0,1] if you are using single or double data types. Try to scale your image to the range [0,1] before saving.
If you provide a colormap in the call to imwrite, MATLAB assumes you are using an indexed image. Thus you will have to convert the image to the indexed format first. The following snippet worked for a test image I of mine:
% scale to [0,1]
I = I - min(I(:));
I = I ./ max(I(:));
% Create indexed image
[J,~] = gray2ind(I);
% Save image
imwrite(J,jet,'path','jpg');
Solution by hbaderts worked well for me, but later I found out that some images were still scaled slightly different way from imshow.
However, I might found a reason of an original problem. Just after Matlab starts, its default colormaps (including 'jet') are set to 64 colors (64x3). Then, if any image is shown with a colormap, for example if imshow('cameraman.tif'), colormap('jet') is executed, all default colormaps become 256x3 (can be verified with jetMap=jet; before and after). Then it might happen that an image was written with a colormap different from the one applied to image figure (for example, if a figure called after imwrite).
Finally I found this solution (no image pre-scaling needed):
% Create indexed image, explicitly using 256 colors
imInd=gray2ind(im,256);
% Convert indexed image to RGB using 256-colors jet map
jetRGB=ind2rgb(imInd,jet(256));
% Save image
imwrite(jetRGB,'jet.png');
The images I used have the same color scale now, both the saved one and the one shown in figure.
I am processing microscopy images (in Matlab) in the tiff format, normally uint8 or uint16. Basically I read them, put them in a cell array for processing and then export them in the tiff format either as an image sequence or a stack (using imwrite and either the 'overwrite' or 'append' writemode property of imwrite, respectively). Up to now everything works very well.
The problem I'm having is the following:
When I open the images with ImageJ, they are not in truecolor "RGB" color mode, but rather in composite mode. For example ImageJ reads the data as 8 bit, which it is, but does not open the image as a truecolor (Sorry for the bad choice of words I don't know the right terminology). Hence I have to manually combine the 3 channels together, which is bothersome for large datasets.
Here is a screen shot explaining. On the left is what I would like,i.e. what I obtain if I open the image directly with ImageJ, and on the right is what I currently have after saving images with Matlab and opening them with ImageJ, which I don't want.
The code I'm using to export the image sequence is the following. "FinalSequenceToExport" is the cell array containing the images.
for i = 1:SliceNumber
ExportedName = sprintf('%s%s%d.tiff',fileName,'Z',i);
imwrite(FinalSequenceToExport{i},ExportedName,'tif','WriteMode','overwrite','Compression','none');
end
If I ask Matlab the size of FinalSequenceToExport{1}, for instance, it gives 512 x 512 x 3.
If I open a given image in the command window and then save it with the same code as above, it does what I want and the resulting image opens as I want in ImageJ. Hence my guess would be that the problem arises from the use of the cell array but I don't understand how.
I hope I've been clear enough. If not please ask for more details.
Thanks for the help!
You need to specify the the 'ColorSpace'
Try this
imwrite(FinalSequenceToExport{i},ExportedName,...
'tif','WriteMode','overwrite','Compression','none', ...
'ColorSpace', 'rgb');
After revisiting this question I found the following to work, thanks to the hint from #Ashish:
imwrite(uint8(FinalSequenceToExport{i}/255),...);
I just needed to divide by 255 after converting to uint8.
I used these codes to produce an RGB image with gray levels between 50 and 170.
a='C:\Users\sepideh\Desktop\IP_abadpour\S45C-113050518040.jpg';
b=imread(a);
b=b+50;
b(b>170)=170;
and you'll see when I call functions max and min, it is proved that the gray levels are between 50 and 170.
max(max(max(b)))
ans =
170
min(min(min(b)))
ans =
50
then I used imshow and imsave functions to save the image with the name "50to170"
c=imshow(b);
d=imsave(c);
Now I read the written image in this way:
a='C:\Users\sepideh\Desktop\IP_abadpour\50to170.jpg';
b=imread(a);
This time when I call max and min functions,I see:
max(max(max(b)))
ans =
235
min(min(min(b)))
ans =
16
I mean it seems that gray levels have been changed after using imshow and imsave functions!
Why does it happen?
Is it because of the format (.jpg) that I'm using when employing imsave function?
Instead of using imsave, use imwrite
b=imread(a);
b=b+50;
b(b>170)=170;
imwrite(b,'50to170.png','png')
Notice that I am saving it as a png file instead of a jpg to prevent compression. Bitmap also saves it without compression.
This method is a more direct way to save raw image matrices than using imshow and imsave.
If you want the same functionality of imsave (selecting where the file goes) check out "uiputfile" to get file name and location.
I tested it.
1.First of all you can't use imsave(b) because the function imsave expects its first input argument to be a valid handle to a single graphics object.So first you should show the image in form c=imshow(b) and then use c as an input for function imsave.
2.If you want to save the image without showing it first use function "imwrite" and pass b as the first input argument to it.
Note that if you don't want gray levels be changed after saving, you should use 'bmp' as the save format not 'jpg'.
Because 'jpg' does not support indexed images and "imwrite" converts indexed images to RGB before writing data to JPEG files so the gray levels might be changed.It's not related to the contrast stretching when showing the image in matlab.It's related to the format used to save the image.