Акварелизация изображения с помощью dlib

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

Для того, чтобы сделать эффект акварелизации потребуются только D, dlib, подходящее изображение и огромное желание поработать с картинками собственными руками. Тех, кому интересно добро пожаловать под кат этой статьи.

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

Сама акварелизация выглядит следующим образом:

- Берем исходное изображение и производим его цветовое выравнивание с помощью медианного фильтра размером 4 на 6.
- Из полученного после такой обработки изображения создается новое изображение путем применения фильтра резкости.

Реализацию акварелизации можно сделать буквально в несколько строк кода, для чего мы взяли нашу реализацию медианного фильтра, а фильтр резкости взяли из dlib, в которой есть функция convolve, которая берет изображение и некоторый фильтр (есть несколько предопределенных) и применяет его к исходному изображению:

#!/usr/bin/env dub
/+ dub.sdl:
	dependency "dlib" version="~>1.0.0"
+/

import std.conv;
import std.stdio;
import std.string;
import std.file;

import dlib.image;

auto medianFilter(int M, int N)(SuperImage source)
{
	import std.algorithm : sort;
	import std.range : array;
			
	enum edgeM = M / 2;
	enum edgeN = N / 2;
	
	auto imageWidth = source.width;
	auto imageHeight = source.height;
	auto simg = image(imageWidth, imageHeight);
	
	for (int i = edgeM; i < imageWidth - edgeM; i++)
	{
		for (int j = edgeN; j < imageHeight - edgeN; j++)
		{
			Color4f[] window;

			for (int w = 0; w < M; w++)
			{
				for (int h = 0; h < N; h++)
				{
					window ~= source[i + w - edgeM, j + h - edgeN];
				}
			}
			
			auto sortedWindow = (sort!"a.luminance > b.luminance"(window)).array;
			simg[i, j] = sortedWindow[$ / 2];
		}
	}
	return simg;
}


void main()
{
	auto img = loadImage(`исходное изображение`);
	
	img = img
		.medianFilter!(6, 6)
		.convolve(Kernel.Sharpen);
	
	img.saveImage(`результирующее изображение`);
}

Все настолько просто, что мы не только сделали это обычным скриптом для dub, но еще и не стали выделять эффект акварелизации в отдельную функцию!

Для испытания эффекта достаточно указать правильный путь к изображению, допустим к такому:

А также указать путь для полученного результата, запустить скрипт dub, и в результате получаем вот такую картинку:

Здорово получилось, а?

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

Мы очень надеемся, что вам понравилась эта статья и что кто-то из вас разовьет идею в нечто более интересное. И если у вас получиться, то не стесняйтесь оставить свою идею в комментариях к этой записи или наших социальных сетях.

Добавить комментарий