How to open a raw YCbCr image file in MatLab? - image

I am trying to open a 1920x1080 YCbCr raw image file in Matlab, however I am having difficulties getting the following code below to work:
fid = fopen(filePath);
image = fread(fid, 1920*1080, 'uint8=>uint8');
fclose(fid);
image = reshape(image, 1080, 1920);
However, when I go to show the image, it does not look as expected.
The actual image should be colour, however I get a strange black and white image, not resembling the expected output at all.
I have also tried loading it into a 3D array, with each dimension representing one of the Y, Cb and Cr channels, however this also produced a similar output as described before.
Any help would be appreciated.

Ignore this bit and look below at the EDIT:
I don't understand why you are using fread? Why not use imread,
which is mean't for reading images? Using this infamous original
image, as a base for my test script, I could display a YCbCr
image, as shown in the little script below.
original = imread("lenna.jpg");
% figure, imshow(original); % if you want to see how the original image looks
YCbCr_version = rgb2ycbcr(original);
% figure, imshow(YCbCr_version); % if you want to see how the YCbCr image looks
imwrite(YCbCr_version, "out.jpg");
YCbCr_fromFile = imread("out.jpg");
figure, imshow(YCbCr_fromFile);
EDIT:
IF however you have a binary version of the file and can only read it using using fread,
then the following script should work,
clc;
clear;
close all;
original = imread("lenna.jpg");
% figure, imshow(original); % if you want to see how the original image looks
YCbCr_version = rgb2ycbcr(original);
% figure, imshow(YCbCr_version); % if you want to see how the YCbCr image looks
fileID = fopen('out.bin','w');
fwrite(fileID, YCbCr_version, 'uint8');
fclose(fileID);
fileID = fopen('out.bin','r');
fromFile = fread(fileID, 512*600*3, 'uint8=>uint8');
fclose(fileID);
image = reshape(fromFile, 512, 600, 3);
imagesc(image)
The point is, in the read operation, you have to give the 3 channels in the multiplier also, as color images have this 3rd dimension, i.e. 512*600*3. If you only give 512*600, as you were doing, you would have no color info. Also the reshape function would need to be changed to take into account the 3rd dimension. Hence, reshape(fromFile, 512,600, 3).
YCbCr version loaded from the file

As you said "Any help would be appreciated", I thought I would mention you can simply convert a raw YCbCr file to PNG, TIFF, JPEG or any other format file with ImageMagick which is installed on most Linux distros and is available for macOS and Windows.
Start a Terminal, (or Command Prompt if under Windows), and convert the YCbCr image.raw to PNG with:
magick -size 1920x1080 -depth 8 YCbCr:image.raw result.png
Or, say a CCIR 601 YUV file to NetPBM PPM format:
magick -size 800x600 -depth 8 YUV:image.raw result.ppm

Related

OpenCV imwrite gives washed-out result for jpeg images

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.

Why does this pbm image behaves weirdly

I am trying to understand why I am not getting expected result from the following lines of code:
pix=np.asarray(Image.open(File))) #I am reading a pbm file into memory
img = Image.fromarray((pix), '1') #rewriting
img.save("test1.pbm")
newpix=~pix #inverting the image
img = Image.fromarray((newpix), '1')
img.save("test2.pbm")
original image and test1.pbm(image 1) is same, but test2.pbm (image 2) isn't what I am expecting (the foreground pixels become background ones and vice versa). I am attaching the images here (converted to jpeg). What am I doing wrong?
Another issue is that for most of the foreground pixels in test1.pbm, the value is False. But that is not reflected in the saved image.
I converted both of these images from this original image http://www.mathgoodies.com/lessons/graphs/images/line_example1.jpg using Imagemagick.
I don't recognise which language you are using, but your original image, when converted with ImageMagick like this:
convert cdLTY.jpg -negate out.jpg
looks like this:
So I deduce the problem is in your inversion. I don't know what
newpix=~pix
does (probably complelementing it or inverting all the bits?) but I think you need to subtract each pixel from 255 to invert your image, so if a pixel is 10 in the original image, it needs to be 255-10 or 245 in the new image.
Explanation
Pixels are normally encoded with 0=black and 255=white. So, if your pixel was originally black (0) when you do new pixel = 255 - original value, it will become 255-0, or 255 meaning it is now white. Likewise, if a pixel starts off white (255), when you do 255-255 you get 0 which is now black.

