Я уверен, что многим программистам знакома формула:

Y = 0.299 R + 0.587 G + 0.114 B

А уж тот, кто плотно работал с графикой, знает эти цифры буквально наизусть — как в былые времена эникейщики запоминали серийники Windows. Иногда коэффициенты округляют до второго знака, иногда уточняют до четвертого, но каноническая форма именно такая.

Вычисляет она относительную яркость цвета (relative luminance или в некоторых контекстах luma; не путать с lightness и brightness) и широко применяется для преобразования цветного RGB-изображения в Grayscale и связанных с этим задач.

Формула растиражирована и процитирована в тысячах статей, форумных обсуждений и ответов на StackOverflow… Но дело в том, что единственно-правильное её место — на свалке истории. Использовать её нельзя. Однако же используют.

Но почему нельзя? И откуда же взялись именно такие коэффициенты?

Мини-экскурс в историю


Есть такая международная организация, которая разрабатывает рекомендации (де-факто стандарты) для сферы телерадиокоммуникаций — ITU.

Интересующие нас параметры прописаны в рекомендациях ITU-R BT.601, принятых в 1982 году (по ссылке обновленная редакция). Уже на этом моменте можно слегка удивиться — где мы и где 82-ой год? Но это только начало.

Циферки перекочевали туда из рекомендаций ITU-R BT.470 от 1970 года (по ссылке также обновленная редакция).

А они, в свою очередь — наследие цветовой модели YIQ, которая была разработана для североамериканской системы телевещания NTSC в 1953 году! К нынешним компьютерам и гаджетам она имеет отношение чуть более, чем никакое.

Никому не напоминает байку про связь космических кораблей с шириной древнеримской лошадиной задницы?

Современные колориметрические параметеры начали выкристаллизовываться в 1970 году с модернизацией систем PAL/SECAM. Примерно в это же время американцы придумали свою спецификацию SMPTE-C на аналогичные люминофоры, но NTSC перешла на них только в 1987 году. Я не знаю наверняка, но подозреваю, что именно этой задержкой объясняется сам факт рождения пресловутых Rec.601 — ведь по большому счету, они морально устарели уже к моменту своего появления.

Потом в 1990 году случились новые рекомендации ITU-R BT.709, а в 1996 на их основе придумали стандарт sRGB, который захватил мир и царствует (в потребительском секторе) по сей день. Альтернативы ему существуют, но все они востребованы в узкоспецифичных областях. И прошло уже, ни много ни мало, 20 лет — не пора бы уже избавиться от атавизмов окончательно?

Так в чем же конкретно проблема?


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

Любое RGB-пространство (а YIQ это преобразование над моделью RGB) определяется тремя базовыми параметрами:

1. Хроматическими координатами трех основных цветов (они называются primaries);
2. Хроматическими координатами белой точки (white point или reference white);
3. Гамма-коррекцией.

Хроматические координаты принято задавать в системе CIE xyY. Регистр букв в данном случае важен: cтрочные xy соответствуют координатам на хроматической диаграмме (всем известная «подкова»), а заглавный Y — это яркость из вектора CIE XYZ.

Теперь посмотрим на компоненту Y у всех первичных цветов NTSC (я пометил их розовым):


* Оригинал таблицы со многими другими пространствами на сайте Брюса Линдблума.

Знакомая цифирь, правда? Вот и ответ на вопрос «откуда взялось?»

А проблема в том, что используемое сегодня пространство sRGB существенно отличается от системы 60-летней давности. И дело даже не в том, что из них лучше или хуже — они просто разные:



Треугольник шире и смещён в сторону. Другая белая точка. К слову сказать, иллюминант C уже очень давно признан deprecated в пользу иллюминантов серии D вообще и наиболее популярного D65 в частности. Тело цветового охвата другое — соответственно, результаты вычислений яркости окажутся неадекватны реальности.

Вы можете спросить: а зачем древнему NTSC охват (практически совпадает с охватом Adobe RGB 1998!) настолько больше, чем у современного sRGB? Я не знаю. Совершенно очевидно, что кинескопы того времени покрыть его не могли. Быть может, хотели сделать задел на будущее?

Как правильно?


Относительные яркости первичных цветов в пространстве sRGB приведены в таблице выше (помечены зеленым) — их и нужно использовать. На практике обычно делают округление до 4-х знаков:

Y = 0.2126 R + 0.7152 G + 0.0722 B

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

Этой формулы хватит для 99% типичных случаев. Её использует во всех своих спецификациях W3C (например, матричные фильтры в SVG).
Если вам нужна бОльшая точность, придется вычислять L*, но это отдельная большая тема. Неплохой ответ на StackOverflow, который дает отправные точки для дальнейшего чтения.
Если изображение у вас в другом цветовом пространстве (Adobe RGB, ProPhoto RGB и т.д.) — коэффициенты будут свои; их можно найти в вышеупомянутой таблице Брюса Линдблума.

Почему меня это волнует?


Как уже было сказано выше, за многие годы формула растиражирована на несметном количестве сайтов, и они сидят в топе всех поисковиков (например). Источники посерьезнее часто приводят обе формулы, но не делают между ними должного различия, преподнося их как равноправные альтернативы. Характерный пример на StackОverflow: Formula to determine brightness of RGB color — ответы довольно подробные, но человеку не в теме сложно сделать осознанный выбор.

Справедливости ради, серьезные проекты такими ошибками почти не страдают — авторы не брезгуют сверяться со стандартами, да и фидбек аудитории работает (хотя и там не обходится без исключений). А вот рядовой программист, которому нужно побыстрее решить задачу, вбивает в поисковик что-то типа «rgb to grayscale», и тот подсовывает ему сами знаете что. Формулу продолжают находить и копипастить до сих пор! Феноменальная живучесть.

На розыск этих примеров я потратил около 20 минут:


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

А поводом для написания этой заметки стал слайд из доклада Василики Климовой с HolyJS-2016 — с той же самой доисторической формулой. Понятно, что формула не повлияла на основной смысл выступления, но наглядно продемонстрировала ваши шансы ненароком её нагуглить в 2016 году.

Подытоживая: если увидите в чьем-то действующем коде последовательность 299/587/114 — кидайте автору ссылку на эту заметку.

