RGB в монохромное преобразование
Как преобразовать значения RGB пикселя в одно монохромное значение?
7 ответов
Эта статья 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.
Оригинальная картинка в цветах.
После преобразования в монохромный режим с использованием 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);
Вот и все. Если вам не нужно анализировать шестнадцатеричные строки....