Продолжение: «Сортировка» цветов по различимости

Исходный вопрос

Если вам даны N максимально удаленных цветов (и некоторая соответствующая метрика расстояния), можете ли вы придумать способ отсортировать эти цвета в некотором порядке, чтобы первые M также были достаточно близки к тому, чтобы быть максимально отличным набором?

Другими словами, учитывая набор различных цветов, придумайте такой порядок, чтобы я мог использовать столько цветов, сколько мне нужно, начиная с самого начала, и быть разумно уверенным, что все они различны и что соседние цвета также очень различны (например, голубовато-красный не рядом с красновато-синим).

Рандомизация - это нормально, но определенно не оптимально.

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

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
23
0
2 641
9

Ответы 9

Вы имеете в виду, что из набора 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

Поэтому единственное, что вам нужно будет решить, это насколько близки вы хотите цвета и какая разница будет приемлемой, чтобы сегменты считались разными.

Это также звучит для меня как своего рода график сопротивления, где вы пытаетесь наметить путь наименьшего сопротивления. Если вы инвертируете требования, путь максимального сопротивления, возможно, его можно использовать для создания набора, который с самого начала дает максимальную разницу по мере продвижения, а к концу начинает возвращаться к значениям, близким к другим.

Например, вот один из способов сделать то, что вы хотите.

  1. Рассчитайте расстояние (ref ваш другой пост) от каждого цвета до всех остальных цветов.
  2. Суммируйте расстояния для каждого цвета, это дает вам указание для насколько далеко этот цвет от всех остальных цветов в целом
  3. Сортировать список по расстоянию, спускаясь вниз

Это, по-видимому, приведет к созданию списка, который начинается с цвета, который наиболее удален от всех других цветов, а затем идет вниз, цвета в конце списка будут ближе к другим цветам в целом.

Обновлено: чтение вашего ответа на мой первый пост о пространственном подразделении не совсем соответствовало бы приведенному выше описанию, поскольку цвета, близкие к другим цветам, упадут в конец списка, но предположим, что у вас есть кластер цветов где-то в по крайней мере, один из цветов из этого кластера будет расположен рядом с началом списка, и это будет тот, который обычно наиболее удален от всех остальных цветов в целом. Если в этом есть смысл.

Эта проблема называется квантованием цвета и имеет много хорошо известных алгоритмов: http://en.wikipedia.org/wiki/Color_quantization Я знаю людей, которые реализовали подход октодерева с хорошим эффектом.

Кажется, восприятие важно для вас, в этом случае вы можете рассмотреть возможность работы с воспринимаемым цветовым пространством, таким как YUV, YCbCr или Lab. Каждый раз, когда я их использовал, они давали мне гораздо лучшие результаты, чем один только sRGB.

Преобразование в sRGB и обратно может быть проблемой, но в вашем случае это действительно может упростить алгоритм, и в качестве бонуса он в основном будет работать и для дальтоников!

N максимально удаленных цветов можно рассматривать как набор хорошо распределенных точек в трехмерном (цветовом) пространстве. Если вы можете сгенерировать их из Последовательность Холтона, то любой префикс (первые M цветов) также состоит из хорошо распределенных точек.

Если я правильно понимаю вопрос, вы хотите получить подмножество цветов M с наивысшее среднее расстояние между цветами, учитывая некоторую функцию расстояния d.

Другими словами, рассматривая начальный набор цветов N как большой неориентированный граф, в котором все цвета связаны, вы хотите найти самый длинный путь, который посещает любые узлы M.

Боюсь, что решение проблем с NP-полным графом намного выше моих возможностей, но вы можете попробовать запустить простую физическую симуляцию:

  1. Генерация случайных точек M в цветовом пространстве
  2. Рассчитайте расстояние между каждой точкой
  3. Рассчитайте векторы отталкивания для каждой точки, которая будет перемещать ее от всех других точек (используя 1 / (расстояние ^ 2) в качестве величины вектора)
  4. Просуммируйте векторы отталкивания для каждой точки
  5. Обновите положение каждой точки в соответствии с суммированными векторами отталкивания.
  6. Ограничьте любые координаты за пределами границ (например, отрицательную или большую яркость)
  7. Повторите с шага 2, пока точки не стабилизируются.
  8. Для каждой точки выберите ближайший цвет из исходного набора N

Это далеко не эффективно, но для небольшого M может быть достаточно эффективным и даст почти оптимальные результаты.

Если ваша функция цветового расстояния проста, может быть более детерминированный способ создания оптимального подмножества.

Это не NP-полная. Это либо сортировка O (NLog (N)) по максимуму минимального расстояния до любых цветов индекса O (N), либо по среднему O (N). Это явно O (N + NLog (N)) или O (NLog (N)). В худшем случае вам нужно добавить отсортированные цвета к цветам индекса, сделав его N²Log (N). Найдите лучший, добавьте его в список цветов индекса. Начать сначала.

Tatarize 04.09.2012 00:57
  1. Начнем с двух списков. CandidateColors, который изначально содержит ваши отдельные цвета, и SortedColors, который изначально пуст.
  2. Выберите любой цвет, удалите его из CandidateColors и поместите в SortedColors. Это первый цвет, который будет наиболее распространенным, так что это хорошее место для выбора цвета, который хорошо сочетается с вашим приложением.
  3. Для каждого цвета в CandidateColors рассчитайте его общее расстояние. Общее расстояние - это сумма расстояний от CandidateColor до каждого из цветов в SortedColors.
  4. Удалите цвет с наибольшим общим расстоянием от CandidateColors и добавьте его в конец SortedColors.
  5. Если CandidateColors не пустой, вернитесь к шагу 3.

Этот жадный алгоритм должен дать вам хорошие результаты.

Вы можете просто отсортировать цвета-кандидаты на основе максимального или минимального расстояния до любого из цветов индекса.

Используя евклидово цветовое расстояние:

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, добавить его к индексным цветам и начать все сначала.

Tatarize 04.09.2012 01:01

Другие вопросы по теме