HSI and HSV color space - image-processing

What is the difference between HSI and HSV color space? I want to use HSI color space but I did not find any useful material for HSI. Is HSI the same as HSV?

HSI, HSV, and HSL are all different color spaces. Hue computation is (as far as I can find) identical between the three models, and uses a 6-piece piece-wise function to determine it, or for a simpler model that is accurate to within 1.2 degrees, atan((sqrt(3)⋅(G-B))/2(R-G-B)) can be used. For the most part, these two are interchangeable, but generally HSV and HSL use the piece-wise model, where HSI usually uses the arctan model. Different equations may be used, but these usually sacrifice precision for either simplicity or faster computation.
For lightness/value/intensity, the three spaces use slightly different representations.
Intensity is computed by simply averaging the RGB values: (1/3)⋅(R+G+B).
Lightness averages the minimum and maximum values for RGB: (1/2)⋅(max(R,G,B) + min(R,G,B)).
Value is the simplest, being the value of the maximum of RGB: max(R,G,B).
When used in subsequent calculations, L/V/I is scaled to a decimal between 0 and 1.
Saturation is where the three models differ the most. For all 3, if I/V/L is 0, then saturation is 0 (this is for black, so that its representation is unambiguous), and HSL additionally sets saturation to 0 if lightness is maximum (because for HSL maximum lightness means white).
HSL and HSV account for both the minimum and maximum of RGB, taking the difference between the two: max(R,G,B) - min(R,G,B), this value is sometimes referred to as chroma (C).
HSV then takes the chroma and divides it by the value to get the saturation: C/V.
HSL divides chroma by an expression taking lightness into account: C/(1-abs(2L-1)).
HSI doesn't use chroma, instead only taking min(R,G,B) into account: min(R,G,B)/I.
Sources
Wikipedia: HSL and HSV
Wikipedia: Hue

From the mathematical formula, the Hues are the same for HSV and HSI when you are trying to make the conversion from RGB to one of them.
Saturation in HSL is dependent on max, min, and Lightness, while HSV's Saturation is only max and min dependent. (max and min are the maximum and minimum pixel value among R, G, B space).
Value is max while the Lightness is (max + min)/2
Appendix: RGB->HSV, RGB->HSL

Related

Choice of Bins in 3D color histogram and HSV color space

I am implementing a classifier that is capable of recognizing vehicle color, and I am using the 3D color histograms of the region of interest as a feature vector, computed using openCV's method, calcHist(). Specifically, to calculate the histograms, I use hist = cv.calcHist([hsv_image], [0, 1, 2], None, (8,8,8), [0, 180, 0, 256, 0, 256]). With these parameters, I got, by doing the flatten() of the histogram, a feature vector of 8x8x8 = 512, and with these feature vectors the classifier works pretty well, but I'm looking to further improve the accuracy of my model. So, what I would like to know is if there is any correlation between the number of bins and the range of color channel values, so that I can choose the best number of bins possible.
I'd suggest if you want to improve accuracy, perhaps try a perceptually accurate colorspace — and HSV isn't one. As color is not "real", and only a perception, it would follow that using a perceptually accurate appearance model is a best practice for your application.
Perceptual Appearance Models
CIECAM02, CIECAM16, Jzazbz are pretty much state of the art, and there is ZCAM for HDR imagery, and also image appearance models such as iCAM. These might not be available in a library for OpenCV, but most aren't that difficult to implement.
CIELAB
A simpler model is CIELAB which is part of OpenCV, and is a better choice than HSV or HSL, particularly if you are goal is to judge or select colors in a manner similar to human perception.
L*a*b* breaks the colors down based on human perception and the opponent process of vision. The channels are perceptual lightness, L* as a value from 0 to 100, and a* and b* which encode red/green and blue/yellow respectively, and are each nominally -128 to 127 if using signed 8bit integers.
LAB is a 3D Cartesian space. To determine the color difference, it is simply the euclidian distance between two colors, in other words, the square root of the sum of the squared differences, so:
∆ = ((L*1 - L*2)2 + (a1 - a2)2 + (b1 - b2)2 )0.5
Polar Version
CIELAB is also available with polar coordinates, LCh, for Lightness, Chroma, and hue.
Saturation is not available with LAB, only Chroma. The other color appearance models I mentioned above do have a saturation correlate, as well as brightness in addition to lightness. (Brightness being a different perception than lightness/darkness).

