Matlab rgb2hsv changes image - image

I am trying to convert an array of RGB values into an array of HSV values in Matlab. I am running the following code:
pic = imread('ColoradoMountains.jpg');
pic = rgb2hsv(pic);
imwrite(pic,'pic.jpg')
But the image that gets written has completely different colors. I've been trying to set the color map to hsv, but I'm not sure if that even makes sense. Nothing on the internet comes up with my keywords, can someone please point me in the right direction?

You can specify the colormap that imwrite is supposed to use. Try this:
imwrite(pic,colormap('HSV'),'pic.png');
Here's the documentation for imwrite: http://www.mathworks.com/help/matlab/ref/imwrite.html

In Matlab you have to distinguish between an indexed image and an 3-channel image. An indexed image is a n*m*1 image where each value of the [0,1] range is associated to a colour. This association is called colour map, which could be for example a unit circle in HSV or RGB. This can be written using imwrite with the map parameter, but this is not what you want.
What you obviously want is an HSV-encoded image, which means the three rgb-channels are converted to three hsv channels. This is (as far as I know) not possible. If you take a look into the documentation of imwrite, you can see how CMYK-Encoded images are written, this is done implicit passing a n*m*4 image. Is there any of the standard file formats which supports HSV? If so I'll take a closer look at this format.

Related

Distance transform of grayscale image

Matlab has bwdist and graydist: I was looking for something like bwdist for grayscale images, but I wasn't sure what the mask specified in graydist was.
When I'm working with the graydist function, I have tried:
T = graydist(image,image<=0)
T = graydist(image,image<=254)
I can't find an example of it being used other than that one Matlab page, but they're using different input arguments. An explanation or suggestions as to how to get the distance transform of a greyscale image in Matlab would be really helpful!

Imagesc conversion formula

I have a .png image that has been created from some grayscale numbers using Matlab's imagesc tool using the standard color map.
For some reason, I am unable to recover the raw data. Is there a way of recovering the raw data from the image? I tried rgb2gray which more or less worked, but if I replug the new image into imagesc, it gives me a slightly different result. Also, the pixel with the most intensity differs in both images.
So, to clarify: I would love to know, how Matlab applies the rgb colormap to the grayscale values, when using the standard colormap.
This is the image we are talking about:
http://imgur.com/qFsGrWw.png
Thank you!
No, you will not get the right data if you are using the standard colormap, or jet.
Generally, its a very bad thing to try to reverse engineer plots, as they will never contain the entirety of the information. This is true in general, but even more if you use colormaps that are do not change accordingly with the data. The amount of blue in jet is massively bigger in range than the amount of orange, or another color. The color changes are non-linear with the data changes, and this will make you miss a lot of resolution. You may know what value orange corresponds to, but blue will be a very wide range of possible values.
In short:
Triying to get data from representation of data (i.e. plots) is a terrible idea
jet is a terrible idea

keep original values when saving matrix to image in Matlab

Let me explain.
My program takes an x-ray in a format of the x-ray detector ".his" which goes from 0 to 65535, and from those values it can tell you how much of a certain material is in each pixel "4 cm of aluminum" for example.
It does that for every pixel and you end up with a matrix that tells you how much of a given material is there, and you can visualize that matrix and see only fat tissue in an image without the bones blocking your view, it's very cool I know.
What I want to do now is to save that matrix as an image so that I can analyse and modify that image with programs like Image J, but I also want that if I see the pixel value I see the original value, I want to see "4" and know that pixel shows 4 cm of lungs or whatever material I'm working on.
Is that possible?, my professor seems to think that it is but he's not sure how to do it, and figure that out is my job anyway.
It should be possible since with Image J I can open the ".his" format and I can do just that, I can see the values from 0 to 65535, provided I say Image J that the image is 16 bit unsigned and other properties of that kind of files, but I wouldn't know how to do that for a Matlab variable.
Thanks a lot.
So if I understand correctly, you want to save an image that also contains arbitrary metadata on every pixel (in this case an integer).
If you use an image format like PNG you could encode that extra data into the alpha channel (which would be nearly imperceptible with a value like 4/255 away from fully opaque), but you'd have to be careful when editing the image that you don't change the alpha channel by mistake.
However, this is rather finnicky and would be cumbersome to implement in Matlab.
Instead I would suggest simply saving a standard image and a text file (or binary file) alongside it with the data you want.

Reading voxel values from binary file into matlab

I have a 16bit voxel data set from which I need to extract the integer values for each voxel. The data set can be downloaded from here, it is the 'Head Aneuyrism 16Bits' data set (You need to click on the blood vessels image to download the 16bit version). Its size is 512x512x512, but I don't know whether it is greyscale or color, nor if that matters. Looking at the image on the website I'd guess that it is color, but I am not sure whether the image should be taken literally.
A related question on SO is the following: How can I read in a RAW image in MATLAB?
and the following on mathworks: http://www.mathworks.com/matlabcentral/answers/63311-how-to-read-an-n-dimensioned-matrix-from-a-binary-file
Thanks to the information in the answers to these questions I managed to extract some information from the file with matlab as follows:
fileID=fopen('vertebra16.raw','r');
A=fread(fileID,512*512*512,'int16');
B=reshape(A,[512 512 512]);
I don't need to visualise the image, I only need to have the integer values for each voxel, but I am not sure whether I am reading the information in the correct way with my script.
The only way I found to try and check whether I have the correct voxel values is to visualise B using the following:
implay(B)
Now, with the code above, and then using implay(B) I get a black and white movie with a white disc in the center and black background and some black pixels moving in the disc (I tried to upload a frame of the movie, but it didn't work). Looking at the image on the website from which I downloaded the file, the movie frames I get seem quite different from that image, so I'd conclude that I do not have the correct voxel values.
Here are some questions related to my problem:
Do I need to know whether the image is in grey scale or color to read the voxel values correctly?
On the data set website there is only written that the data set is in 16bit format, so how do I know whether I am dealing with signed or unsigned integers?
In the SO question linked to above they use 'uint8=>uint8'. I could not find this in the matlab manual, so I wonder whether 'uint8=>uint8' is an obsolete matlab notation for 'uint8' or if it does something different. I suspect that it does something different since if I use 'int16=>int16' instead of 'int16' in my code above I get a completely black movie with implay.
It looks like you read the data correctly.
The problem when displaying it is the scale of the values. implay seems to assume the values to be in [0,1] and therefore clamps all values to be in that range, where are your data range is [0,3000].
Simply doing
B = B / max(B(:))
will rescale your data to [0,1] and looking at the data again with
implay(B)
shows you something much more sensible.

Reading data from colour terrain map

I have a question about converting a height-map that is in colour into a matrix - look here to see examples of such maps. If I were to have a terrain plot and plot it using imagesc, then I would see it as a colour map. I was wondering how I could convert an image that looks like this into its corresponding matrix.
This seems like it should be a pretty basic procedure, but I can neither work out how to do it myself nor find out how to do it online (including looking on SO).
To put it another way, the image in question is a jpeg; what I'd like is to be able to convert the .jpg file into a matrix, M say, so that imagesc(M), or surf(M), with the camera looking at the (x,y)-plane (from above), give the same as viewing the image, eg imshow(imread('Picture.jpg')).
You can use Matlab's rbg2ind function for this. All you need to choose is the "resolution" of the output colormap that you want, i.e. the second parameter n. So if you specify n as 8 for example, then your colormap will only have 8 values and your output indexed image should only have 8 values as well.
Depending on the color coding scheme used, you might try first converting the RGB values to HSL or HSV and using the hue values for the terrain heights.

Resources