Color that is most contrast to a given set of colors? - colors

I have a list of several different "random" colors values (no less than 1 and no more than 8 colors). (Random means that there is no telling of their mutual "contrast".)
Colors are given as RGB values (possible simplification: as H values in HSL model, or in some other color system of choice — I have some degree of control of how original colors are generated).
I need to compute a single one color value that is the most "contrast" (i.e. visually distinguishable) from all colors from the list.
A practical criteria for the contrast, for the case with 8 colors:
If we draw 9 squares, filled with our colors as follows:
[1][2][3]
[4][X][5]
[6][7][8]
Color of square X must be clearly distinguishable from all adjacent colors.
Possible simplification: reduce maximum number of colors from 8 to 4 (squares 2, 4, 5, 7 in the example, ignore diagonals).

I think the best solution could be:
maximize hue difference with all the colors (simple linear optimization)
maximize lighting
maximize saturation
http://www.colorsontheweb.com/colorcontrasts.asp
Edit: with linear programming, you could give lower significance to the diagonal colors.
Edit2: What maximization means:
You want to maximize the hue contrast, that means the sum of all |Hi - result|, where Hi stands for Hue of color i, is to be maximized. You can even create conditions for minimum difference, e.g. |Hi - result| > Hmin. The actual calculation can be done by giving the equations to the linear optimization algorithm or you can try all hue values between 0.0 and 1.0 stepping by 0.05 and saving the best result.
http://en.wikipedia.org/wiki/Linear_programming.

Related

How to generate color palette based on given image?

I would like to generate color palette based on the given image containig max. 10 colors. Assume that, the given picture is bot bigger then 800x600 px. I've tried the next algorithm:
Generate 500 random X, Y values.
Check the colors' R,G,B values at the (X,Y) position, put colors into an array.
Find similar colors to each color, count how many similar colors have found. (Similar means: +- 10 difference in R, G, B)
Display colors which have the most similar colors.
The result is not what I expect. Any idea how to get the appropriate colors?
An example, I want something like this
You probably want Median Cut or K-means.
With median cut, you'll generate a point cloud of color samples from your source image. Divide the pointcloud in half at its median across the axis with maximum variance, creating two sub-pointclouds. Recursively divide these until you have the desired number of leaf nodes. You can then generate a palette by averaging the color samples in each leaf node.
With K-means, you select k random color samples from your image. These will be the first color samples in k buckets. Then, for each pixel, add its color value to the bucket whose average color is closest to that of the pixel in question-- you may use euclidean distance to determine "closeness". After all pixels have been sampled, the average colors of the k buckets is your palette.
You will get better results if you first convert your color samples to CIE lab color space, where euclidean distance is a better measure of perceptual distance.

how to choose a range for filtering points by RGB color?

