Распараллеливание обработки изображений

API dlib.image позволяет создавать фильтры, которые легко распараллеливать на несколько процессоров. Изображение условно разбивается на несколько блоков заданного размера, которые затем обрабатываются фильтром через std.parallelism.

import std.parallelism;
import dlib.functional.range;
import dlib.image.image;

struct Block
{
uint x1, y1;
uint x2, y2;
}

alias Range!uint PixRange;

void parallelFilter(
SuperImage img,
void delegate(PixRange blockRow, PixRange blockCol) ffunc,
uint bw = 100,
uint bh = 100)
{
if (bw > img.width)
bw = img.width;
if (bh > img.height)
bh = img.height;

uint numBlocksX = img.width / bw + ((img.width % bw) > 0);
uint numBlocksY = img.height / bh + ((img.height % bh) > 0);

Block[] blocks = new Block[numBlocksX * numBlocksY];
foreach(x; 0..numBlocksX)
foreach(y; 0..numBlocksY)
{
uint bx = x * bw;
uint by = y * bh;

uint bw1 = bw;
uint bh1 = bh;

if ((img.width - bx) < bw)
bw1 = img.width - bx;
if ((img.height - by) < bh)
bh1 = img.height - by;

blocks[y * numBlocksX + x] = Block(bx, by, bx + bw1, by + bh1);
}

foreach(i, ref b; taskPool.parallel(blocks))
{
ffunc(range!uint(b.x1, b.x2),
range!uint(b.y1, b.y2));
}
}


Пример (закрашивание сплошным цветом):

SuperImage filterTestMultithreaded(SuperImage img)
{
auto res = img.dup;

img.parallelFilter((PixRange row, PixRange col)
{
foreach(x; row)
foreach(y; col)
{
res[x, y] = hsv(180.0f, 1.0f, 0.5f);
}
});

return res;
}


Для сравнения - однопоточный вариант:

SuperImage filterTestSinglethreaded(SuperImage img)
{
auto res = img.dup;

foreach(x; img.row)
foreach(y; img.col)
{
res[x, y] = hsv(180.0f, 1.0f, 0.5f);
}

return res;
}


На двухъядерном Intel Dual Core T2390 (1.86 ГГц) многопоточный вариант показывает прирост производительности на 70%.

Обновление dlib.image

В dlib.image появилась возможность отслеживать прогресс во время работы фильтров. Для этого используется многопоточность – необходимо создать класс-враппер, наследующий от FilteringThread. Прогресс (от 0 до 1) считывается из свойства progress для SuperImage. В данном примере показано, как использовать эту функциональность для вывода прогресса свертки в консоль:

import std.stdio;
import dlib.image.image;
import dlib.image.io.png;
import dlib.image.filters.convolution;
import dlib.image.fthread;

class ConvolutionThread: FilteringThread
{
float[] kernel;

this(SuperImage img, float[] k)
{
super(img);
kernel = k;
}

override void run()
{
output = image.convolve(kernel);
}

override void onRunning()
{
writef("Convolving %s%%", cast(uint)(image.progress * 100));
write("r");
stdout.flush();
}

override void onFinished()
{
writeln();
}
}

void main()
{
auto img = loadPNG("test.png");
img = (new ConvolutionThread(img, Kernel.Emboss)).filtered;
img.savePNG("output.png");
}

Фильтры Instagram для GIMP

Пять винтажных фильтров в стиле Instagram для GIMP.

Скачать

Кстати, остальные мои скрипты для GIMP теперь лежат здесь.

Журнал “FPS” №26

Вышел 26 номер электронного PDF-журнала “FPS”, посвященного разработке игр, программированию, компьютерной графике и звуку.

Читайте в этом номере:

> Tube Open Movie. Интервью с Бассамом Курдали
> Обзор дополнений Blender, выпуск 5
> GIMP: ломо-эффект как в Instagram
> Физический движок своими руками, часть III
> Making-of: логическая мини-игра Arrow
> Генерация случайных уровней
> Осваиваемся в SDL2
> Пишем плагин для DeleD на D
> Как я стал D-шником или Путь художника в IT
> Игровые новости из мира СПО и Linux
> “Корпорация зла”. Почему у Microsoft нет будущего

Номер доступен для онлайн-чтения и загрузки на сервисе Issuu.com, Документах Google и Dropbox.

Последние новости по проекту вы можете узнать в публичной странице журнала в социальной сети Google+: http://gplus.to/fpsmag. Добавляйте нас в круги, оставляйте свои комментарии и отписывайтесь в нашем сообществе.

Архив номеров журнала здесь.

Журнал “FPS” №25

Вышел 25 номер электронного PDF-журнала “FPS”, посвященного разработке игр, программированию, компьютерной графике и звуку.

Читайте в этом номере:

> SIGGRAPH 2013: новости с выставки
> VIGAMUS – музей видеоигр
> Моделирование волос в Blender
> Физический движок своими руками, часть II
> Дуальные числа и автоматическое дифференцирование
> Фильтрация изображений в dlib
> История Git
> Linux – для геймеров?
> Полезные консольные команды в Linux

Номер доступен для онлайн-чтения и загрузки на сервисе Issuu.com, Документах Google и Dropbox.

Последние новости по проекту вы можете узнать в публичной странице журнала в социальной сети Google+: http://gplus.to/fpsmag. Добавляйте нас в круги, оставляйте свои комментарии и отписывайтесь в нашем сообществе.