Если вам даны N максимально удаленных цветов (и некоторая соответствующая метрика расстояния), можете ли вы придумать способ отсортировать эти цвета в некотором порядке, чтобы первые M также были достаточно близки к тому, чтобы быть максимально отличным набором?
Другими словами, учитывая набор различных цветов, придумайте такой порядок, чтобы я мог использовать столько цветов, сколько мне нужно, начиная с самого начала, и быть разумно уверенным, что все они различны и что соседние цвета также очень различны (например, голубовато-красный не рядом с красновато-синим).
Рандомизация - это нормально, но определенно не оптимально.
Уточнение: учитывая некоторый большой и визуально различимый набор цветов (скажем, 256 или 1024), я хочу отсортировать их так, чтобы, когда я использую первые, скажем, 16 из них, я получал относительно визуально отличное подмножество цветов. Это примерно эквивалентно тому, что я хочу отсортировать этот список из 1024, так что чем ближе отдельные цвета визуально, тем дальше друг от друга они находятся в списке.





Вы имеете в виду, что из набора N цветов вам нужно выбрать M цветов, где M - лучшее представление N цветов в пространстве M?
В качестве лучшего примера уменьшите истинный цвет (24-битное цветовое пространство) до 8-битного отображаемого цветового пространства (GIF?).
Для этого существуют алгоритмы квантования, такие как алгоритм Адаптивное пространственное деление, используемый ImageMagic.
Эти алгоритмы обычно не просто выбирают существующие цвета из исходного пространства, но создают новые цвета в целевом пространстве, которые наиболее близко напоминают исходные цвета. В качестве упрощенного примера, если у вас есть 3 цвета в исходном изображении, где два красных (с разной интенсивностью или голубоватыми оттенками и т. д.), А третий синий, и его нужно уменьшить до двух цветов, целевое изображение может иметь красный цвет. это какое-то среднее из двух исходных красных + синий цвет из исходного изображения.
Если вам нужно что-то еще, то я не понял вашего вопроса :)
Вы можете разделить их на формат RGB HEX, чтобы вы могли сравнить R с R другого цвета, то же самое с G и B.
Тот же формат, что и HTML
XX XX XX
RR GG BB
00 00 00 = black
ff ff ff = white
ff 00 00 = red
00 ff 00 = green
00 00 ff = blue
Поэтому единственное, что вам нужно будет решить, это насколько близки вы хотите цвета и какая разница будет приемлемой, чтобы сегменты считались разными.
Это также звучит для меня как своего рода график сопротивления, где вы пытаетесь наметить путь наименьшего сопротивления. Если вы инвертируете требования, путь максимального сопротивления, возможно, его можно использовать для создания набора, который с самого начала дает максимальную разницу по мере продвижения, а к концу начинает возвращаться к значениям, близким к другим.
Например, вот один из способов сделать то, что вы хотите.
Это, по-видимому, приведет к созданию списка, который начинается с цвета, который наиболее удален от всех других цветов, а затем идет вниз, цвета в конце списка будут ближе к другим цветам в целом.
Обновлено: чтение вашего ответа на мой первый пост о пространственном подразделении не совсем соответствовало бы приведенному выше описанию, поскольку цвета, близкие к другим цветам, упадут в конец списка, но предположим, что у вас есть кластер цветов где-то в по крайней мере, один из цветов из этого кластера будет расположен рядом с началом списка, и это будет тот, который обычно наиболее удален от всех остальных цветов в целом. Если в этом есть смысл.
Эта проблема называется квантованием цвета и имеет много хорошо известных алгоритмов: http://en.wikipedia.org/wiki/Color_quantization Я знаю людей, которые реализовали подход октодерева с хорошим эффектом.
Кажется, восприятие важно для вас, в этом случае вы можете рассмотреть возможность работы с воспринимаемым цветовым пространством, таким как YUV, YCbCr или Lab. Каждый раз, когда я их использовал, они давали мне гораздо лучшие результаты, чем один только sRGB.
Преобразование в sRGB и обратно может быть проблемой, но в вашем случае это действительно может упростить алгоритм, и в качестве бонуса он в основном будет работать и для дальтоников!
N максимально удаленных цветов можно рассматривать как набор хорошо распределенных точек в трехмерном (цветовом) пространстве. Если вы можете сгенерировать их из Последовательность Холтона, то любой префикс (первые M цветов) также состоит из хорошо распределенных точек.
Если я правильно понимаю вопрос, вы хотите получить подмножество цветов M с наивысшее среднее расстояние между цветами, учитывая некоторую функцию расстояния d.
Другими словами, рассматривая начальный набор цветов N как большой неориентированный граф, в котором все цвета связаны, вы хотите найти самый длинный путь, который посещает любые узлы M.
Боюсь, что решение проблем с NP-полным графом намного выше моих возможностей, но вы можете попробовать запустить простую физическую симуляцию:
Это далеко не эффективно, но для небольшого M может быть достаточно эффективным и даст почти оптимальные результаты.
Если ваша функция цветового расстояния проста, может быть более детерминированный способ создания оптимального подмножества.
Этот жадный алгоритм должен дать вам хорошие результаты.
Вы можете просто отсортировать цвета-кандидаты на основе максимального или минимального расстояния до любого из цветов индекса.
Используя евклидово цветовое расстояние:
public double colordistance(Color color0, Color color1) {
int c0 = color0.getRGB();
int c1 = color1.getRGB();
return distance(((c0>>16)&0xFF), ((c0>>8)&0xFF), (c0&0xFF), ((c1>>16)&0xFF), ((c1>>8)&0xFF), (c1&0xFF));
}
public double distance(int r1, int g1, int b1, int r2, int g2, int b2) {
int dr = (r1 - r2);
int dg = (g1 - g2);
int db = (b1 - b2);
return Math.sqrt(dr * dr + dg * dg + db * db);
}
Хотя вы можете заменить его чем угодно. Ему просто нужна процедура цветового расстояния.
public void colordistancesort(Color[] candidateColors, Color[] indexColors) {
double current;
double distance[] = new double[candidateColors.length];
for (int j = 0; j < candidateColors.length; j++) {
distance[j] = -1;
for (int k = 0; k < indexColors.length; k++) {
current = colordistance(indexColors[k], candidateColors[j]);
if ((distance[j] == -1) || (current < distance[j])) {
distance[j] = current;
}
}
}
//just sorts.
for (int j = 0; j < candidateColors.length; j++) {
for (int k = j + 1; k < candidateColors.length; k++) {
if (distance[j] > distance[k]) {
double d = distance[k];
distance[k] = distance[j];
distance[j] = d;
Color m = candidateColors[k];
candidateColors[k] = candidateColors[j];
candidateColors[j] = m;
}
}
}
}
Хотя на самом деле это может выбрать два очень похожих цвета из кандидатаColors. Возможно, вы захотите просто найти лучший вариант кандидатаColor, добавить его к индексным цветам и начать все сначала.
Это не NP-полная. Это либо сортировка O (NLog (N)) по максимуму минимального расстояния до любых цветов индекса O (N), либо по среднему O (N). Это явно O (N + NLog (N)) или O (NLog (N)). В худшем случае вам нужно добавить отсортированные цвета к цветам индекса, сделав его N²Log (N). Найдите лучший, добавьте его в список цветов индекса. Начать сначала.