iOS Metal. Why does simply changing colorPixelFormat result in brighter imagery?

In Metal on iOS the default colorPixelFormat is bgra8Unorm. When I change format to rgba16Float all imagery brightens. Why?
An example:
Artwork
MTKView with format bgra8Unorm.
Texture-mapped quad. Texture created with SRGB=false.
MTKView with format rgba16Float.
Texture-mapped quad. Texture created with SRGB=false.
Why is everything brighter with rgba16Float. My understanding is that SRGB=false implies that no gamma correction is done when importing artwork. The assumption is the artwork has no gamma applied.
What is going on here?
If your artwork has a gamma (it does per the first image you uploaded), you have to convert it to a linear gamma if you want to use it in a linear space.
What is happening here is you are displaying gamma encoded values of the image in a linear workspace, without using color management or transform to convert those values.
BUT: Reading some of your comments, is the texture not an image but an .svg?? Did you convert your color values to linear space?
Here's the thing: RGB values are meaningless numbers unless you define how those RGB values relate to a given space.
#00FF00 in sRGB is a different color than #00FF00 in Adobe98 for instance. In your case you are going linear, but what primaries? Still using sRGB primaries? P3 Primaries? I'm not seeing a real hue shift, so I assume you are using sRGB primaries and a linear transfer curve for the second example.
THAT SAID, an RGB value of the top middle kid's green shirt is #8DB54F, normalized to 0-1, that's 0.553 0.710 0.310 .These numbers by themselves don't know if they are gamma encoded or not.
THE RELATIONSHIP BETWEEN sRGB, Y, and Light:
For the purposes of this discussion, we will assume the SIMPLE sRGB gamma of 1/2.2 and not the piecewise version. Same for L*
In sRGB, #8DB54F when displayed on an sRGB monitor with a sRGB gamma curve, the luminance (Y) is 39
This can be found by
(0.553^2.2)*0.2126 + (0.710^2.2)*0.7152 + (0.310^2.2)*0.0722
or 0.057 + 0.33 + 0.0061 = 0.39 and 0.39 * 100 = 39 (Y)
But if color management is told the values are linear, then the gamma correction is discarded, and (more or less):
0.553*0.2126 + 0.710*0.7152 + 0.310*0.0722
or 0.1175 + 0.5078 + 0.0223 = 0.65 and 0.65 * 100 = 65 (Y)
(Assuming the same coefficients are used.)
Luminance (Y) is linear, like light. But human perception is not, and neither are sRGB values.
Y is the linear luminance from CIEXYZ, while it is spectrally weighted based on the eye's response to different wavelengths, it is NOT uniform in terms of lightness. On a scale of 0-100, 18.4 is perceived as the middle.
L* is a perceptual lightness from CIELAB (L* a* b*), it is (simplified curve of):
L* = Y^0.42 On a scale of 0-100, L* 50 is the "perceived middle" value. So that green shirt at Y 39 is L* 69 when interpreted and displayed as sRGB, and the Y 65 is about L* 84 (those numbers are based on the math, here are the values per the color picker on my MacBook):
sRGB is a gamma encoded signal, done to make the best use of the limited bit depth of 8bits per channel. The effective gamma curve is similar to human perception so that more bits are used to define darker areas as human perception is more sensitive to luminance changes in dark regions. As noted above it is a simplified curve of:
sRGB_Video = Linear_Video^0.455 (And to be noted, the MONITOR adds an exponent of about 1.1)
So if 0% is black and 100% is white, then middle gray, the point most humans will say is in between 0% and 100% is:
Y 18.4%. = L* 50% = sRGB 46.7%
That is, an sRGB hex value of #777777 will display a luminance of 18.4 Y, and is equivalent to a perceived lightness of 50 L*. Middle Grey.
BUT WAIT, THERE'S MORE
So what is happening, you are telling MTKView that you are sending it image data that references linear values. But you are actually sending it sRGB values which are lighter due to the applied gamma correction. And then color management is taking what it thinks are linear values, and transforming them to the needed values for the output display.
Color management needs to know what the values mean, what colorspace they relate to. When you set SRGB=false then you are telling it that you are sending it linear values, not gamma encoded values.
BUT you are clearly sending gamma encoded values into a linear space without transforming/decoding the values to linear. Linearization won't happen unless you implicitly do so.
SOLUTION
Linearize the image data OR set the flag SRGB=true
Please let me know if you have further questions. But also, you may wish to see the Poynton Gamma FAQ or also the Color FAQ for clarification.
Also, for your grey: A linear value of 0.216 is equivalent to an sRGB (0-1) value of 0.500