I have an image and I am picking colors by RGB (data sampling). I select N points from a specific region in the image which has the "same" color. By "same" I mean, that part of the image belongs to an object, (let's say a yellow object). Each picked point in the RGB case has three values [R,G,B]. For example: [120,150,225]. And the maximum and minimum for each field are 255 and 0 respectively.
Let's assume that I picked N points from the region of the object in the image. The points obviously have different RGB values but from the same family (a gradient of the specific color).
Question:
I want to find a range for each RGB field that when I apply a color filter on the image the pixels related to that specific object remain (to be considered as inliers). Is it correct to find the maximum and minimum from the sampled points and consider them as the filter range? For example if the max and min of the field R are 120 ,170 respectively, can it be used as a the range that should be kept.
In my opinion, the idea is not true. Because when choosing the max and min of a set of sampled data some points will be out of that range and also there will be some point on the object that doesn't fit in this range.
What is a better solution to include more points as inliers?
If anybody needs to see collected data samples, please let me know.
I am not sure I fully grasp what you are asking for, but in my opinion filtering in RGB is not the way to go. You should use a different color space than RGB if you want to compare pixels of similar color. RGB is good for representing colors on a screen, but you actually want to look at the hue, saturation and intensity (lightness, or luminance) for analysing visible similarities in colors.
For example, you should convert your pixels to HSI or HSL color space first, then compare the different parameters you get. At that point, it is more natural to compare the resulting hue in a hue range, saturation in a saturation range, and so on.
Go here for further information on how to convert to and from RGB.
What happens here is that you implicitly try to reinvent either color indexing or histogram back-projection. You call it color filter but it is better to focus on probabilities than on colors and color spaces. Colors of course not super reliable and change with lighting (though hue tends to stay the same given non-colored illumination) that's why some color spaces are better than others. You can handle this separately but it seems that you are more interested in the principles of calculating "filtering operation" that will do segmentation of the foreground object from background. Hopefully.
In short, a histogram back-projection works by first creating a histogram for R, G, B within object area and then back-projecting them into the image in the following way. For each pixel in the image find its bin in the histogram, calculate its relative weight (probability) given overall sum of the bins and put this probability into the image. In such a way each pixel would have probability that it belongs to the object. You can improve it by dividing with probability of background if you want to model background too.
The result will be messy but somewhat resemble an object segment plus some background noise. It has to be cleaned and then reconnected into object using separate methods such as connected components, grab cut, morphological operation, blur, etc.

Calculate the apparent difference in color between two HSI color values

I have two color values in HSI (Hue Saturation and Intensity) and I want a number which represents the visual difference between the two colors. Hue is a number between 0 and 360 inclusive. Saturation is 0 to 1 and Intensity is 0 to 1.
Lets consider for example Red and Blue at Saturation of 100% and Intensity of 100%.
At this website is a way to display the color by entering in the following text.
red is:
hsv 0, 100%, 100%
blue is:
hsv 240, 100%, 100%
Clearly these are two very different colors, and so a simple way I could try to calculate the difference between colors is to use the Hue component and calculate the absolute difference in hue which would be 120 (360-240) since 360 is also equal to 0 in hue.
The problem arises where the Saturation or Intensity is very dark or light, consider a very dark red and blue.
dark red is:
hsv 0, 100%, 20%
dark blue is:
hsv 240, 100% 20%
Obviously the visual difference between these two colors is less than the bright red and blue colors, as a human would state if asked to compare the differences. What I mean here is, ask a friend "Which pair of colors is most different?" they will likely say the top bright red blue.
I am trying to calculate the difference between two colors as a human would notice. If a human being looked at two colors a and b, then two colors c and d, he could notice which ones are the most different. Firstly if the colors are bright (but not too bright) then the difference is hue based. If the colors are too bright such as white or too dark such as black or too grey then the differences are smaller.
It should be possible to have a function diff where x=diff(a,b) and y=diff(c,d) yields x and y, and I can use x and y to compare the differences to find the most different color or least different color.
The WCAG2.0 and 1.0 guidelines both make reference to different equations on perception of color difference:
contrast ratio (http: //www.w3.org/TR/2008/REC-WCAG20-20081211/Overview.html#contrast-ratiodef)
brigtness difference and 3. color difference (http://www.w3.org/TR/AERT#color-contrast).
I tried the Delta-e method(http: //colormine.org/delta-e-calculator/) but it is quasimetric so the difference measurement may change depending on the order you pass the two colors. If in your example you expect diff(a,b) to always equal diff(b,a) then this is not what you want(there may be different algorithms under this name that aren't quasimetric but I haven't looked into it past that site).
I think that the color difference metric is the closest to matching my expectations of color difference measurements. For your example it will yield that diff(a,b) > diff(c,d)
You can test it out for yourself using the tool at this website: http://www.dasplankton.de/ContrastA/
The general answer seems to be what David van Driessche said, to use Delta E. I found some Java code here: https://github.com/kennyliou/GAI
This is a answer to the question, may not be the best answer.

WebGL color mix calculation

What is WebGL color mix calculation algorithm? I need to draw quadrangle with 4-way gradient color fill and I decided to do it with 3-way gradient triangles (like this), calculating the center of quadrangle and using such point for 4 triangles to get the best result of gradient smoothness. To do it right, I need to calculate the color of the center of quadrangle by same way as WebGL calculates color mix for 3-way gradient fill. What is the formular for such calculation?
WebGL uses linear interpolation for vertex attributes. The formula for interpolating a value across a square given samples at the four corners is simply linear interpolation applied twice. In GLSL,
mix(mix(color00, color01, y), mix(color10, color11, y), x)
If you are interested in the center point in particular, this is just
0.25 * (color00 + color01 + color10 + color11)
However, if your goal is to interpolate the four colors smoothly across a square, in a WebGL application, then you don't actually need to perform this calculation yourself, and you don't need to use four triangles!
Create a 2×2 texture with your four colors.
Set its TEXTURE_MAG_FILTER to LINEAR.
Draw your square with that texture applied in the usual fashion, but with texture coordinates ranging from 0.25 to 0.75.
This performs the same interpolation you're looking for, but using built-in facilities. If you wanted, you could also skip using a texture, but still have “texture” coordinates, and use the mix formula above to map the coordinates to your four colors.
The reason this works is that texture coordinates, unlike arbitrary colors, are such that linearly interpolating between 3 points gives you non-degenerate results which you can then use to lookup the color taking into consideration all 4 color values.

Calculating colours in a colour map

Suppose I have some data to be displayed on a bar chart, and each bar will be coloured according to its height.
Say the bars range in height from a to b.
What is the best way of calculating the numbers in a continuous colour map so that a is assigned a set of RGB values, a+1 is assigned a set of RGB values all the way through to b. The data is continuous.
The colours assigned need to be such that if data point 1 has value x and data point 2 has a value close to x, the colours assigned to data points 1 and 2 will be similar.
Pretty much, depending on what program you're using to do it in, it's fairly straight forward. Think of having 3 columns R G and B (they could be stored multiple different ways).
Pure red is 255 with G and B being 0. Same goes for pure green and blue with their respective colors. Then it's just a matter of covering every possible color you want.
A sample color chart is here
Another option is to use the HSV color system and then convert it to RGB if you really need to have RGB. I personally find working with HSV to be easier and more concise when generating a whole array of usable colors.

Resources