Форум Flasher.ru

Форум Flasher.ru (http://www.flasher.ru/forum/index.php)
-   Pixel Bender/AGAL (http://www.flasher.ru/forum/forumdisplay.php?f=100)
-   -   Chroma Keying? (http://www.flasher.ru/forum/showthread.php?t=147425)

Zebestov 04.12.2010 00:47

Chroma Keying?
 
Думал найти уже готовый, но они работают как-то сложнее и хуже
Сварганил свой )

Код:

<languageVersion : 1.0;>

kernel GreenscreenKeying
<
    namespace : "ChromaKeying";
    vendor : "Vadim BELLinSKY";
    version : 1;
    description : "Greenscreen keying";
>
{

    parameter float threshold
    <
        minValue:      float(0.0);
        maxValue:      float(3.0);
        defaultValue:  float(1.8);
    >;

    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        dst = sampleNearest( src, outCoord() );
        dst.a = 1.0 - ( dst.g * threshold - dst.r - dst.b ) * 5.0;
    }

}

Работает с зеленым фоном разной степени однотонности и яркости. Очевидные изменения приведут к пригодности для синего фона.
Может встречалось что попроще (ну это вряд ли) или качественнее — киньте ссылкой плиз.

i.o. 04.12.2010 03:08

По-моему нужно уходить от RGB пространства. Например в YUV - вот у чувака статья с картинками. Качество может не очень, но думаю отполировать можно :)

Zebestov 04.12.2010 03:47

Отличная наводка! сразу пришла на ум еще одна палитра подобной структуры: LAB. Она есть в фотошопе, поэтому я сразу проверил — превосходный результат кеинга по каналу A. Попробую утром.

Единственное, чем подкупает мой алгоритм — он примитивен при очень хорошем результате. Так что необходимо, чтобы новый алгоритм оправдал вычисления (RGB2LAB или RGB2YUV) существенно лучшим кеингом, особенно упакованных изображений — видео.

Отпишусь )

Добавлено через 2 часа 40 минут
YUV отлично "пилит" синий — у него второй канал хранит именно эту составляющую.
Для зеленого нужно просто в формуле подсчета U поменять каналы, что вкупе c финальными коррекциями удивительным образом напоминает мои манипуляции =)

а вот Lab не дал того результата, ради которого стоит столько считать:

Код:

<languageVersion : 1.0;>

kernel GreenscreenKeyingLAB
<
    namespace : "ChromaKeying";
    vendor : "Vadim BELLinSKY";
    version : 1;
    description : "Greenscreen keying";
>
{
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
        dst = sampleNearest( src, outCoord() );
       
        float var_R = dst.r;
        float var_G = dst.g;
        float var_B = dst.b;
       
        if ( var_R > 0.04045 ) { var_R = pow( ( var_R + 0.055 ) / 1.055, 2.4 ); }
        else                  { var_R = var_R / 12.92; }
        if ( var_G > 0.04045 ) { var_G = pow( ( var_G + 0.055 ) / 1.055, 2.4 ); }
        else                  { var_G = var_G / 12.92; }
        if ( var_B > 0.04045 ) { var_B = pow( ( var_B + 0.055 ) / 1.055, 2.4 ); }
        else                  { var_B = var_B / 12.92; }
       
        var_R = var_R * 100.0;
        var_G = var_G * 100.0;
        var_B = var_B * 100.0;
       
        float X = var_R * 0.4124 + var_G * 0.3576 + var_B * 0.1805;
        float Y = var_R * 0.2126 + var_G * 0.7152 + var_B * 0.0722;
        float Z = var_R * 0.0193 + var_G * 0.1192 + var_B * 0.9505;
       
        X /= 95.047;
        Y /= 100.0;
        Z /= 108.883;
       
        float a = 17.5 * ( ( ( 1.02 * X ) - Y ) / sqrt( Y ) );

        dst.a = a * 350.0 + 350.0;
    }
}


i.o. 04.12.2010 23:21

Как оказалось, можно и в RGB очень хорошо вырезать. Вот:
Код:

<languageVersion : 1.0;>

kernel GreenScreenKeying
<
    namespace : "ChromaKeying";
    vendor : "Vadim BELLinSKY, feat. by i.o. ;)";
    version : 2;
    description : "Green screen keying with key-color supression";
