Chroma Key с использованием dlib

Эффект Chroma Key (“цветовой ключ”) заключается в сегментации изображения с тем, чтобы отделить объект переднего плана от фона. При этом цвет фона должен быть сплошным и равномерным – как правило, выбирают либо зеленый, либо синий, в зависимости от того, какой цвет отсутствует на объекте. Отделенное изображение затем накладывается на другой фон – например, на фотографию или рендер виртуальной сцены.

Существуют различные алгоритмы подобной сегментации, мы рассмотрим один из самых простых. Несмотря на простоту, он достаточно эффективен. Метод основан на нахождении евклидового расстояния в пространстве RGB – между цветом исходного пикселя и цветом фона. Если рассматривать цвета как точки в трехмерном пространстве, то пиксели, например, зеленого фона будут представлять собой облако точек, сосредоточенное вокруг “абсолютно зеленой” точки – (0, 1, 0). Чтобы получить значение альфа-канала (0 – пиксель принадлежит фону, 1 – не принадлежит), мы просто нормируем расстояние в заранее выбранном диапазоне.

import dlib.math.vector;
import dlib.math.utils;
import dlib.image.image;
import dlib.image.color;

SuperImage chromaKey(
    SuperImage img, 
    Color4f keyColor, 
    float minDist,
    float maxDist)
{
    auto res = new ImageRGBA8(img.width, img.height);
   
    foreach(y; img.col)
    foreach(x; img.row)
    {       
        Color4f col = img[x, y];
        
        Color4f delta = col - keyColor;
        float distSqr = dot(delta, delta);
        col.a = clamp(
            (distSqr - minDist) / (maxDist - minDist), 
            0.0f, 1.0f);
        res[x, y] = col;
    }
    
    return res;
}

Вот пример использования этой функции:

import dlib.image.io.io;

auto img = load("input.png");
auto res = img.chromaKey(Color4f(0, 1, 0), 0.3f, 0.7f);
res.save("output.png");

Как нетрудно заметить, результат не идеален – если наложить изображение на фон, вокруг актера наблюдается зеленоватый контур. От него можно избавиться путем эрозии альфа-канала: изображение пропускается через дискретный оконный фильтр 3х3, который присваивает пикселю наименьшее значение в окне. В результате, непрозрачная область “теряет” несколько пикселей контура, и зеленый ореол практически исчезает.

SuperImage erodeAlpha(SuperImage img)
{
    uint kw = 3, kh = 3;
    
    auto res = img.dup;
    
    foreach(y; img.col)
    foreach(x; img.row)
    {
        auto c = img[x, y];
        
        foreach(ky; 0..kh)
        foreach(kx; 0..kw)
        {
            int iy = y + (ky - kh/2);
            int ix = x + (kx - kw/2);

            if (ix < 0) ix = 0;
            if (ix >= img.width) ix = img.width - 1;
            if (iy < 0) iy = 0;
            if (iy >= img.height) iy = img.height - 1;
            
            float a = img[ix, iy].a;
            
            if (a < c.a) 
                c.a = a;
        }

        res[x, y] = c;
    }
    
    return res;
}

Кинематика персонажа

Доступна новая демонстрация работы dmech — на этот раз, на примере игровой кинематики (Character Controller) для игры от третьего лица. Персонаж умеет двигаться и прыгать, взаимодействуя со всеми физическими объектами и тримешем уровня.

Управление:
Стрелки — поворот вправо-влево и движение вперед-назад;
Пробел — прыжок.

Скачать для Windows

Исходники вскоре будут доступны в рамках проекта Atrium.

Cook 2.0.1

Вышел первый стабильный релиз Cook2 — программы сборки проектов на языке D. По сравнению с первой версией проекта, Cook2 перенес множество серьезных изменений и нововведений:

  • Полностью переделана система обработки параметров командной строки — теперь она работает с помощью std.getopt. Подробнее читайте в конольной справке (--help) и в документации по проекту.
  • Произведен рефакторинг парсера импортов. Появилась поддержка условий version и debug (в настоящее время других инструментов сборки для D с подобной функциональностью практически нет).
  • Появилась поддержка разрешения внешних зависимостей у проектов: в качестве таковых можно указать удаленные Git-репозитории или локальные каталоги в системе. Загрузка кода из репозиториев возможна с использованием HTTPS и SSH. Исходники зависимостей и — соответствующие объектные файлы хранятся в специальной папке в домашнем каталоге пользователя (~/.cook2) и являются общими для всех проектов, которые объявляют эти зависимости.
  • Улучшена система конфигурации: так, в папке ~/.cook2 можно хранить файл глобальной конфигурации default.conf, который будет использован по умолчанию всеми проектами.
  • Исправлено множество багов — в частности, серьезный баг с отслеживанием обратных зависимостей у модулей D.