Saving grayscale image as it appears in jet colormap

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.

matplotlib.pyplot.imsave backend

I'm working in Spyder with matplotlib.pyplot and want to save numpy array to images.
The documentation of imsave() says, that the format to which I can save depends on the backend. So what exactly is the backend? I seem to be able to save .tiff images, but f.e. I want them to be saved as 8-bit tiffs instead of RGB-Tiffs. Any Idea where I can change that?
If you are trying to save an array as a tiff (with no axis markers ect) from mat, you might be better off using PIL.
(this assumes you are using ipython --pylab, so rand is defined)
write:
import PIL.Image as Image
im = Image.new('L',(100,100))
im.putdata(np.floor(rand(100,100) * 256).astype('uint8').ravel())
im.save('test.tif')
The ravel() is important, putdata expects a sequence (ie, 1D) not an array.
read :
im2 = Image.open('test.tif')
figure()
imshow(im2)
and the output file:
$ tiffinfo test.tif
TIFF Directory at offset 0x8 (8)
Image Width: 100 Image Length: 100
Bits/Sample: 8
Compression Scheme: None
Photometric Interpretation: min-is-black
Rows/Strip: 100
Planar Configuration: single image plane

MATLAB - write image into an eps file

In MATLAB, how do you write a matrix into an image of EPS format?
It seems imwrite does not support EPS.
Convert is not working on the Linux server I am using:
$ convert exploss_stumps.jpg exploss_stumps.eps
convert: missing an image filename `exploss_stumps.eps' # convert.c/ConvertImageCommand/2838
Why?
I tried gnovice's idea under terminal mode:
figH = figure('visible','off') ;
imshow(img,'border','tight',... %# Display in a figure window without
'InitialMagnification',100); %# a border at full magnification
print(strcat(filepath,'/', dataset,'_feature_',num2str(j), '.eps'),'-depsc2');
close(figH) ;
However I got:
??? Error using ==> imshow at 191
IMSHOW requires Java to run.
Error in ==> study_weaker at 122
imshow(img,'border','tight',... %# Display in a figure window without
191 error(eid,'%s requires Java to run.',upper(mfilename));
How can I fix it?
One possible solution is to plot your image using IMSHOW, then print the entire figure as a .eps using PRINT:
img = imread('peppers.png'); %# A sample image
imshow(img,'Border','tight',... %# Display in a figure window without
'InitialMagnification',100); %# a border at full magnification
print('new_image.eps','-deps'); %# Print the figure as a B&W eps
One drawback to this solution is that if the image is too big to fit on the screen, IMSHOW will shrink it to fit, which will reduce the on-screen resolution of the image. However, you can adjust the final resolution of the saved image using the -r<number> option for the PRINT function. For example, you can print your figure as an Encapsulated Level 2 Color PostScript with a resolution of 300 dpi by doing the following:
print('new_image.eps','-depsc2','-r300');
EDIT: If you are unable to use IMSHOW (either because you don't have the Image Processing Toolbox or because you are using a MATLAB mode that doesn't allow it), here is an alternative way to create and print the figure:
img = imread('peppers.png'); %# A sample image
imagesc(img); %# Plot the image
set(gca,'Units','normalized',... %# Set some axes properties
'Position',[0 0 1 1],...
'Visible','off');
set(gcf,'Units','pixels',... %# Set some figure properties
'Position',[100 100 size(img,2) size(img,1)]);
print(gcf,'new_image.eps','-depsc2','-r300'); %# Print the figure
You can also take a look at this documentation to see how printing works without a display.
It should work using imwrite. You would have to add a colormap for it to work though.
However, ckecking the help pages I see that it is NOT possible to use imwrite to write an EPS file.
Following code may help you to convert png file to eps.
fileName = 'FarmerStats'; % your FILE NAME as string
A = imread(fileName,'png');
set(gcf,'visible','off') %suppress figure
image(A);
axis image % resolution based on image
axis off % avoid printing axis
set(gca,'LooseInset',get(gca,'TightInset')); % removing extra white space in figure
saveas(gcf,fileName,'epsc'); % save as COLOR eps file

Resources