Все статьи
Цвет и CSS

Как извлечь цвета из изображения

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

19 марта 2025
6 мин чтения
ConvertHub
#цвета#изображения#дизайн

Введение

Подобрать цвета для дизайна часто помогают сами изображения. Красивый закат, фото продукта, иллюстрация из Pinterest — всё это может стать источником вдохновения и готовой цветовой палитры. Но вручную «на глаз» определять доминирующие цвета неэффективно и неточно. Нужен инструмент, который проанализирует пиксели и выдаст палитру. В этой статье разберём, как работают такие инструменты, какие алгоритмы используются для выделения доминантных цветов, как применять извлечённую палитру в реальных проектах. Для практики используйте нашинструмент извлечения цветов из изображения.

Зачем извлекать цвета из изображений

У извлечения палитры из изображения есть несколько типичных сценариев:

  • Согласованность с визуалом. Если на странице будет большая фотография, цвета интерфейса лучше подбирать из неё — так дизайн выглядит целостно.
  • Реверс-инжиниринг палитры. Понравилась картинка с красивым сочетанием — извлекаем цвета и используем в своём проекте.
  • Создание превью. Для генерации обложек видео и плейлистов берут доминантный цвет — он становится фоном.
  • Генерация градиентов. Из двух доминантных цветов можно построить градиент, идеально подходящий к исходному фото. Подробнее — в статье проCSS-градиенты.
  • Создание темы. На основе обоев рабочего стола или аватара генерируют цветовые темы интерфейса.

Как работает извлечение цветов

Изображение состоит из пикселей, у каждого из которых есть цвет. Несколько миллионов пикселей — это несколько миллионов цветов (с учётом антиалиасинга). Напрямую работать с таким объёмом неэффективно. Алгоритмы кластеризации группируют похожие цвета и выдают небольшой набор наиболее частых.

Основные этапы алгоритма:

  1. Загрузка изображения в Canvas через drawImage.
  2. Получение массива пикселей через getImageData.
  3. Уменьшение выборки — часто берут каждый 4-й или 10-й пиксель, чтобы ускорить обработку.
  4. Кластеризация — группировка похожих цветов.
  5. Сортировка кластеров по частоте и выбор топ-N.

Алгоритмы кластеризации

Для извлечения цветов используют несколько алгоритмов, у каждого свои плюсы и минусы.

K-means

Классический алгоритм кластеризации. Задаётся число кластеров K (5–6 для палитры), алгоритм итеративно распределяет пиксели по кластерам и пересчитывает центры. Хорошо работает, но медленный на больших изображениях.

Median Cut

Рекурсивно делит цветовое пространство пополам по каналу с наибольшим разбросом. Быстрее K-means, результат чуть менее точный, но для палитры из 5–8 цветов разница незаметна.

Octree

Строит восьмеричное дерево цветов. Очень быстрый, используется в большинстве онлайн-инструментов. Даёт стабильный результат для типичных задач.

Color quantization через гистограмму

Строит гистограмму по цветам (например, с шагом 16 значений на канал) и выбирает самые частые. Самый простой и быстрый метод, но менее точный — близкие цвета могут попасть в одну корзину.

Пример извлечения цветов на JavaScript

Покажем простую реализацию на Canvas. Этот код даёт грубое приближение, но демонстрирует принцип:

function extractColors(image, count = 6) {
  const canvas = document.createElement('canvas');
  const ctx = canvas.getContext('2d');

  // Уменьшаем для скорости
  const size = 100;
  canvas.width = size;
  canvas.height = size;
  ctx.drawImage(image, 0, 0, size, size);

  const data = ctx.getImageData(0, 0, size, size).data;
  const buckets = {};

  for (let i = 0; i < data.length; i += 4) {
    const r = data[i] & 0xf0;
    const g = data[i + 1] & 0xf0;
    const b = data[i + 2] & 0xf0;
    const key = (r << 16) | (g << 8) | b;
    buckets[key] = (buckets[key] || 0) + 1;
  }

  return Object.entries(buckets)
    .sort((a, b) => b[1] - a[1])
    .slice(0, count)
    .map(([key, freq]) => {
      const r = (key >> 16) & 0xff;
      const g = (key >> 8) & 0xff;
      const b = key & 0xff;
      return { r, g, b, freq };
    });
}

Здесь используется гистограмма с шагом 16 (маска 0xf0) — это даёт 16³ = 4096 корзин, что достаточно для приличного результата. Для более точного извлечения используйте библиотеки вродеnode-vibrant илиcolor-thief.

Доминантный цвет и палитра

«Доминантный цвет» — самый частый цвет в изображении. Это не всегда тот, что вы ожидаете: на фото леса доминантным может оказаться не зелёный листьев, а серый неба, потому что небо занимает больше площади. Поэтому палитру обычно формируют из топ-N цветов, а не из одного.