>
{

    parameter float threshold
    <
        minValue:      float(0.0);
        maxValue:      float(3.0);
        defaultValue:  float(1.80);
    >;
   
    parameter float factor
    <
        minValue:      float(0.0);
        maxValue:      float(50.0);
        defaultValue:  float(2.00);
    >;
   
    parameter float supressFactor
    <
        minValue:      float(0.0);
        maxValue:      float(10.0);
        defaultValue:  float(1.60);
    >;
   

    input image4 src;
    output pixel4 dst;


    void evaluatePixel()
    {
        dst = sampleNearest( src, outCoord() );
       
        float valueMatch = clamp( 1.0 - factor * (dst.g * threshold - dst.r - dst.b), 0.0, 1.0 );

        dst.a = valueMatch;
        dst.r *= valueMatch;
        dst.g *= pow( valueMatch, supressFactor );
        dst.b *= valueMatch;
    }
}

По-моему вырезает если не идеально, то почти идеально ))
Несколько картинок, взятых в гугле с первой страницы с зеленым фоном, вырезались отлично.
Жду ответа.

Добавлено через 2 часа 26 минут
все-таки не совсем отлично..

Zebestov 05.12.2010 02:55

i.o. — респект! отличная наводка на подавление зеленого края!
я ее лишь несколько видоизменил и лишил настройки (она поначалу была, но все тесты показали ее ненадобность)

теперь наш фильтр имеет такой вид:
Код:

<languageVersion : 1.0;>

kernel GreenscreenKeying
<
    namespace : "ChromaKeying";
    vendor : "Vadim BELLinSKY feat. i.o.";
    version : 3;
    description : "Greenscreen keying with edge color correction";
>
{

    parameter float amount
    <
        minValue:      float(0.0);
        maxValue:      float(10.0);
        defaultValue:  float(0.0);
    >;
   
    parameter float threshold
    <
        minValue:      float(0.0);
        maxValue:      float(1.0);
        defaultValue:  float(0.8);
    >;
   
    input image4 src;
    output pixel4 dst;

    void
    evaluatePixel()
    {
   
        dst = sampleNearest( src, outCoord() );

        // очищаем зерна от плевел
        float A  = clamp( 1.0 - ( dst.g * ( 1.0 + threshold ) - dst.r - dst.b ) * amount, 0.0, 1.0 );
        float A1 = 1.0 - A;
       
        // упрощенная схема поиска серого, эквивалентного(~) данной точке по яркости
        float GREY = ( dst.r + dst.g + dst.b ) * 0.33;
       
        // обесцвечивание полупрозрачных точек с акцентом на зеленый канал
        dst.r += A1 * ( GREY - dst.r );
        dst.g += A1 * ( GREY - dst.g ) * 2.0;
        dst.b += A1 * ( GREY - dst.b );
       
        // ну и, собственно, отсечение зеленого фона
        dst.a = A;
       
        // код ниже добавлен лишь для демонстрации и должен быть удален в релизе
        // начало кода задника
        dst.r = dst.r * A + A1 * ( sin( outCoord().x * 0.25 ) * cos( outCoord().y * 0.5 ) * 0.5 + 0.5 );
        dst.g = dst.g * A + A1 * ( cos( outCoord().x * 0.5 ) * sin( outCoord().y * 0.25 ) * 0.5 + 0.5 );
        dst.b = dst.b * A + A1;
        dst.a  = 1.0;
        // конец кода задника
       
    }

}

особенно показательны эти кадры:
первый: волосы в блюре — частая ситуация (наряду с прочими размытостями при быстрых движениях)
второй: весь кадр какой-то зеленоватый — нередко при съемках отражающих объектов (в данном случае ткань платья приняла на себя много рира)

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

i.o. 05.12.2010 08:36

Да, стало лучше. Я тут потыкался, вроде получилось еще круче, только правда пара настроек добавилась - addAlpha и addAlphaRank. Не знаю как назвать по-человечески.. Просто когда тыкался, то там действительно с альфой связано было, а потом все закрутилось-завертелось... так что хз как и обозвать ;)
colorMult и colorOffset - это для контроля за альфа каналом, чтобы можно было посмотреть не вырезаются ли дыры там, где не надо.
Вот примеры:

женщина на сцене (оригинал, на розовом фоне, на разноцветном фоне):
http://d.imagehost.org/0118/01a.jpg
http://b.imagehost.org/0410/01b.jpg
http://b.imagehost.org/0106/01c.jpg

Джессика:
http://b.imagehost.org/0241/02a.jpg
http://d.imagehost.org/0335/02b.jpg
http://d.imagehost.org/0248/02c.jpg

Птичка:
http://b.imagehost.org/0582/03a.jpg
http://d.imagehost.org/0512/03b.jpg
http://d.imagehost.org/0579/03c.jpg

Пати:
http://d.imagehost.org/0575/04a.jpg
http://d.imagehost.org/0916/04b.jpg
http://d.imagehost.org/0422/04c.jpg

И самое главное - практически отсутствует зеленоватый цвет. Даже в отражениях полная тон-компенсация.