update 1
В комментариях настоятельно просят примеры. Но тут не всё так просто, как кажется.
Если взять произвольную картинку и перевести её в ч/б двумя способами — это не даст вообще ничего. Картинки будут просто немного разными. Зритель сможет только оценить, какой вариант ему субъективно симпатичнее. А дело-то не в этом! Дело в том, какой вариант правильнее, точнее.

Немного поразмыслив, я набросал вот такую штуку: codepen.io/dom1n1k/pen/LZWjbj

Скрипт генерирует 2 раза по 100 случайных цветов, подбирая компоненты так, чтобы яркость всех кубиков была теоретически одинакова (Y = 0.5). То есть всё поле целиком должно субъективно восприниматься как можно более однородно (однородно именно с точки зрения яркости, не учитывая разные тона).
Слева старая «неправильная» формула, справа новая «правильная». Справа однородность действительно заметно выше. Хотя и не идеальна, конечно — для бОльшей точности нужно вычислять перцептивную светлоту L*.

update 2.1
Ещё возник вопрос по поводу гаммы. Его подняло уже минимум 3 человека, поэтому тоже вынесу в апдейт. Вопрос на самом деле непростой и отчасти даже философский (вполне потянет на отдельную статью).

Если говорить строго — да, для перевода картинки в ч/б вид гамму нужно декодировать. Но на практике (в задачах, не связанных с точной колориметрией) этот шаг часто опускают ради простоты и производительности. Например, Photoshop при конвертации в grayscale гамму учитывает, а одноименный CSS-фильтр (MDN) — нет.

С точки зрения корректности результата, выбор весовых коэффициентов и пересчёт гаммы — взаимодополняющие вещи. Влияет и то, и другое. Разница только в том, что гамма требует дополнительных вычислений, а вот правильные коэффициенты обходятся бесплатно.

Вторая версия демо с учетом гаммы (первая никуда не делась): codepen.io/dom1n1k/pen/PzpEQX
Получилось, конечно, точнее.
Поделиться с друзьями
-->