Хороший алгоритм также фильтрует слишком близкие цвета: если в палитре два почти одинаковых оттенка синего, их объединяют. Дополнительно можно отсеивать слишком тёмные или слишком светлые цвета, чтобы палитра была «рабочей».

Vibrant и Muted палитры

Библиотека Vibrant (используется в Android и iOS) не просто извлекает частые цвета, а классифицирует их по тональности:

  • Vibrant — насыщенный, среднего значения светлоты.
  • Light Vibrant — насыщенный и светлый.
  • Dark Vibrant — насыщенный и тёмный.
  • Muted — приглушённый, средний.
  • Light Muted — светлый и приглушённый.
  • Dark Muted — тёмный и приглушённый.

Такая классификация удобна для UI: Vibrant используют для акцентов, Muted — для фонов и текста. Это даёт палитру, готовую к применению в интерфейсе, а не просто набор цветов.

Применение извлечённой палитры

Подбор акцентного цвета

Из палитры выберите один-два цвета как акцентные. Проверьте их на контраст с фоном черезинструмент проверки контраста — это обязательно для доступности.

Создание градиента

Возьмите два самых насыщенных цвета из палитры и используйте их вlinear-gradient. Это даёт градиент, идеально сочетающийся с фото на странице.

/* Извлечённая палитра: #2C5F8D, #4A90C2, #B8D4E8, #F4E4C1 */
.hero {
  background: linear-gradient(135deg, #2C5F8D, #4A90C2);
  color: #ffffff;
}

Генерация темы

Цвета из изображения можно превратить в полный набор CSS-переменных для светлой и тёмной темы. Подробнее про построение шкал — в статье про генерацию палитр.

Превью для медиа

Доминантный цвет используют как фон для обложек видео и плейлистов — пока загружается само изображение, пользователь видит «родственный» фон, и переход выглядит плавным.

Сложные случаи

Изображения с градиентом

На фотографии с плавным градиентом «доминантных» цветов нет — каждый пиксель чуть отличается. Алгоритмы кластеризации всё равно найдут центры, но палитра будет выглядеть как набор промежуточных оттенков. В таких случаях полезно увеличить число кластеров или применять фильтр по насыщенности.

Чёрно-белые изображения

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

Перенасыщенные фото

HDR-фото с перенасыщенными цветами даст палитру слишком ярких «кричащих» оттенков. Снизьте насыщенность в CSS через HSL преобразование: тот же Hue, S уменьшить на 20–30%, L — средний. Подробнее — в статье проHSL модель.

Логотипы и иконки

Логотипы часто содержат 1–3 цвета — извлечение палитры тут тривиально. Но алгоритм может «найти» антиалиасинг-переходы на границах. Решение: используйте маску прозрачности или фильтруйте пиксели по альфа-каналу.

Производительность и браузер

Обработка больших изображений в браузере занимает время. Чтобы избежать подвисаний интерфейса:

  • Уменьшайте изображение до 100–200 пикселей по большей стороне перед анализом — этого достаточно для палитры.
  • Используйте requestIdleCallback или Web Worker для тяжёлых вычислений.
  • Кэшируйте результат — повторно извлекать палитру из того же файла не нужно.
  • Не вызывайте извлечение на каждом событии onmousemove— только при загрузке изображения.

Пипетка цвета: точечный выбор

Иногда нужна не вся палитра, а цвет конкретного пикселя. Для этого используется «пипетка» — инструмент, который по клику на изображении выдаёт цвет пикселя. Реализация проста:

canvas.addEventListener('click', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
  const pixel = ctx.getImageData(x, y, 1, 1).data;
  const hex = '#' + [pixel[0], pixel[1], pixel[2]]
    .map(v => v.toString(16).padStart(2, '0'))
    .join('').toUpperCase();
  console.log(hex);
});

Этот приём используют в нашеминструменте извлечения цветов из изображения и впипетке цвета.

Инструменты ConvertHub для работы с цветом

Все инструменты работают в браузере — изображения не загружаются на сервер, что важно для приватности и скорости.

Заключение

Извлечение цветов из изображения — мощный приём, который связывает визуал страницы с её интерфейсом. Алгоритмы кластеризации (K-means, Median Cut, Octree) выделяют доминантные цвета, а классификация по насыщенности и светлоте превращает их в готовую палитру. Используйте наш инструмент извлечения цветов для практики, а затем встраивайте полученные цвета в свой проект: через градиенты, темы, акцентные элементы. Не забывайте проверять контраст черезинструмент проверки контраста и читать статьи прогенерацию палитр итеорию цвета.

Попробуйте эти инструменты

Похожие статьи