Вот код:
Код:

<languageVersion : 1.0;>

kernel GreenscreenKeying
<
    namespace : "ChromaKeying";
    vendor : "Vadim BELLinSKY feat. i.o.";
    version : 4;
    description : "Greenscreen keying with edge color correction";
>
{

    parameter float enableBackground
    <
        minValue:      float(0.0);
        maxValue:      float(1.0);
        defaultValue:  float(0.0);
    >;
   
    parameter float amount
    <
        minValue:      float(0.0);
        maxValue:      float(10.0);
        defaultValue:  float(1.0);
    >;
   
    parameter float threshold
    <
        minValue:      float(0.0);
        maxValue:      float(1.0);
        defaultValue:  float(1.0);
    >;
   
    parameter float addAplha
    <
        minValue:      float(0.00);
        maxValue:      float(0.50);
        defaultValue:  float(0.10);
    >;
   
    parameter float addAplhaRank
    <
        minValue:      float(0.00);
        maxValue:      float(10.0);
        defaultValue:  float(1.7);
    >;
   
    parameter float colorSupression
    <
        minValue:      float(0.00001);
        maxValue:      float(2.0);
        defaultValue:  float(0.00001);
    >;
   
    parameter float colorMult
    <
        minValue:      float(0.0);
        maxValue:      float(+10.0);
        defaultValue:  float(1.0);
    >;
   
    parameter float colorOffset
    <
        minValue:      float(-1.0);
        maxValue:      float(+1.0);
        defaultValue:  float(0.0);
    >;
   
    input image4 src;
    output pixel4 dst;

    void evaluatePixel()
    {
        dst = sampleNearest( src, outCoord() );

        // calc a key-color match
        float A = clamp( 1.0 + amount * (dst.r + dst.b - dst.g * (1.0 + threshold)), 0.0, 1.0 );
        // calc a mask value
        float mask = pow( addAplha + A, addAplhaRank );
       
        // supress key-color (green)
        dst.g += ( 0.33*(dst.r + dst.b) - 0.66*dst.g ) * pow( 1.0 - A, colorSupression );
        // apply mask value
        dst.a *= mask;
        // clamp color
        dst = clamp( dst, 0.0, 1.0 );
       
        //{ helping calcs
        dst.r *= colorMult;
        dst.g *= colorMult;
        dst.b *= colorMult;
        //
        dst.r += colorOffset;
        dst.g += colorOffset;
        dst.b += colorOffset;
        //
        dst = clamp( dst, 0.0, 1.0 );
        //
        float4 bgColor = float4( 0.5 + 0.5 * sin( 0.25 * outCoord().x ) * cos( 0.50 * outCoord().y ),
                                0.5 + 0.5 * cos( 0.50 * outCoord().x ) * sin( 0.25 * outCoord().y ),
                                1.0,
                                1.0 );

        if( enableBackground > 0.5 )
        {
            dst = mix( dst, bgColor, 1.0 - dst.a );
        }
        //} helping calcs

    }
}

Может сможешь еще как-то прокачать...
Ах да, у меня в Бендере не пишется по-русски — надеюсь разберешься, что я там нашлепал в комментах :)

Zebestov 05.12.2010 16:33

отлично! еще ночью думал продолжить в направлении работы непосредственно с полученной альфой — levels.
в твоей редакции результаты действительно в большинстве случаев превосходные! можно еще подумать над настройками — свести их к минимуму.

i.o. 05.12.2010 21:07

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

Zebestov 05.12.2010 21:35

Цитата:

Сообщение от i.o. (Сообщение 955215)
спасибо)
Есть все-таки недостаток - подавление зеленого цвета происходит по всей картинке. Т.е результаты хорошие, но если объект будет содержать целеные цвета, то он либо обесцветится, либо станет коричневатым либо вообще вырежется...

вырежется — это норм! нефиг для зеленого рира одевать зеленые свитера =)
подавление цвета на краях да — действует по всей картинке. рецепт — оберни его в проверку на полупрозрачность.

и настроек я немного поуменьшил. чуть позже выкину.

отличный кеинг выходит!

Zebestov 17.10.2015 16:21

Вложений: 2
Недавно набрел на восторженную статью о плагине CloudCutout, который показывает хороший результат:

Вложение 31849

Вспомнил про эту поделку. Вы только посмотрите!

Вложение 31848

:)


Часовой пояс GMT +4, время: 12:38.

Copyright © 1999-2008 Flasher.ru. All rights reserved.
Работает на vBulletin®. Copyright ©2000 - 2024, Jelsoft Enterprises Ltd. Перевод: zCarot
Администрация сайта не несёт ответственности за любую предоставленную посетителями информацию. Подробнее см. Правила.