Answer the question
In order to leave comments, you need to log in
How to find the most similar color?
I confess that I am not strong in algorithms, so I ask this question.
I have a list of colors, it looks like this:
/**
* All colors and their names
*/
@Suppress("SpellCheckingInspection")
val names = mapOf(
"000000" to "Black",
"000080" to "Navy Blue",
"0000C8" to "Dark Blue",
"0000FF" to "Blue",
"000741" to "Stratos",
"001B1C" to "Swamp",
"002387" to "Resolution Blue",
"002900" to "Deep Fir",
"002E20" to "Burnham",
"002FA7" to "International Klein Blue",
object ColorHandler {
/**
* Color sample: 556A74
*/
fun getColorName(color: String): String {
if (color in names.keys)
return names[color]!!
val red = color.slice(R)
val green = color.slice(G)
val blue = color.slice(B)
// what's here???
}
}
val R = 0..1
val G = 2..3
val B = 4..5
Answer the question
In order to leave comments, you need to log in
The simplest is to calculate the sum of the squared distances for each of the components: R, G and B.
For a pair 0000DD, 0000C8
of "distance" will be:
(0x00 - 0x00)^2 + (0x00 - 0x00)^2 + (0xDD - 0xC8)^2 = 441
So count up to each of the certain colors, find the minimum. If speed is not particularly important, then just go through all the named colors (better that it be some kind of list or array, not a map) and calculate some kind of metric (for example, the sum of the squared difference for each channel separately). From the received numbers, look for the minimum and give out the color that gave it.
If you need to work very fast, then you need to represent your nominal colors as points in three-dimensional space, build a kd-tree or r-tree and already look for the closest point to the requested point in it.
Translate channels from strings to numbers, calculate the absolute difference for all channels separately. Add the difference of all to the total difference, The color with the smallest difference will be the desired one.
abs(00 - 00) + abs(00 - 00) + abs(DD - .C8) = difference
Since the question is in the "algorithms" tag, I will describe the following algorithm:
1. Colors in RGB are encoded by three numbers, each of which indicates the intensity of some component.
Red, Green, and Blue, respectively.
2. The hexadecimal format shown uses 6 hexadecimal digits, with two digits for each component in the same order. When converted to a decimal system, this will be a value from 0 to 255.
3. The simplest algorithm is to represent the color as a point in a three-dimensional coordinate system, and find the closest known point to the given one.
Here is a naive solution with exhaustive search and without taking into account shades (pseudocode)
In theory, if there are a lot of colors, then it will really find the closest color, and not some kind of game.
struct Color(red: u8, green: u8, blue: u8);
type ColorName = String;
let KNOWN_COLORS: Map<Color, ColorName> = Map {...};
fn get_nearest_known_color_name(color: Color) -> ColorName {
if KNOWN_COLORS.has(color) {
return KNOWN_COLORS.get(color);
}
var (nearest_color, nearest_color_name) = KNOWN_COLORS.first();
var distance = calculate_distance(nearest_color, color);
for (key, value) of KNOWN_COLORS.skip(1) {
var distance = calculate_distance(key, color);
if distance < distance_to_nearest {
distance_to_nearest = distance;
nearest_color = key;
nearest_color_name = value;
}
}
return nearest_color_name;
}
fn calculate_distance(lhs: Color, rhs: Color) -> f64 {
var r = lhs.red - rhs.red;
var g = lhs.green - rhs.green;
var b = lhs.blue - rhs.blue; // вычитаем один вектор из другого
return sqrt(r^2+g^2+b^2); // считаем длину получившегося вектора по теореме пифагора
}
Technically, dE is used for the color similarity criterion. This formula works in Lab space.
You can calculate the Lab value for each RGB value (suppose it is sRGB) and the color difference is found using ready-made formulas.
www.easyrgb.com/en/math.php
For example sRGB-XYZ-Lab and the difference between two DeltaE CIE colors.
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question