Можно ли получить средний цвет изображения с помощью RMagick?

Мне нужно знать средний цвет изображения, когда я загружаю его в приложение Ruby on Rails. Можно ли получить среднее значение цвета в HEX или RGB, чтобы использовать этот цвет позже в представлении, отображающем это изображение?

Что-то вроде:

img =  Magick::Image.read(path).first
hexVal = img.getHexValue

Ответы

Ответ 1

Измените размер изображения на один пиксель и получите его цвет?

img =  Magick::Image.read(path).first
pix = img.scale(1, 1)
averageColor = pix.pixel_color(0,0)

Ответ 2

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

Я думаю, что самым простым способом было бы извлечь цветную гистограмму, а затем использовать ее для вычисления среднего. Вероятно, вы захотите quantize изображение, хотя вычисление гистограммы для изображения с большим количеством цветов не является дешевым и, вероятно, бессмысленным занятая работа, если вас просто интересует среднее значение:

total = 0
avg   = { :r => 0.0, :g => 0.0, :b => 0.0 }
img.quantize.color_histogram.each { |c, n|
    avg[:r] += n * c.red
    avg[:g] += n * c.green
    avg[:b] += n * c.blue
    total   += n
}
[:r, :g, :b].each { |comp| avg[comp] /= total }

Это даст вам средний цвет в avg. Но цвет будет в внутреннем формате ImageMagick (т.е. Компоненты будут варьироваться от нуля до Magick::QuantumRange), поэтому вам придется масштабировать их до 0-255:

[:r, :g, :b].each { |comp| avg[comp] = (avg[comp] / Magick::QuantumRange * 255).to_i }

И, наконец, у вас есть компоненты RGB в avg как целые числа от нуля до 255, а средний цвет в шестнадцатеричном формате должен быть тривиальным. Вы можете легко слить это на шаг усреднения, если это необходимо.

Я мог бы быть более умным с итераторами, но .each приятен и ясен, а ясность важнее умения.

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

Ответ 3

Я нашел свое решение (здесь), после того как я проверил все возможности, представленные здесь.

def maincolor()
  img =  Magick::Image.read(self.url).first
  pix = img.scale(1, 1)
  avg_color_hex = pix.to_color(pix.pixel_color(0,0))
  return avg_color_hex
end

Надеюсь, это поможет. Я добавил преобразование в шестнадцатеричный цвет rmagick, потому что это pita с ruby ​​(иначе я использовал sprintf для шестнадцатеричного преобразования)

Ответ 4

Рассмотрите возможность использования miro gem, который, по-видимому, следует за "mu is too short": https://github.com/jonbuda/miro

Ответ 5

В соответствии с @muistooshort - если вся функция квантования делает изображение менее сложным, принимая средние значения цветов пикселей (предполагая) - не будет даже проще, если вы просто квантовали изображение до цвета, например:

img.quantize(1,Magick::RGBColorspace).color_histogram

И просто используйте полученный цвет?