k-means clustering on RGB or HSV scale?

I want to segment an image but someone told me that the Euclidean distance for RGB is not as good as HSV -- but for HSV, as not all H, S, V are of the same range so I need to normalize it. Is it a good idea to normalize HSV and then do clustering? If so, how should I normalize on HSV scale?
Thanks
As HSV components are signify Hue, Saturation and gray intensity of a pixel they are not correlated to each other in terms of color, each component have its own role in defining the property of that pixel, like Hue will give you information regarding color (wavelength in other terms) Saturation always shows how much percentage of white is mixed with that color and Value is nothing but magnitude of that color(in other term Intensity), that is why all components of HSV space not follow same scale for representation of the values while hue can goes negative(because these are cyclic values) on the scale as well but intensity (V) will never goes negative, so normalization will not help in clustering much, the Better idea is you should apply clustering only on Hue if you want to do color clustering.
Now why Euclidean is not good for multi-channel clustering is because its distribution along mean is spherical(for 2D circular) so if it can not make any difference between (147,175,208) and (208,175,147) both will have same distance from the center, its better to use Mahalanobis Distance for distance calculation because it uses Co-variance matrix of the components which makes this distance distribution Parabolic along the mean.
so if you want to do color segmentation in RGB color space use mahalanobis distance(but it will computationally extensive so it will slows down clustering process) and if you want to do clustering in HSV color space use Hue for the segmentation of colors and than use V for fine tuning of segmentation output.
Hope it will help. Thank You
Hue is cyclic.
Do not use the mean (and thus, k-means) on such data.
Firstly you need to know why HSV is more preffered than RGB in image segmentation. HSV separates color information (Chroma) and image intensity or brightness level (Luma) which is very useful if you want to do image segmentation. For example if you try to use RGB approach for a photo with sea as the background there is a big chance the dominant RGB component in the sea is not blue (usually because of shadow or illumination). But if you are using HSV, value is separated and you can construct a histogram or thresholding rules using only saturation and hue.
There is a really good paper that compared both RGB and HSV approach and I think it will be a good read for you -> http://www.cse.msu.edu/~pramanik/research/papers/2002Papers/icip.hsv.pdf

Poisson blending rgb out of range

I am trying to blend two images using Poisson Blending technique. I have written the program and solved the system of linear equations separately for each r,g,b channel. After solving the equation rgb values are going out of bound, each value greater than 255. If I clamp each value to 255, the resulting image becomes white as all three channes are 255 now. My question is that can the rgb values be greater than 255 after solving poisson equation ? How can I have a proper blended image in this case ?
I think you need to change your scale for color values. According to the formula given in most of the online sites (set of equations), they consider the color value to be in the 0 to 1 range. Convert your 0 - 255 scale to floating point values between 0 - 1 and see.

compare two components with their colors

i want to compare to components with their filled colors if they are equal or not
i do the following algorithm , i do averaging for the rgb as following
double avg1 =(comp[0].Red+comp[0].Blue+comp[0].Green)/3;
double avg2 =(comp[1].Red+comp[1].Blue+comp[1].Green)/3;
then compare them as following
double ratio = avg1/avg2 ;
if(ratio > 0.8 && ratio < 1.2){} //then they are supposed to be equal
but this way isn't accurate at all
after searching i found that the best way is converting the image to HSL space and compare
but i can't get how i compare 2 colors ?!! here
in other words after converting the image into HSL space what can i do ?!
help please !!
modification to the question for more clarification
i mean with component (sequence of points) so in the averaging step actually i revisit all the points calculating the sum of the average of rgb for each pixel , then do averaging over the total number of the points
Convert to HSL and use the difference in H (hue) to group colors.
So if your question is "after converting the image into HSL space what can i do ?!" then here goes:
convert the RGB image you've loaded to HSL using cvCvtColor() with the CV_RGB2HLS flag (the HSL image should be 3-channel, naturally)
make three single-channel images (of same size) for the H, L, S channels to be separated into
cvSplit( hls, h, l, s, 0 ) to separate the HSL image into channels
Now the h_image will be just like any single-channel grayscale image. So after extracting components (do this from thresholding the RGB image, sometimes Hue channel image looks weird :P) simply compare the colors in the hue image that correspond to their co-ordinates.
Hope this helps.

Resources