Math to obtain a color scale variation in decimal - hsv

I am trying to find a math that makes possible a correct calculation of a color (HSV) scale variation like:
Color blue = #002AFF (in hexadecimal) = 11007 (in decimal)
This color blue has Hue = 230, 100% saturation and 100% value.
So I need to make a scale that contains X blue colors (in this example) variations from 50% saturation to 100% saturation, and after that, from 100% value to 50% of value (while 100% saturation).
Example:
blue(99% saturation, 100% value) == 142591 in decimal
blue(98% saturation, 100% value) == 339711 in decimal
In order to make that scale, I need that this math returns me a decimal value of each color generated out of that color math, so Ill use the decimal value within my program to generate the rgb color.
So do you guys knows any code able to do this math? Cause I can't just figure out a math for it

Related

Plotting multiple lines in Matlab - make colors more intense on each iteration?

I am plotting graphs of a function that changes slightly on each iteration as it converges towards its limiting values...How can I make the colors of the lines get more intense on each iteration? By intense I mean the lines stay the same color but get more saturated or darker on each iteration?
If you are plotting all you lines with one call of plot then set the 'ColorOrder' property of your axes (search for ColorOrder).
If you are using a loop, then you could do something like this:
baseColour = rgb2hsv([1,0,0]); %// Get the HSV values for pure red, but choose any colour
hue = baseColour(1);
saturation = baseColour(2);
for k = 1:n
%// do stuff
lineColour = hsv2rgb([hue, saturation, 1-(k-1)/(n-1)]);
%plot(..., 'Color', lineColour)
end
This should shift your lines from having no lightness (value actually) i.e. black to being fully light, but keeping the same hue and saturation which creates a fairly natural colour grading. This makes the most sense if your data are ordinal i.e. the user should know that the value of some property of the data forming the bright lines is greater than the value of that property of the data froming the darker lines.
You should create your own colormap, and for a given color you can set the intensity by interpolating the rgb values while keeping the proportions - an example explains what I mean more clearly. So for green:
cmap = [zeros(128,1), linspace(0,1,128)', zeros(128,1)];
imagesc(1:128)
colormap(cmap)

Counting number of coloured pixels in an image

I have an image of a Jacaranda tree (jpeg) and i want to count the number of 'purple' pixels in this image using matlab.
The hard thing about this question is -> How do you define purple?
Before answering that lets introduce HSV color space.
In this color space, unlike in RGB, there is a single value that describes colors, while the others are saturation and "light" (see wikipedia or my answer here for more info about HSV). This means that just by looking at H we can know which color something is. The first thing we will do is put our image in HSV.
hsv_image = rgb2hsv(rgb_image)
Now we need to know which values of H are "purple". We can see a rough approximation of where purple is in this SO answer, where it is identified in around 300 degrees of Hue. If, instead, we look a bit deeper to the wikipedia page of Shades of purple*. There, we can see that the shades of purple listed are about 270-320 Hue values.
If we like this approximation, then we can just select the pixels of the image with that amount of H by
H=hsv_image(:,:,1);
and then just select the ones that are in the desired range
purple=H<320 && H> 270;
Or in just one go
purple=hsv_image(:,:,1)<320 && hsv_image(:,:,1)> 270;
Then we just need to count.
N_purple=sum(purple(:))
*If you were asking for gray the wikipedia page would be confusing

Difference between imshow(pic) and imshow(pic,[])

I have a very brief question on imshow in matlab.
what is the difference between imshow(pic) and imshow(pic,[])?
when should I use imshow(pic,[])?
From Mathwork's website (see here in the DisplayRange section):
Display range of a grayscale image, specified as a two-element vector [LOW HIGH]. imshow displays the value low (and any value less than low) as black, and the value high (and any value greater than high) as white. Values in between are displayed as intermediate shades of gray, using the default number of gray levels. If you specify an empty matrix ([]), imshow uses [min(I(:)) max(I(:))]; that is, use the minimum value in I as black, and the maximum value as white.
Suppose, you have an image which has the lowest value of 230 and highest value of 255, and if you do imshow(img), it will assume that the lowest of the displayed image is 0 and maximum is 255, so you end up with an (almost) white image. On the other hand, if you do imshow(img,[]), you tell MATLAB adjust the minimum and maximum of the displayed image according to the minimum and maximum values of the image. Therefore, in the above example, calling imshow(img,[]) is equivalent to calling imshow(img,[230 255]). This will enable you to see the intermediate shades of gray.

Block artifact in converting RGB 2 HSV

I would like to convert an image from RGB space to HSV in MATLAB and use the Hue.
However, when I use 'rgb2hsv' or some other codes that I found in the internet the Hue component has block artifacts. An example of the original image and the block artifact version are shown below.
Original
Hue
I was able to reproduce your error. For those of you who are reading and want to reproduce this image on your own end, you can do this:
im = imread('http://i.stack.imgur.com/Lw8rj.jpg');
im2 = rgb2hsv(im);
imshow(im2(:,:,1));
This code will produce the output image that the OP has shown us.
You are directly using the Hue and showing the result. You should note that Hue does not have the same interpretation as grayscale intensity as per the RGB colour space.
You should probably refer to the definition of the Hue. The Hue basically refers to how humans perceive the colour to be, or the dominant colour that is interpreted by the human visual system. This is the angle that is made along the circular opening in the HSV cone. The RGB colour space can be represented as all of its colours being confined into a cube. It is a 3D space where each axis denotes the amount of each primary colour (red, green, blue) that contributes to the colour pixel in question. Converting a pixel into HSV, also known as Hue-Saturation-Value, converts the RGB colour space into a cone. The cone can be parameterized by the distance from the origin of the cone and moving upwards (value), the distance from the centre of the cone moving outwards (saturation), and the angle around the circular opening of the cone (hue).
This is what the HSV cone looks like:
Source: Wikipedia
The mapping between the angle of the Hue to the dominant / perceived colour is shown below:
Source: Wikipedia
As you can see, each angle denotes what the dominant colour would be. In MATLAB, this is scaled between [0,1]. As such, you are not visualizing the Hue properly. You are using the Hue channel to directly display this result as a grayscale image.
However, if you do a scan of the values within this image, and multiply each result by 360, then refer to the Hue colour table that I have shown above, this will give you a representation of what the dominant colours at these pixel locations would be.
The moral of this story is that you can't simply use the Hue and visualize that result. Converting to HSV can certainly be used as a pre-processing step, but you should do some more processing in this domain before anything fruitful is to happen. Looking at it directly as an image is pretty useless, as you have seen in your output image. What you can do is use a colour map that derives a relationship between hue and colour like in the Hue lookup map that I showed you, and you can then colourize your image but that's really only used as an observational tool.
Edit: July 23, 2014
As a bonus, what we can do is display the Hue as an initial grayscale image, then apply an appropriate colour map to the image so we can actually visualize what each dominant colour at each location looks like. Fortunately, there is a built-in HSV colour map that is pretty much the same as the colour lookup map that I showed above. All you would have to do is do colormap hsv right after you show the Hue channel. We can show the original image and this colourized image side-by-side by doing:
im = imread('http://i.stack.imgur.com/Lw8rj.jpg');
im2 = rgb2hsv(im);
subplot(1,2,1);
imshow(im); title('Original Image');
subplot(1,2,2);
imshow(im2(:,:,1)); title('Hue channel - Colour coded');
colormap hsv;
This is what the figure looks like:
The figure may be a bit confusing. It is labelling the sky as being blue as the dominant colour. Although this is confusing, this makes actual sense. On a clear day, the sky is blue, but the reason why the sky appears gray in this photo is probably due to the contributions in saturation and value. Saturation refers to how "pure" the colour is. As an example, true red (RGB = [255,0,0]), means that the saturation is 100%. Value refers to the intensity of the colour. Basically, it refers to how dark or how light the colour is. As such, the saturation and value would most likely play a part here which would make the colour appear gray. The few bits of colour that we see in the image is what we expect how we perceive the colours to be. For example, the red along the side of the jet carrier is perceived as red, and the green helmet is perceived to be green. The lower body of the jet carrier is (apparently) perceived to be red as well. This I can't really explain to you, but the saturation and value are contributing to the mix so that the overall output colour is about a gray or so.
The blockiness that you see in the image is most likely due to JPEG quantization. JPEG works great in that we don't perceive any discontinuities in smooth regions of the image, but the way the image is encoded is that it reconstructs it this way... in a method that will greatly reduce the size it takes to save the image, but allow it to be as visually appealing as if you were to look at the RAW image.
The moral of the story here is that you can certainly use Hue as part of your processing chain, but it is not the entire picture. You will probably need to use saturation or value (or even both) to help you discern between the colours.

What does `imshow(someImage, [])` do?

I am trying to figure out what the second (empty vector) parameter in imshow(someImage, []) in Matlab is for.
According to doc imshow, it's either a color map or a range of width/height, but neither of these make sense to me since the vector is empty.
With the empty bracket imshow will display the range between the minimum and maximum value. For example, if your image is 16bits, the maximum value is 65536, but if your actual pixel values stop at 1000, imshow(image) will seem black (because even 1000 over 65536 is small). If you use imshow(image, []), then the display will be adjust between 0 and 1000.
It is the same as:
minValue = min(min(image));
maxValue = max(max(image));
imshow(image,[minValue maxValue]);
The documentation from help imshow describes this syntax:
imshow(I,[LOW HIGH]) displays the grayscale image I, specifying the display
range for I in [LOW HIGH]. The value LOW (and any value less than LOW)
displays as black, the value HIGH (and any value greater than HIGH) displays
as white. Values in between are displayed as intermediate shades of gray,
using the default number of gray levels. If you use an empty matrix ([]) for
[LOW HIGH], imshow uses [min(I(:)) max(I(:))]; that is, the minimum value in
I is displayed as black, and the maximum value is displayed as white.