Rgb to Closest Predefined Color

RGB to closest predefined color

You have to calculate the distance to each color, and pick the smallest.

There are a few ways to do this. A simple method would be to calculate the distance would be:

sqrt((r-r1)^2+(g-g1)^2+(b-b1)^2)

A better method might be to incorporate the weighted values to calculate a distance, for instance the values used when converting RGB->YUV:

Y = 0.299 * R + 0.587 * G + 0.114 * B

in that case you would use

sqrt(((r - r1) * .299)^2 + ((g - g1) * .587)^2 + ((b - b1) * .114)^2)

Of course, since you don't need the exact distances, just a comparison, you can and probably should just skip the square root, making the last calculation:

((r - r1) * .299)^2 + ((g - g1) * .587)^2 + ((b - b1) * .114)^2

Changing RGB values of a picture to closest predefined RGB values

I would use distance_matrix to compute the distance across the pixels/reference-colors and then argmin to extract the colors:

# sample image
np.random.seed(1)
avg = np.random.randint(0,255, (10,10,3), dtype=np.uint8)

# in your code, make sure `avg` is an np array
# you can use `cv2.imread` for that purpose, not the BGR color space
# for example
# avg = cv2.imread('image.png')
# agv = cv2.cvtColor(avg, cv2.BGR2RGB) # convert to RGB

# convert main_colors to np array for indexing
main_colors = np.array(main_colors)

# compute the distance matrix
dist_mat = distance_matrix(avg.reshape(-1,3), main_colors)

# extract the nearest color by index
color_idx = dist_mat.argmax(axis=1)

# build the nearest color image with indexing
nearest_colors = main_colors[color_idx].reshape(avg.shape)

# plot
fig, axes = plt.subplots(1,2)
axes[0].imshow(avg) # original image
axes[1].imshow(nearest_colors) # nearest_color
plt.show()

Output:

Sample Image

PHP - Find the closest RGB to predefined RGB from list

Try it like this:

$inputColor = array(20,40,80);

function compareColors($colorA, $colorB) {
return abs($colorA[0] - $colorB[0]) + abs($colorA[1] - $colorB[1]) + abs($colorA[2] - $colorB[2]);
}

$selectedColor = $colors[0];
$deviation = PHP_INT_MAX;

foreach ($colors as $color) {
$curDev = compareColors($inputColor, $color);
if ($curDev < $deviation) {
$deviation = $curDev;
$selectedColor = $color;
}
}

var_dump($selectedColor);

The advantage of this solution is that you can easily replace the comparison function. It might also be possible to use

Disclaimer: There might be more elegant ways of implementation, perhaps leveraging map.

Closest RGB color from list of colors

Precomputing a full lookup table is not so unthinkable nowadays. As long as you have less than 256 reference colors, the required array has 256³ (not 255³) entries, which is 17 MB. (The double for 65536 colors.) But you really need good reasons to use such a device.

If the number of colors is reasonable, the naive solution is quite acceptable.

For larger number of colors (say from 10 up), several practical solutions are possible:

  • a kD-tree (where k=3); query time close to O(Log N);

  • an octree; query time close to O(Log N) if the colors are not clustered;

  • a grid (for instance 4096 cells of size 16); query time O(N), but in lucky cases, the asymptotic constant can be made very small.

The tools of computational geometry might suggest a 3D Voronoi diagram combined to a locator in a 3D subdivision, but these are sophisticated and pretty hard to implement, even though they will support a guaranteed O(Log N) query time.

I would personally favor a kD-tree.

Given an RGB value what would be the best way to find the closest match in the database?

Consider a color as a vector in 3-dimensional space, you can then easily compute the difference by using 3d pythagoras:

d = sqrt((r2-r1)^2 + (g2-g1)^2 + (b2-b1)^2)

However, note that due to colors being subject to interpretation by not-so-perfect eyes, you might want to adjust the colors to avoid them having the same importance.

For instance, using a typical weighted approach:

d = sqrt(((r2-r1)*0.3)^2 + ((g2-g1)*0.59)^2 + ((b2-b1)*0.11)^2)

Since eyes are most sensitive to green, and least sensitive to blue, two colors that differ only in the blue component must thus have a larger numeric difference to be considered "more different" than one that is the same numeric difference in the green component.