Комментарии (118)


  1. alexkunin
    28.06.2016 15:11
    +20

    Очень не хватает примера: исходная цветная картинка, ч/б по старой формуле, ч/б по новой формуле.


    1. alexkunin
      28.06.2016 15:53
      +7

      Вот фиддл с Леной: http://jsfiddle.net/x6W4C/2/. Разница есть, на глаз ощутима, но не принципиальна. На каком-нибудь другом изображении может и получше было бы видно.


      1. degorov
        28.06.2016 16:49
        +1

        В тёмной части спектра разница вполне заметна даже так.


        1. petrovnn
          28.06.2016 20:14

          Слева старая «неправильная» формула, справа новая «правильная». Справа однородность действительно заметно выше.

          Объясните тогда, почему в grayscale, слева как раз более однородно?

          image


          1. dom1n1k
            28.06.2016 20:36
            +1

            Мой вариант

            Нужно выяснять чем и как конвертировали в grayscale, какие настройки и т.д.
            Случайно не функцией Desaturate в ФШ? Она работает иначе — в модели HSB (т.е. совершенно не перцептивно).


    1. bertmsk
      28.06.2016 15:55
      -3

      Тогда ценность багета автора резко упадет, поскольку картинки практически идентичные

      Исходная:
      />

      Со старыми коэффициентами
      />

      С новыми коэффициентами
      />


    1. DistortNeo
      28.06.2016 16:06
      +2

      Кстати, формула все равно неверная: при вычислении Y нужно учитывать гамму.

      Вот статейка, где можно посмотреть результаты:
      www.cgm.computergraphics.ru/files/cgm/rgb2gray_article.pdf


      1. dom1n1k
        28.06.2016 21:38
        +1

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


    1. dom1n1k
      28.06.2016 18:04

      См. апдейт


      1. alexkunin
        28.06.2016 18:38
        +1

        Все вы верно в апдейте написали. Но! Нет прямого и простого примера. В вашем кодепене случайные цвета немного отличаются (и так как они случайны, разница эта на глаз не видна — нужно комплексное изображение, чтобы глаз распознал контент и увидел различия), и это не привносит ясности: все еще нет примера, демонстрирующего видимую, ощутимую разницу. Да, оценка этой разницы весьма субъективна (большинство, наверное, выбрало бы более контрастный вариант, т.к. «ну четче же»), и к правильности отношения не имеет.

        Я бы так написал в статье: «вот пример изображения — до, после старой формулы, после новой; как видите, разница есть, хоть и невелика, но хочу обратить ваше внимание, что...» — дальше ваш пассаж про правильность.

        Просто без этого ваша статья о переводе цветных изображений в черно-белые осталась без изображений, т.е. «теоретическое махание руками» (как если бы где-то на природе человек без бумажки и карандаша буквально на пальцах что-то пытался пояснить — но мы ж не на природе, в нашем распоряжении любые инструменты). С точки зрения науки все верно. С точки зрения «заинтересовать читателя» — нужны примеры, без которых средний читатель останется неудовлетворенным.


      1. sasha1024
        28.06.2016 19:05

        Совет: я бы модифицировал Ваш пример следующим образом (но мне лень)…

        У Вас (псевдокод):
        var ethalonY := 0.5, count := 100;
        for (var n := 0; n!=count; ++n) {
        var r := random(), b := random();
        var g1 := getGreenFromRedBlueY(r, b, ethalonY, [0.299, 0.587, 0.114]);
        var g2 := getGreenFromRedBlueY(r, b, ethalonY, [0.2126, 0.7152, 0.0722]);
        putLeft(r, g1, b); putRight(r, g2, b);
        }

        Надо:
        var ethalonY := 0.5, count := 100;
        for (var n := 0; n!=count; ++n) {
        var h := n / count * 360°;
        var (r, g, b) := hslToRgb(h, 100%, 50%);
        var (r1, g1, b1) := normalizeToY(r, g, b, ethalonY, [0.299, 0.587, 0.114]);
        var (r2, g2, b2) := normalizeToY(r, g, b, ethalonY, [0.2126, 0.7152, 0.0722]);
        putLeft(r1, g1, b1); putRight(r2, g2, b2);
        }

        Т.е.:
        1. Не подбирать зелёный по красному и синему, а подбирать все 3 канала по hue.
        2. Меньше рандома, просто перебрать все значения hue подряд с каким-то шагом.


        1. sasha1024
          28.06.2016 19:12

          А ещё лучше: не слева одна картинка, справа другая, а отобразить получившиеся цвета в виде 2 рядов один под другим:

          ???????????????????????????????????????????????????????????????????????????????? (YIQ)
          ???????????????????????????????????????????????????????????????????????????????? (sRGB)

          Какой ряд равномернее по яркости — тот и лучше.


          1. dom1n1k
            28.06.2016 19:27
            +1

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


            1. sasha1024
              28.06.2016 19:34

              Может быть, это всё субъективно, мне кажется, так было бы лучше, но, может быть, я неправ.
              Мой основной коммент был выше про «не G по (R:=rand(), B:=rand(), Y:=0.5), а L по (H:=seq(), S:=100%, Y:=0.5)».


              1. dom1n1k
                28.06.2016 19:39

                Эмм… не получится же: координата L в HSL и Y в XYZ — это разные параметры. По смыслу немного похожие, но разные.


                1. sasha1024
                  28.06.2016 20:09

                  А где я говорил, что они одинаковые?


                  1. dom1n1k
                    28.06.2016 21:50

                    Тогда я не совсем понял, какие преимущества сулит предложение. Лучше форкнуть и показать как надо :)


      1. DrSmile
        28.06.2016 20:34

        Как уже неоднократно писали, учет гаммы так же важен, как и цифры интенсивности. Так что «рядовой программист», в итоге, все равно сделает неправильно, без учета нелинейности цветового пространства, независимо от того, какие магические числа он нагуглит. Не позорьтесь, исправьте в апдейте

        function stringify (r, g, b) {
        	return 'rgb(' + Math.round(255 * Math.pow(r, 0.45)) + ',' +
                                Math.round(255 * Math.pow(g, 0.45)) + ',' +
                                Math.round(255 * Math.pow(b, 0.45)) + ')';
        }
        


        1. dom1n1k
          28.06.2016 21:40

          См. второй апдейт


          1. DrSmile
            29.06.2016 00:00

            Очевидно, что написанное там не соответствует истине.

            Пусть у нас есть два цвета — красный {1, 0, 0} и темно зеленый {0, 0.5, 0} в нелинейном цветовом пространстве с гаммой 2.2. Забив на гамму и применяя формулу напрямую, получим яркости 0.2126 и 0.3576. Если же корректно преобразовать цвета в линейное пространство, рассчитать яркость и вернуть в нелинейное, то получится 0.4947 и 0.4293. Налицо принципиальное изменение отношения.

            Вообще, если пытаться приближать правильную формулу без степеней, то стоит хотя бы возвести в степень 1/2.2 сами коэффициенты, т. е. использовать Y = 0.4948R + 0.8587B + 0.3028G. Будет работать правильно хотя бы для чистых цветов. Для смешанных, в том числе белого, будет врать, поэтому надо заново нормировать на единицу. В общем, как я и говорил, «рядовой программист» будет врать независимо от выбранных магических чисел.


            1. dom1n1k
              29.06.2016 01:49

              Нашел у себя ошибку в выкладках, касающуюся этого момента. Но исследовать её буду уже завтра.


            1. dom1n1k
              29.06.2016 16:41

              Поэкспериментировал я с Монте-Карло — генерировал рандомные пары цветов и проверял, в каком количестве случаев отношение яркости сохранятся при разных методах. За эталон принимал соотношение CIE L*.

              Метод       В лоб     С учетом гаммы
              Rec.601     92.6%     94.3%
              Rec.709     94.1%     100%
              

              Результаты вполне устойчивые, разные эксперименты дают разброс <0.1%.
              Выводы в общем-то капитанские: влияет и то, другое. Разница лишь в том, что гамма просаживает производительность, а коэффициенты достаются бесплатно.


  1. VioletGiraffe
    28.06.2016 15:13

    А в контексте YUV исходные коэффициенты валидны, или тоже нет?


    1. dom1n1k
      28.06.2016 15:40

      YUV — это просто преобразование системы координат над RGB-пространством (точнее семейство из нескольких родственных преобразований).
      В какой пропорции смешивать — зависит от конкретного RGB-пространства, а оно в свою очередь зависит от контекста задачи.
      Если вы вдруг действительно работаете с NTSC-видеосигналом — исходная формула верна. Но только для него. Для других пространств — нет.


  1. Cthutq66a
    28.06.2016 15:17

    А если ч/б картинка используется только для вычислений(например детектор границ) есть разница как ее считать по RGB?


    1. alexkunin
      28.06.2016 15:19

      Контрасты будут другие. Навскидку, новая модель «приглушает» красный и синий каналы, а зеленый наоборот «усиливает».


      1. Cthutq66a
        28.06.2016 15:23

        Это более — менее очевидно. Вопрос скорее — как правильно?


        1. dom1n1k
          28.06.2016 15:29
          +2

          Правильно — использовать те формулы, которые выведены конкретно для вашего рабочего цветового пространства.
          Если это sRGB (подавляющее большинство случаев), то верна формула, которую я привёл (вторая). Если вдруг вы используете что-то иное (Adobe RGB, ProPhoto RGB и так далее) — там будут свои коэффициенты, их можно вывести из таблички Линдблума.


        1. alexkunin
          28.06.2016 16:00

          Правильные коэффициенты зависят от контекста, мне кажется. Если у вас синие буквы (диапазон 0-255) на черном фоне, то умножение на 0.07 оставляет вам диапазон 0-18, примерно 4 бита (а было-то 8!). Я бы постарался не терять столько информации.


          1. evtomax
            30.06.2016 12:38

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


            1. DistortNeo
              30.06.2016 20:11

              Конкретно для вычисления границ можно использовать цветовой градиент Di Zenzo,


        1. sasha1024
          30.06.2016 15:59
          +1

          По хорошему, наверное (я не специалист), следовало бы не переводить вообще в grayscale в данном случае, а делать вычисления на основе формул цветового отличия. Ну это в идеале. Не знаю, как делают на практике.


    1. RouR
      28.06.2016 16:20

      Выше есть ссылка на фиддл с Леной — смотрите на область вокруг носа, полутени лучше видно


    1. darkAlert
      28.06.2016 17:52

      Разница есть, но единственного «правильного» способа нет.
      Изменения формулы rgb_to_gray аналогичны изменению контраста изображения.
      Но это палка о двух концах — увеличим контраст, усилим границы, но получим больше шума. И обратно.

      Проблема в том, что rgb_to_gray преобразование и последующий оператор Собеля это все линейные преобразования. Изменяя коэффициент в формуле rgb_to_gray мы лишь получаем масштабирование, т.е: Sobel(Rgb2Gray(I*A)) = Sobel(Rgb2Gray(I))*B

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


  1. homm
    28.06.2016 15:57

    если увидите в чьем-то действующем коде последовательность 299/587/114 — кидайте автору ссылку на эту заметку.
    Основная проблема в том, что эта заметка на русском. Куда лучше всего всего давать ссылку англоязычным разработчикам (хочу попроваить формулу в Pillow)?


    1. homm
      28.06.2016 16:44

      dom1n1k так что?


      1. dom1n1k
        28.06.2016 16:57
        +3

        Прямой англоязычный аналог мне неизвестен, к сожалению.
        Навскидку в голову приходит известный Color FAQ Чарльза Пойнтона, а конкретнее пункт 9:
        http://www.poynton.com/notes/colour_and_gamma/ColorFAQ.html#RTFToC9


  1. RolexStrider
    28.06.2016 16:14
    +2

    коэффициенты привязаны к технологии воспроизведения цвета

    Именно так и было, но наоборот: привязка изначально была к Ч/Б телевизорам и их особенностям. В целях обратной совместимости. Ну а после… Эти костыли кочуют из руководства в руководство прям аки мировые константы.


  1. Randl
    28.06.2016 16:33

    А разве коэффициенты не зависят от того, в каком цветовом пространстве у нас картинка? Конечно, sRGB сейчас стандарт де-факто, но ведь теоретически изображение может быть и в AdobeRGB, и в ProPhoto, и в чём то еще.


    1. dom1n1k
      28.06.2016 16:42

      Конечно зависят. Об этом есть комментарий выше, и это подразумевается в тексте. Но видимо, нужно уточнить более явно, сейчас сделаю поправку.


      1. Randl
        28.06.2016 16:54

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


        1. dom1n1k
          28.06.2016 17:16
          +2

          Формула не моя, её придумали задолго до меня :) И в настоящее время она определена как стандартная (тем же W3C). Я лишь хочу обратить на неё внимание.

          Что касается разных пространств. Да, конечно, лучше и точнее считать всё по-взрослому. Но это сразу забросит нас в пучину нетривиальной и громоздкой колориметрической математики. Вот так быстро и сходу в ней разобраться сложно — да и не особо нужно, откровенно говоря. В 99% случаев, с которыми сталкивается рядовой программист, это себя не оправдает. Достаточно, чтобы он не использовал заведомо неправильные формулы, которые ему случайно нагуглились.

          Ну а если кто-то решает более серьезные задачи — там, конечно, не обойтись. Но это отдельная и настолько большая тема, по ней пишут толстенные книжки, а не заметки на Хабр.


          1. Randl
            28.06.2016 17:24
            -2

            В 99% случаев визуальной разницей между двумя формулами можно пренебречь. Конечно, лучше и точнее считать по правильной формуле, но принципиальной разницы увидеть не удалось.


            1. silvansky
              28.06.2016 17:34

              Вообще, тут ещё от монитора зависит восприятие. Я тестировал на макбуке и внешнем монике Dell, на встроенном мониторе разница заметна слабее.


              1. Randl
                28.06.2016 17:59

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


            1. dom1n1k
              28.06.2016 17:43
              +4

              Какой-то радикальной, космической разницы — да, не будет.
              Но зачем использовать заведомо неверные коэффициенты, если можно взять верные, и дополнительные трудозатраты для этого равны нулю? :)


  1. amarao
    28.06.2016 16:56
    +2

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

    А тут, вдруг, «координаты цветов». О чём речь, вообще? (Я понимаю, что это айтишные условности по перекладыванию байтиков из системы в систему, но, всё-таки).


    1. dom1n1k
      28.06.2016 17:07
      +7

      Метамерия. Цвет — это ощущение.
      Если коротко, то длина волны однозначно соответствует цвету (и то с некоторыми оговорками) только в том случае, когда она одна — то есть имеем чистый спектральный свет. Если же имеем смесь волн (а на практике так почти всегда), ситуация резко становится намного сложнее.
      Поэтому пришлось придумать свои особые, цветовые системы координат. Причем их много разных и у каждой свои плюсы и минусы.


    1. alexkunin
      28.06.2016 17:17
      +3

      Не спец, и ответ, возможно, тоже глупый.

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

      Есть «человеческая» модель — LMS: ровно по колбочкам глаза все определено, зависимости неровные (заданы таблицей лукапов, так сказать). А есть историческая — XYZ (зависимости заданы формулами, т.е. можно рассчитать). Я бы тоже XYZ выбрал, чтобы не таскать везде таблицы значений.

      Вот тут вся зубодробительность. По ссылке точные определения (формулы) координат.


    1. lockywolf
      28.06.2016 17:38

      >>О чём речь, вообще?

      Если на пальцах:

      На глаз падет электромагнитная волна, зависящая от времени. Это не синусоида!
      Глаз не ловит конкретных отклонений волны, и он не спектроанализатор (это было бы слишком накладно).

      Глаз делает две вещи: режет сигнал по типичному времени (времени реакции) и каждый интервал раскладывает в сумму ряда из всего трёх членов. У этих собственных членов есть собственные функции — это примерно (но не точно!) гауссианы с центрами в длинах волн, которые мы называем «красным», «синим» и «зелёным».

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


  1. sasha1024
    28.06.2016 17:17

    Когда-то в качестве развлечения делал игру. Стратежку. Там выдранные с какого-то сайта фришные картинки юнитов были в синей гамме. Чтобы получить картинки юнитов оппонентов, я делал «цветовой поворот» на 120° и 240° (т.е. R->G, G->B, B->R). Меня удивило, что цвета получались совсем неожиданные (из визуально-синей исходной картинки получались не визуально-красные, а какое-то сиреневые). Погуглил, понял что «мощности» каналов R, G и B неравны, стал подправлять их этими коэффициентами перед/после «поворота» (пробовал и sdtvWeights = [0.299, 0.587, 0.114], и hdtvWeights = [0.2126, 0.7152, 0.0722]). Визуально на моём мониторе с SDTV-коэффициентами выглядело лучше.

    Ещё удивило, что gimp «поворачивает», кажется, вообще, без учёта коэффициентов. По крайней мере, в нём результат поворота получался совсем удручающий.


    1. Randl
      28.06.2016 17:26

      Цветовой поворот удобно делать в HSV, HSL и подобных.


      1. sasha1024
        28.06.2016 17:42

        Эмм, нет. При (стандартном) переводе из RGB в HSL/HSV как раз эти коэфициенты и не учитываются. Т.е. RGB=[0,0,255] даёт L=50% и RGB=[0,255,0] тоже даёт L=50% (несмотря на то, что [0,0,255] — это синий, а [0,255,0] — это салатовый).

        Да и вообще, зачем мне HSL/HSV, если у меня поворот ровно на 120° и 240° — достаточно поменять местами каналы (ну, с поправками, учитывая, что разные каналы имеют разную «мощность»).

        Вот для этих поправок и нужны коэфициенты. Прикол в том, что более древние (и по логике неправильные) SDTV-коэфициенты на моём мониторе давали более правильный результат, чем более новые, рекомендуемые в т.ч. автором этой статьи.


        1. sasha1024
          28.06.2016 17:56

          Возможно, я неправильно их называю SDTV- и HDTV-коэфициентами.
          Вероятно, судя по статье, это YIQ и sRGB (накрайняк — NTSC и HDTV).
          Но у меня в коде переменные почему-то были названы так.


        1. Randl
          28.06.2016 17:56

          Ну так у чисто зеленого и чисто синего одинаковая lightness. Менять надо hue, который в градусах и измеряется.


          1. sasha1024
            28.06.2016 18:00

            Ну так в том-то и дело, что #0000FF — это синий (не голубой), а #00FF00 — это салатовый (не зеленый). Т.е. #00FF00 визуально намного ярче, чем #0000FF.

            Поэтому и нужны эти коэфициенты.

            А если просто менять hue, то получится та же херня, что и в gimp'е.


            1. playermet
              28.06.2016 23:13

              > визуально намного ярче
              Эта характеристика называется «светлота».


              1. sasha1024
                28.06.2016 23:31

                Т.е. lightness. Будем знать.


              1. sasha1024
                30.06.2016 00:43

                Стоп, подождите, Вы меня запутали.
                Если светлота (lightness?) — это то, какой цвет визуально выглядит светлее…
                … то как тогда называется третий параметр (L) в HSL?


                1. playermet
                  30.06.2016 19:13

                  Это он и есть. При L равном 100% в результате будет белый цвет, вне зависимости от остальных настроек. Просто L в HSL регулирует светлоту (близость к белому) без учета текущего тона (hue).


                  1. sasha1024
                    30.06.2016 19:39

                    Ну так в том-то и дело, что #0000FF — это синий (не голубой), а #00FF00 — это салатовый (не зеленый). Т.е. #00FF00 визуально намного ярче, чем #0000FF.

                    Эта характеристика называется «светлота».


                    Тогда Вы сами себе противоречите. Я говорил о том, что #0000FF (синий) и #00FF00 (салатовый) в HSL имеют одинаковое L (50%) — несмотря на то, что #00FF00 визуально выглядит светлее #0000FF'а.

                    P.S.: Т.е. меня интересует «субъективная светлота» (не знаю как называется), а не параметр L в HSL.


                    1. playermet
                      30.06.2016 19:54

                      > Тогда Вы сами себе противоречите
                      Не противоречу. Я лишь дал вам название термина.

                      > Я говорил о том, что #0000FF (синий) и #00FF00 (салатовый) в HSL имеют одинаковое L (50%) — несмотря на то, что #00FF00 визуально выглядит светлее #0000FF'а.
                      Именно это и называется «светлотой» (2).

                      > Т.е. меня интересует «субъективная светлота» (не знаю как называется), а не параметр L в HSL.
                      Объясню по другому. L в HSL отвечает за субъективную светлоту, но HSL не подразумевает что при одинаковом L она всегда будет одинаковой. В Lab эта же светлота, но формула устроена так что результативная светлота полностью определяется L.


                      1. sasha1024
                        30.06.2016 21:11
                        +1

                        Т.е. в HSL параметр L регулирует светлоту (lightness) в пределах тона (hue, H). Короче говоря: если Hцв1=Hцв2, то (Lцв1>Lцв2) ? (цв1 светлее цв2) — но если Hцв1?Hцв2, то (Lцв1>Lцв2) ? (цв1 светлее цв2).


                        1. playermet
                          30.06.2016 21:28

                          Да, все правильно.


          1. sasha1024
            28.06.2016 18:01

            Т.е. HSL/HSV тут никак не поможет (ну, я имею в виду, если не учитывать дополнительно эти коэфициенты, о которых речь в статье).


            1. VioletGiraffe
              28.06.2016 23:05

              Именно потому и недостаточно просто поменять каналы. По-моему, самое продвинутое цветовое пространство для манипуляций над воспринимаемыми цветами — Lab.


              1. sasha1024
                28.06.2016 23:21

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

                Про Lab надо почитать, это интересно; просто для той задачи это было явно излишне.

                Тут я просто отвечал человеку, который зачем-то настойчиво советовал HSL/HSV; и я ему пытался объяснить, что HSL/HSV мне не помог бы (HSL/HSV мне нужен был бы, если бы у меня был поворот не на 120° или 240° ровно, а на другое число; но поворот hue на 120° или 240° это и есть обмен каналов); так как проблему неравноценности RGB каналов сам по себе HSL/HSV бы никак не решал (потому что при стандартных формулах перевода RGB <-> HSL/HSV каналы как раз считаются равноценными), просто была бы лишняя арифметика.


                1. VioletGiraffe
                  28.06.2016 23:28

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


                  1. sasha1024
                    28.06.2016 23:50

                    Странно, что этого ещё нету в стандартном gimp'е или ещё где-то. Потенциально низкое удобство пользования отдельной софтиной меня смущает. Возможно такие софтины уже есть, просто мы не знаем.

                    Ну, формулы RGB<->Lab я как раз нашёл, там (вроде) всё просто:
                    RGB<->sRGB<->«CIE XYZ»<->Lab
                    (1) RGB<->sRGB и sRGB<->«CIE XYZ»
                    (2) «CIE XYZ»<->Lab
                    (Но не знаю насколько просто всё остальное, потому что суть Lab я пока не понимаю.)

                    А какого рода софтину Вы собираетесь делать? Т.е. какой у неё должен быть функционал? (Условно говоря: просто преобразовать 1 цвет типа такого но сложнее или именно работа с изображениями?)


                    1. VioletGiraffe
                      29.06.2016 00:00

                      Спасибо! Википедию, конечно, я читал, (2) я находил, а (1) не смотрел (хотя и понимал, что это где-то задокументировано). Хотел прямое одноходовое преобразование, но хоть так.

                      Софтина именно для обработки изображений, конкретная задача, где нужен (ну или желателен) Lab — составление функции визуальной похожести цветов.


  1. stepik777
    28.06.2016 18:51
    +1

    А не нужно перед вычислением яркости сперва преобразовать sRGB к линейным координатам (то есть убрать гамму), а после опять применить её? Иначе получается, что результат будет зависеть от того, какая используется гамма в конкретном цветовом пространстве.


    1. alexkunin
      28.06.2016 19:25

      Тема зубодробительная, я могу ошибаться, но вы и правы, и не правы — одновременно.

      Формула в статье — исключительно для sRGB. sRGB уже предполагает конкретную гамму — табличка в статье говорит «примерно 2.2». «Примерно» — это потому, что именно в sRGB гамма является функцией (вроде бы от яркости — для черного 1.0, для остального пространства — меняется от 1.0 до 2.4). Это ваше «не правы», на сколько я понимаю, т.к. пространство и его гамма фиксированы по определению.

      Но, вроде, да, учитывать гамму нужно, и формула преобразования должна быть со степенями. Разница в абсолютных числах мизерна, а вот вычислений значительно больше — видимо, поэтому и не заморачиваются. Выше DistortNeo в своем комментарии привел ссылку на обоснование (там и формула). Это ваше «правы», и обоснование ваше верное — преобразование в линейное пространство (на сколько я понимаю, речь только о координате «яркость»).


      1. stepik777
        28.06.2016 19:45

        Понятно, что в sRGB гамма уже фиксированная. Но если взять другое цветовое пространтсво, например Rec. 709, в котором те же коэффициенты, но другая гамма, то рузультат будет выглядеть немного по другому, если не преобразовывать сперва в линейное пространство.


        1. alexkunin
          28.06.2016 20:05

          Тогда не понятно, в чем ваш вопрос состоит.

          Прежде чем использовать коэффициенты, которые подходят только для sRGB, нужно преобразовать изображение в sRGB. Очевидно же.


      1. DistortNeo
        28.06.2016 20:04
        +1

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

        Например, при гамме 2.2 смешение пикселей с интенсивностями 0 и 255 будет равно 186, а не 127.


        1. dom1n1k
          30.06.2016 23:23

          Эта гамма не дает мне покоя уже 2 дня. И вот я погрузился в справочники, провел кое-какие эксперименты и постепенно прихожу к выводу, что тут не всё так однозначно.

          Эксперименты склонят меня к мысли, что для конвертаций (из пространства в пространство и в частности из rgb в grayscale) — гамму конечно же нужно учитывать.
          Но для обработки изображений (например, регулировки яркости, контрастности, фильтры, смешивание и пр.) гамму лучше не трогать. Она же не просто так придумана — она нужна, чтобы сделать шкалу перцептивной. И гамма sRGB и L* делают это с разной степенью точности. Цвета нужно смешивать по перцептивной шкале, а не физической.

          Я пока поостерегусь назвать эти выводы окончательными. Но похоже, что ФШ именно так и поступает.
          И похоже, что мой апдейт 2 нужно проапдейтить, рассуждения в нём были частично ошибочные.


          1. DrSmile
            01.07.2016 00:57

            Всякую артистическую обработку можно проводить в нелинейном пространстве. Однако трансформации, имеющие конкретный физических аналог (смещения, изменения масштаба, повороты, в том числе нерегулярные; фильтры размытия и т. п.) обязаны быть реализованы физически корректно. В противном случае будут артефакты той или иной степени заметности в местах с сильными градиентами. Например, при движении тонкой линии, ее яркость будет заметно колебаться.


            1. dom1n1k
              01.07.2016 13:57

              А что означает «физически корректно»? Ведь (не)линейность пространства — штука относительная.
              CIE Lab и любое гамма-корректированное RGB-пространство очень нелинейны (типичный показатель степени от 1.8 до 3) относительно CIE XYZ. Но относительно человеческого восприятия всё наоборот — они более линейны (для того гамма и придумана!), Lab получше, RGB похуже. Но оба они превосходят в этом смысле XYZ, которое очень сильно нелинейно (эллипсы МакАдама).
              XYZ это такая математическая абстракция, которую придумали для удобства математики в докомпьютерную эпоху — считали все на логарифмических линейках, и отрицательные числа доставляли большие неудобства. Но оно вообще не перцептивное. Так почему же обработка в нём (или в его линейных преобразованиях, которыми являются RGB-пространства без гамма-коррекции) должна быть более корректна?


              1. Jetmanman
                10.11.2016 13:11
                -8

                Не все понял. Но возможность путешествия во времени не создает противоречий и логически возможно, другое дело какие здесь ограничения из физики. Судьба существует, я об этом писал в своей статье https://geektimes.ru/post/279780/, а то, что людям не хочется думать, что судьба есть это лишь их желания так думать. Вы сами написали почему судьба есть, но начинаете выдумывать почему ее может не быть. И вот еще что скажу, люди не понимают, что прошлое также существует как настоящее и будущее, это можно доказать из существования парадокса близнецов например, когда один близнец молоде другого и соответственно видит будущее второго близнеца. В реальности вместо близнецов есть космонавты, которые возвращаясь на землю чуть моложе остальных людей, т.е. находятся в их будущем. А в той своей статье я еще писал можно ли предсказать будущее.


                1. dom1n1k
                  01.07.2016 14:54

                  Я как-то участвовал в подобной дискуссии на форуме rudtp, только там было всё наоборот :) Человек утверждал, что корректная интерполяция цветов обязана быть максимально перцептивна (т.е. всегда проводиться только в пространстве Lab).

                  Ошибка ваших рассуждений в том, что Y — это не физическое количество света. Потому что XYZ это тоже пространство «цветовых ощущений», а не физического количества фотонов.


                  1. DrSmile
                    01.07.2016 17:16

                    XYZ пространство однозначно и физическо корректно определяется через количества фотонов. Есть 3 функции спектральной чувствительности, которые фотону определенной частоты ставят в соответствие тройку {X, Y, Z}. С точки зрения математики, базис XYZ — это трехмерное подпространство исходного бесконечномерного пространства физического цвета.

                    В контексте обсуждения важно, что это подпространство линейное, т. е. подчиняется принципу суперпозиции. Соответственно, если взять два источника света и посветить на одно место, то итоговой цвет будет суммой цветов источников в любом линейном пространстве (а уже конкретно ли это XYZ, RGB, или, вообще, функция от длины волны, не важно).


                    1. tretyakovpe
                      10.11.2016 16:35

                      не вижу в условии угла падения 90 градусов.
                      на картинке в посте вижу «пилу» отраженного луча. вот эта «пила», продлённая в бесконечность и становится лучом видимо


                      1. DrSmile
                        01.07.2016 20:53

                        Это все линейные преобразования, на работоспособность принципа суперпозиции не влияют. Проблемы там возможны только при нелинейных операциях, например, при освещении поверхности источником умножается спектральная интенсивность на коэффициент поглощения, и делать это в «урезанных» цветовых координатах (XYZ или RGB) не совсем точно.

                        В общем, лучше один раз увидеть. Тонкие линии на разном сабпиксельном смещении
                        без учета гаммы: image с учетом:image
                        Невооруженным глазом видны колебания яркости в первом случае.
                        (Картинки из темы на геймдеве, посвященной антиалиасингу.)


                        1. rerf2010rerf
                          10.11.2016 16:49

                          Бабло получили, попили, договор всё равно не подписали, соответственно ничего не построили…


                          1. DrSmile
                            01.07.2016 22:05

                            Субпиксельные эффекты — это не особый, а всего лишь частный случай наложения цветов. Какой-нибудь дефокус или наложение света от разных источников будут действовать точно так же.

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

                            Например
                            Какой средний цвет будет у шахматки на большом расстоянии?


                            Или вот мой прошлый пример с яркостью цветов

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


                            1. dom1n1k
                              02.07.2016 01:57

                              C красно-зеленым примером уже раньше разобрались. А что касается остального:

                              Мой пример.
                              Мое мнение — самый верхний. Но это моё, оно теоретически может быть предвзято. Я ещё опросил 4-х человек (никто их них не понимает значения букв на картинке). Двое сказали что средний квадратик, один что верхний, а еще один, что он бы еще немного затемнил верхний.

                              Шахматка.
                              На десктопе совпадает с верхним. На планшете и телефоне где-то посередине, но чуть ближе к нижнему. Сторонние мнения: у одного ближе к нижнему, у одного ближе к верхнему, у одного точно совпал с нижним.
                              И можно было бы списать разброс на разные калибровки разных экранов, но… два последних человека (с противоположным виденьем) смотрели на одном компьютере :)


                              1. DrSmile
                                02.07.2016 03:22

                                У всех ЖК экранов сильно плавает цветопередача в зависимости от угла, особенно вертикального. Еще некоторые устройства отображения бывают испорчены разными «улучшайзерами» (у меня проектор этим грешит и приходится делать квадраты шахматки побольше, чтобы компенсировать эффект). Плюс, условия эксперимента необходимо понимать буквально: надо не субъективно оценивать похожий цвет, а отойти на такое расстояние, с которого квадраты перестанут быть различимы.

                                Но, вообще, все это лирика и законы физики предполагают только один ответ. Получение другого говорит о неправильной калибровке монитора и/или неправильной постановке эксперимента.


          1. DistortNeo
            01.07.2016 09:33

            Для фотореалистичной обработки гамму учитывать нужно. Гамма придумана для того, чтобы сделать более-менее равномерным распределение отсчётов шкалы в соответствии с человеческим восприятием.

            Например, черный провод на белом фоне после размытия должен пропать, а белая нить на чёрном фоне — стать толще, почти не потеряв в яркости. Без преобразования гаммы оба объекта бы стали серыми.


            1. dom1n1k
              01.07.2016 13:23

              Это почему так должно? Имею в виду пример с нитью.


              1. DistortNeo
                01.07.2016 14:08

                Потому что именно так и происходит в реальном мире.


                1. dom1n1k
                  01.07.2016 15:01

                  Где-то можно почитать более подробное объяснение и обоснование этого феномена?


    1. dom1n1k
      28.06.2016 21:40

      См. второй апдейт


  1. homm
    28.06.2016 22:08

    Добью вас про линейность цветового пространства. Вообще говоря перевод sRGB > RGB не ограничивается выправлением гаммы. Формула чуть сложнее.


    1. dom1n1k
      28.06.2016 22:13

      Не совсем понял, на что конкретно обращать внимание. На то, что график гаммы в sRGB состоит из двух кусков, линейного и степенного? Это я знаю. Или что-то еще?


    1. sasha1024
      29.06.2016 00:25

      Вообще, во 2-м update'е он как раз считает по более сложной формуле (если я правильно понял).
      Но за хорошую ссылку спасибо.


  1. TheShock
    29.06.2016 02:19
    +1

    А я вообще использовал когда-то (3r+6g+1b)/10. Визуально разницы почти не заметно, особенно в динамике.


    1. Randl
      29.06.2016 16:28

      Ну так относительная яркость — это всего лишь один из способов перевода изображения в ч/б. Иногда можно вообще один канал взять и готово, иногда надо изображение сначала обработать до перевода в ч/б. У Маргулиса про это хорошо написано, правда, конечно, в свете ручной обработки а не автоматической.


  1. littleguga
    29.06.2016 10:59

    У Вас ссылка на Chart.js битая.

    По хорошему там везде надо issue открыть или кинуть pull request, но как аргументировать?


    1. dom1n1k
      29.06.2016 11:16

      Видимо они изменили систему сборки, потому что папка dist вообще пропала из ветки master. Но если скачать библиотеку со странички релизов — там всё на месте (Chart.js#L450). Но поскольку в их исходниках это место теперь не находится, это вероятно на самом деле тянулось из библиотеки третей стороны?


      1. darkRabbit
        29.06.2016 14:52

        Это библиотека github.com/chartjs/color, форк github.com/harthur/color, ноги которой растут из библиотеки github.com/brehaut/color-js (в которой, кстати, всё с этим хорошо: github.com/brehaut/color-js/blob/master/color.js#L271).


  1. PaulZi
    29.06.2016 12:45

    Я помню сталкивался с этим, когда занимался конвертацией в AviSynth. Я на сколько я помню, там была такая рекомендация:
    использовать BT.601 — для старых не-HD источников (DVD и т. п.)
    использовать BT.709 — для HD-видео
    Не помню уже, откуда инфа, и на сколько она верна, но в памяти отложилось именно так.


    1. dom1n1k
      29.06.2016 12:56
      +1

      По факту выходит, что BT.601 верны только для американского NTSC до 1987 года и японского всех лет (японцы не переходили на новую спецификацию) и PAL/SECAM до 1970 года.
      Для всего остального BT.709 будет лучше — более свежие версии NTSC/PAL/SECAM хоть и не соответствуют им в точности, но очень близки.


  1. iroln
    29.06.2016 13:49

    Посмотрел в scikit-image. Они используют вторую формулу.

    The weights used in this conversion are calibrated for contemporary CRT phosphors


    Ссылаются на этот документ.


    1. sasha1024
      29.06.2016 21:00

      О, ещё одна отличная ссылка.


  1. vconst
    29.06.2016 16:41
    +1

    Я не программист, я фотошопер. Из своего опыта могу сказать, что правильный десатурейт должен не просто приводить все к определенной яркости, но еще и разделять цвета.

    Все у кого есть под руками фотошоп, могут проверить два метода:
    1) Создать RGB-изображение, залить фон градиентом радуги, применить к нему корректирующий слой Hue/Saturation в режиме наложения Normal и сдвинуть ползунок насыщенности в крайнее левое положение. Получится эффект команды Desaturate, аналогичный большинству аналогичных алгоритмов. Но картинка выйдет серая и плоская
    2) Повторить все шаги, но корректирующему слою сделать режим наложения Color. Получается Ч/Б картинка совсем другого характера, даже без цвета она остается яркой и контрастной, все цвета максимально разделяются один от другого

    Я не могу проверить описываемые в статье алгоритмы на своей картинке, но вот результат получающийся в фотошопе (прошу прощения, но полноценная работа с тегами мне недоступна, потому длинные текстовые ссылки):
    Цветной исходник: www.dropbox.com/s/mxbr7fpos67xme6/rainbow-color.jpg?dl=0
    Ч/б результат в режиме Normal: www.dropbox.com/s/oeky5jgi3wtncmh/rainbow-bw-normal.jpg?dl=0
    Ч/б результат в режиме Normal: www.dropbox.com/s/j90vgvi77c9n79k/rainbow-bw-color.jpg?dl=0

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


    1. vconst
      29.06.2016 16:45

      Последняя ссылка «в режиме Color», конечно же


    1. dom1n1k
      29.06.2016 17:17

      Команда Desaturate в ФШ работает в координатах HSB, поэтому её результат и получается, очень мягко говоря, сомнительный (я бы не использовал его вообще).
      Самый точный и правильный (с инженерной точки зрения) вариант обесцвечивания — это перевести картинку в Lab и взять канал L (lightness).
      Mode > Grayscale по качеству где-то посередине (не идеально, но для большинства случаев достаточно).


      1. vconst
        29.06.2016 17:42
        +2

        Не согласен.
        Я рассуждаю не как программист, а как ретушер-цветокорретор. Картинка должна быть не просто «правильная» с точки зрения математики, она должна быть яркой и контрастной, с минимальными потерями в деталях – то есть она должна быть красивой. А это не алгоритмизируется так просто

        Вот примеры той же радуги:
        L-канал из режима Lab: rainbow-Lab.jpg
        Командой Grayscale: rainbow-gray.jpg

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

        На самом деле все еще сложнее, грамотно перевести картинку в чб можно только с помощью команды Calculation, пробуя накладывать разные каналы друг на друга, в разных режимах и пропорциях, это сложная задача и после нее все равно придется доводить картинку корректирующими кривыми, но двухкликовый способ лучше всего тот, который я описал, Я плохо представляю, как его запрограммировать, хотя предполагаю, что это возможно, потому что наблюдал подобные задачи и их решения программными методами как на сервере, так и в браузере. Я не вспомню навскидку, но мне кажется, что в CSS есть возможность сделать подобную обработку не простым обесцвечиванием, а с наложением в разных режимах.

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


        1. dom1n1k
          29.06.2016 18:20

          Я разобрался. Запрограммировать его сравнительно несложно. Адобовская документация говорит:

          Color Creates a result color with the luminance of the base color and the hue and saturation of the blend color. This preserves the gray levels in the image and is useful for coloring monochrome images and for tinting color images.

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

          Вопрос только, что в точности они подразумевают под luminance. Скорее всего это нечто похожее на формулу, описанную в посте, но остается вопрос настроек (конкретные коэффициенты, учет гаммы и т.п.)


          1. vconst
            29.06.2016 18:36

            Можно чисто эмпирически выяснить, что они имеют в виду под luminance, измерив яркость пикселей пипеткой в фотошопе и посчитать, какое получается значение. Свойство из CSS «background-blend-mode» – подойдет? В описании сказано, что там аналоги наложений в фотошопе


            1. dom1n1k
              29.06.2016 18:44

              Там аналоги, близкие по смыслу, но не всегда точные копии.


              1. vconst
                29.06.2016 19:29

                Я думаю, что более полная информация есть в руководстве API Адоб по программированию плагинов


                1. vconst
                  29.06.2016 19:35

                  Ещё можно взять мои файлы, сделать с исходником наложение через CSS и сравнить с тем, что получилось в фотошопе


          1. Randl
            29.06.2016 21:11

            luminance — это L канал из HSL. Подробнее здесь.


            1. dom1n1k
              29.06.2016 21:20
              +1

              В HSL вообще-то lightness.
              И более того, продукты Adobe никогда не были замечены в связях с моделью HSL, они предпочитают HSB/HSV.


              1. Randl
                29.06.2016 21:31

                Упс, и правда. Канал B из HSB, наверное первая буква в luminance меня сбила. Но вы лучше по ссылке перейдите, там все подробно и с примерами.


            1. vconst
              29.06.2016 23:36

              Забавный дядька, знает то он много, но скорее из разряда «кто не умеет работать — учит»


  1. littleguga
    02.07.2016 03:26

    Кстати, я обратил внимание и в inkscape всё верно, ибо там помечено, что это для NTSC.