Скачать Cook 2.0.1
Репозиторий Cook2 на GitHub

Raycast

В физическом движке dmech реализована поддержка пересечения тел с лучом (raycast). В качестве алгоритма для этого используется разновидность GJK. На данный момент есть возможность «стрелять» лучом в статические и динамические выпуклые тела, в ближайшем будущем появится также поддержка полигональных мешей.

Все изменения доступны в репозитории dmech на GitHub.

Угловое ограничение в dmech

В физическом движке dmech существенно улучшена реализация ограничений для тел (constraints):

  • Добавлено угловое ограничение (AngleConstraint), которое заставляет два тела принимать один и тот же поворот относительно друг друга;
  • Улучшено ограничение расстояния (DistanceConstraint), которое удерживает тела на определенном расстоянии друг от друга. Теперь можно ограничивать минимальное или максимальное расстояние между телами. Также этот вид ограничения может работать в качестве пружины с задаваемой жесткостью.
  • Комбинация углового и скользящего (Slider) соединений дает призматическое, которое позволяет двум телам скользить вдоль оси между ними, но не позволяет им вращаться относительно этой оси. Также возможны другие комбинации — в будущем в движке планируется реализовать класс составных ограничений.

Все изменения доступны в репозитории dmech на GitHub.

Поддержка мешей в dmech

В dmech возвращена поддержка статических полигональных мешей. Она существовала и ранее, но ее на долгое время пришлось убрать по причине несовместимости с нынешней архитектурой движка — сейчас, наконец-то, ее код удалось адаптировать.
Проверка столкновений с полигонами основана на все том же алгоритме MPR, но с оптимизацией за счет разбиения пространства (а именно, используется одна из разновидностей BVH — иерархии ограничивающих объемов).
Поддерживается проверка столкновений меша с любыми выпуклыми телами (включая боксы, цилиндры, конусы и т.д.) Единственное ограничение — в настоящее время полигональные меши могут быть только статичными телами.

Изменения доступны в репозитории dmech на GitHub.

Клон 2048

2048 — новый игровой феномен, пришедший на смену Flappy Bird. Изначально созданная итальянским программистом Габриэлем Чирулли на основе концепции другой аналогичной головоломки Threes, нехитрая 2048 намертво приковала к себе внимание как игроков, так и разработчиков. Сейчас в Интернете можно найти десятки ее клонов для всех мыслимых платформ!

Я тоже решил не оставаться в стороне и написал собственную версию игры — а если конкретнее, десктопный вариант 2048 для двух локальных игроков — 2048×2. Экран делится пополам: левое поле управляется WASD, правое — клавишами-стрелками. Игровой процесс, теоретически, может продолжаться бесконечно — пока не заполнятся оба поля. Побеждает тот, кто к концу своей игры наберет больше очков.

Исходники
Сборка для Windows
Сборка для Linux

Для компиляции игры из исходников нужен мой игровой движок DGL.

Обновление dmech

В физическом движке dmech реализована новая система кэширования контактов (persistent contact manifold), которая во многих случаях делает симуляцию более точной и правдоподобной.
Также обновлен репозиторий dmech на GitHub. Кроме свежих изменений в кодовой базе самого движка, добавлены исходники демонстрационного приложения на основе OpenGL и SDL.

Винтажные фильтры — обновление

Обновилась коллекция винтажных фильтров для GIMP: добавлены три новых фильтра (Amaro, Brannan, Toaster), а также поддержка виньетирования. Все фильтры теперь объединены в один: при запуске скрипта выводится диалоговое окно с выбором фильтра и другими опциями.

Скачать можно здесь.