Получить используемые названия цветов из изображения

Я хотел бы проверить, какие цвета присутствуют в изображении. Это будет сохранено в базе данных и использовано для формы поиска. (красный=1, зеленый=1, синий=0, желтый=1, черный=1, белый=1 и т. д.)

img = Magick::Image.read('phosto-file.jpg').first
img = img.quantize(10
h = img.color_histogram
pp h
{red=12815, green=18494, blue=15439, opacity=0=>13007,
 red=44662, green=47670, blue=51967, opacity=0=>18254,
 red=17608, green=43331, blue=48321, opacity=0=>11597,
 red=21105, green=25865, blue=39467, opacity=0=>10604,
 red=15125, green=36629, blue=22824, opacity=0=>10223,
 red=52102, green=42405, blue=10063, opacity=0=>12928,
 red=39043, green=28726, blue=40855, opacity=0=>7728,
 red=10410, green=8880, blue=7826, opacity=0=>13795,
 red=25484, green=25337, blue=24235, opacity=0=>7351,
 red=44485, green=12617, blue=11169, opacity=0=>14513}

Как преобразовать 10 значений в названия цветов? красный, зеленый, NOMATCH, желтый, черный, белый и т. д. Нужно только приблизительное название цвета — не LimeGreen, а зеленый и т. д.

С наилучшими пожеланиями. Асбьёрн Морелл


person atmorell    schedule 05.04.2010    source источник
comment
Рубиновый код в вашем примере недействителен: opacity=0=>13007 недействителен.   -  person kikito    schedule 06.04.2010


Ответы (3)


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

Так, например, если у вас есть значение гистограммы (при условии, что 255 значений для каждого цвета, YMMV)

{ red => 10, green => 255, blue => 10 }

Затем вы можете сравнить его с каждым из

{
  red   => {red => 255, green => 0, blue => 0},
  green => {red => 0, green => 255, blue => 0},
  blue  => {red => 0, green => 0, blue => 255}
}

Итак, если вы добавите разницу между всеми элементами, вы получите

{
  red   => 510,
  green =>  20,
  blue  => 510,
}

Таким образом, вы можете четко видеть, что цвет наиболее близок к зеленому.

ОБНОВЛЕНИЕ: добавлено решение в Ruby


def compare_color(color_val)
  colors = {
    :red    => [255,0,0],
    :green  => [0,255,0],
    :blue   => [0,0,255]
  }

  difference = {}

  def compare_array(a1,a2)
    total = 0
    a1.each_index do |x|
      total += (a1[x]-a2[x]).abs
    end
    total
  end

  colors.each do |color,hex|
    difference[color] = compare_array(color_val,hex)
  end

  closest = difference.sort{|a,b| a[1]  b[1]}.first                                                                       [closest,difference]
end

p compare_color([10,255,10])
# [[:green, 20], {:red=>510, :green=>20, :blue=>510}]
person Fotios    schedule 06.04.2010
comment
Этот код мог бы быть проще (с математической точки зрения) для написания, если бы они были массивами, а не хешами, но это лучше передает суть. - person Fotios; 06.04.2010
comment
Очень хорошо. Спасибо за пример. :) - person atmorell; 07.04.2010

Простым способом было бы иметь список значений RGB и соответствующих имен, и вы бы выбрали ближайший подходящий цвет (в пределах некоторой приемлемой погрешности). Только для основных цветов даже очень простая сумма различий в каждом из каналов RGB может дать рабочие результаты, хотя я подозреваю, что у вас закончатся названия цветов, если данные будут выглядеть так. Вы можете найти список названий цветов в сети, возможно, убрав один из таких списков. может помочь. (Обратите внимание, что они обычно предполагают диапазон цветов от 0 до 255, поэтому вам нужно будет преобразовать данные из более широкого диапазона.)

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

person Arkku    schedule 05.04.2010

Вы можете найти эту запись в моем блоге интересной . Там подробно описано, как решить вашу проблему. Я также выпустил гем ColorNamer, который дает вам ближайший именованный цвет из значения RGB или хэша HTML. Вы также можете использовать любой объект Color.

person retro    schedule 04.10.2010