There's also various ways to optimize this calculation. For instance, since you're not really interested in the actual d value, you can dispense with the square root:

d =   ((r2-r1)*0.30)^2
+ ((g2-g1)*0.59)^2
+ ((b2-b1)*0.11)^2

Note here that in many C-syntax-based programming languages (like C#), ^ does not mean "raise to the power of", but rather "binary exclusive or".

So if this was C#, you would use Math.Pow to calculate that part, or just expand and do the multiplication.

Added: Judging by the page on Color difference on Wikipedia, there's various standards that try to handle perceptual differences. For instance, the one called CIE94 uses a different formula, in the L*C*h color model that looks like it's worth looking into, but it depends on how accurate you want it to be.

Find the closest RGB value from a table in javascript/nodejs

RGB is a 3-dimensional space. Consider a color as a point in 3d space, you should find most closest distance between two points by using 3d pythagoras.

const colors = [
[0,0,255,0],
[1,255,165,0],
[2,0,0,255],
[3,255,192,203],
[4,165,42,42],
[5,255,255,255],
[6,0,0,0],
[7,230,230,350],
[8,255,255,0],
[9,0,0,0],
]

function get_closest_color(colors, [r2, g2, b2]) {
const [[closest_color_id]] = (
colors
.map(([id, r1,g1,b1]) => (
[id, Math.sqrt((r2-r1)**2 + (g2-g1)**2 + (b2-b1)**2)]
))
.sort(([, d1], [, d2]) => d1 - d2)
);
return colors.find(([id]) => id == closest_color_id);
}

const closest_color = get_closest_color(colors, [230, 200,0]);
console.log(closest_color);

Python - Find the closest color to a color, from giving list of colors

You want to find the sum of the absolute difference between the red, green and blue numbers and choose the smallest one.

from math import sqrt

COLORS = (
(181, 230, 99),
(23, 186, 241),
(99, 23, 153),
(231, 99, 29),
)

def closest_color(rgb):
r, g, b = rgb
color_diffs = []
for color in COLORS:
cr, cg, cb = color
color_diff = sqrt((r - cr)**2 + (g - cg)**2 + (b - cb)**2)
color_diffs.append((color_diff, color))
return min(color_diffs)[1]

closest_color((12, 34, 156))
# => (99, 23, 153)

closest_color((23, 145, 234))
# => (23, 186, 241)

EDIT: Improved code and used Euclidian distance calculation Sven mentioned above instead of basic diff sum.

Finding nearest match RGB color from array of colors

There are many different ways to determine color "distance."

There's absolute distance, i.e. the sum of the differences between each channel value:

/**
* Find the "naive" difference between two colors.
* @param int[] $color_a Three-element array with R,G,B color values 0-255.
* @param int[] $color_b Three-element array with R,G,B color values 0-255.
* @return int
*/
function absoluteColorDistance(array $color_a, array $color_b): int {
return
abs($color_a[0] - $color_b[0]) +
abs($color_a[1] - $color_b[1]) +
abs($color_a[2] - $color_b[2]);
}

There's also difference in luminosity, which will give more of a color-independent comparison:

/**
* Find the difference between two colors' luminance values.
* @param int[] $color_a Three-element array with R,G,B color values 0-255.
* @param int[] $color_b Three-element array with R,G,B color values 0-255.
* @return int
*/
function luminanceDistance(int $color_a, int $color_b): int {
$luminance_f = function ($red, $green, $blue): int {
// Source: https://en.wikipedia.org/wiki/Relative_luminance
$luminance = (int) (0.2126 * $red + 0.7152 * $green + 0.0722 * $blue);
return $luminance;
};

return abs(
$luminance_f($color_a[0], $color_a[1], $color_a[2]) -
$luminance_f($color_b[0], $color_b[1], $color_b[2])
);
}

Once you figure out how to compare colors, the next problem you need to solve is finding the color with the least distance from your target color:

$nearest_distance = null;
$nearest_color = null;
foreach ($palate as $test_color) {
$test_distance = luminanceDistance($test_color, $rgbcolor);
if (isset($nearest_distance)) {
if ($nearest_distance > $test_distance) {
// found a closer color
$nearest_distance = $test_distance;
$nearest_color = $test_color;
}
} else {
$nearest_color = $test_color;
$nearest_distance = $test_distance;
}
}


Related Topics



Leave a reply



Submit