RGB в монохромное преобразование

Как преобразовать значения RGB пикселя в одно монохромное значение?

7 ответов

Решение

Я нашел одно возможное решение в FAQ по цвету. Компонент яркости Y (из системы CIE XYZ) фиксирует то, что люди воспринимают как цвет в одном канале. Итак, используйте эти коэффициенты:

mono = (0.2125 * color.r) + (0.7154 * color.g) + (0.0721 * color.b);

Эта статья MSDN использует (0.299 * color.R + 0.587 * color.G + 0.114 * color.B);

Эта статья Википедии использует (0.3* color.R + 0.59 * color.G + 0.11 * color.B);

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

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

Если вы преобразуете цветные фотографии в черно-белые, этот процесс может быть очень сложным и субъективным, требующим специальной настройки для каждого изображения. Для идеи, что может быть вовлечено, взгляните на это руководство от Adobe для Photoshop.

Воспроизведение этого в коде будет довольно сложным, и все же потребует вмешательства пользователя, чтобы получить полученное изображение эстетически "идеальным" (что бы это ни значило!).

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

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

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

Логика преобразования любого изображения на основе RGB в монохромное изображение не является тривиальным линейным преобразованием. На мой взгляд, такую ​​проблему лучше решить с помощью методов "цветовой сегментации". Вы можете добиться "цветовой сегментации" с помощью k-средних кластеров.

Смотрите справочный пример с сайта MathWorks.

https://www.mathworks.com/examples/image/mw/images-ex71219044-color-based-segmentation-using-k-means-clustering

Оригинальная картинка в цветах.

Картинка с цветами

После преобразования в монохромный режим с использованием k-средних Изображение после преобразования в монохромное с использованием кластеризации k-средних

Как это работает?

Соберите все значения пикселей со всего изображения. Из изображения шириной W пикселей и высотой H пикселей вы получите значения цвета W *H. Теперь, используя алгоритм k-средних, создайте 2 кластера (или ячейки) и добавьте цвета в соответствующие ячейки. 2 кластера представляют ваши черные и белые оттенки.

Youtube видео, демонстрирующее сегментацию изображения с помощью k-means? https://www.youtube.com/watch?v=yR7k19YBqiw

Проблемы с этим методом

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

Просто чтобы указать в самостоятельно выбранном ответе, вы должны ЛИНЕАРИЗОВАТЬ значения sRGB, прежде чем сможете применять коэффициенты. Это означает удаление кривой передачи.

Чтобы убрать кривую мощности, разделите 8-битные каналы RG и B на 255,0, затем либо используйте кусочное преобразование sRGB , которое рекомендуется для обработки изображений, ЛИБО можете схитрить и возвести каждый канал в степень 2,2.

Только после линеаризации вы можете применить показанные коэффициенты (которые также не совсем верны в выбранном ответе).

Стандарт 0,2126 0,7152 и 0,0722 . Умножьте каждый канал на его коэффициент и просуммируйте их вместе для Y, яркости. Затем повторно примените гамму к Y и умножьте на 255, затем скопируйте на все три канала, и вы получите полутоновое (монохромное) изображение.

Вот это все сразу в одной простой строчке:

      // Andy's Easy Greyscale in one line.
// Send it sR sG sB channels as 8 bit ints, and
// it returns three channels sRgrey sGgrey sBgrey
// as 8 bit ints that display glorious grey.


  sRgrey = sGgrey = sBgrey = Math.min(Math.pow((Math.pow(sR/255.0,2.2)*0.2126+Math.pow(sG/255.0,2.2)*0.7152+Math.pow(sB/255.0,2.2)*0.0722),0.454545)*255),255);

Вот и все. Если вам не нужно анализировать шестнадцатеричные строки....

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