image processing
Новые статьи от LHS
Статьи по dlib
На сайте студии LightHouse Software, использующей и активно продвигающей язык D, опубликовано несколько интересных статей по использованию коллекции библиотек dlib — в частности, о рисовании фрактала Курликю и графических примитивов с использованием dlib.image, а также о процедурном генерировании картинки с Псаем с последующим сохранением в файл.
http://lhs-blog.info/programming/dlang/fraktal-kurlikyu
http://lhs-blog.info/programming/dlang/dobavlenie-graficheskih-primitivov-v-dlib
http://lhs-blog.info/programming/dlang/gangnam-style-v-d
http://lhs-blog.info/programming/dlang/sohranenie-izobrazheniya-v-fayl
Бенчмарк загрузки PNG
Использовалось RGB-изображение размером 2048х2048, компилятор DMD 2.0.67 c флагами -release -inline -O. Задачей была загрузка из PNG, отражение по горизонтали и сохранение в PNG. Результат получился следующий:
C#:
Загрузка — 90 мс
Отражение — 10 мс
Сохранение — 380 мс
D (dlib):
Загрузка — 500 мс
Отражение — 30 мс
Сохранение — 950 мс
D (imageformats):
Загрузка — 230 мс
Отражение — 30 мс
Сохранение — 1100 мс
Тред с обсуждением
На днях обязательно сделаю собственный тест — необходимо выяснить, что именно тормозит в декодере.
dlib 0.5
- Новый модуль dlib.core.memory предоставляет средства для ручного выделения и высвобождения динамической памяти, независимые от сборщика мусора и основанные на malloc/free. Имеется поддержка структур, классов и массивов. При использовании классов рекомендуется использовать интерфейс ManuallyAllocatable и перегружать метод free, который ответственен за удаление объекта — в противном случае корректное удаление в некоторых случаях не гарантировано (например, при доступе через интерфейс или родительский класс).
- Началась работа по переводу всей dlib на РУП. Так, загрузчики изрбражений (PNG, JPEG, TGA, BMP) в новой версии полностью независимы от сборщика мусора. Для этого активно используется паттерн абстрактной фабрики, ответственный за создание изображений в памяти. Кстати, в загрузчике PNG значительно улучшена поддержка индексированных изображений, для них добавлена поддержка альфа-канала.
- Кроме того, на РУП переведены некоторые контейнеры из dlib.container — BST, ассоциативный массив. Реализован полностью ручной динамический массив (dlib.container.array).
- Еще одна новинка — ООП для структур (dlib.core.oop). Это экспериментальный модуль, реализующий для структур прототипный стиль ООП с поддержкой множественного наследования и параметрического полиморфизма. Полностью заменить классы он, конечно, не может, но окажется весьма полезен, если нужно создавать объекты с наследованием в стеке. В будущем планируется переписать некоторые внутренние механизмы dlib с использованием этой легковесной объектной системы.
- В пакете dlib.math появилась поддержка дуальных кватернионов. Это частный случай алгербы Клиффорда, обобщение кватернионов на поле дуальных чисел. Их можно использовать, например, для описания движения тел в кинематике — один дуальный кватернион охватывает и перенос, и вращение. Кстати, реализация обычных кватернионов через инкапсуляцию теперь совместима с векторами.
- Изменения коснулись и пакета вычислительной геометрии. Усеченная пирамида (dlib.geometry.frustum) теперь задается с нормалями ограничивающих плоскостей, указывающими наружу пирамиды. Подвергся изменению API проверки пересечения Frustum с AABB. Исправлены ошибки в реализации AABB и плоскости.
dcraw
Поддержка JPEG в dlib
Поддержка сохранения в JPEG в ближайшем будущем не планируется.
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;
}
Винтажные фильтры — обновление
Обновилась коллекция винтажных фильтров для GIMP: добавлены три новых фильтра (Amaro, Brannan, Toaster), а также поддержка виньетирования. Все фильтры теперь объединены в один: при запуске скрипта выводится диалоговое окно с выбором фильтра и другими опциями.
Скачать можно здесь.
dlib 0.3
- Добавлены абстрактные потоки ввода/вывода (dlib.core.stream), независимые от Phobos, а также интерфейс файловой системы (dlib.filesystem) с готовыми реализациями для POSIX и Windows — этот интерфейс можно использовать, например, для построения виртуальных ФС.
- Добавлена начальная поддержка HDRI в dlib.image (реализация формата изображений с плавающей запятой в dlib.image.hdri). Кроме того, обеспечена поддержка распараллеливания обработки изображений (dlib.image.parallel), добавлена поддержка чтения форматов TGA и BMP. Чтение/запись графических форматов теперь основаны на потоках, поэтому имеется возможность загружать изображения, например, напрямую из архивов.
- Элементы матриц (dlib.math.matrix) теперь располагаются по столбцам, а не по строкам. Это серьезно нарушило обратную совместимость, но если вы не используете внутренние данные матриц и пользуетесь только внешним API, то это изменение не должно повлечь никаких проблем.
Более полный чейнджлог, а также исходники релиза вы можете найти на GitHub:
https://github.com/gecko0307/dlib/releases/tag/v0.3.0
