...

среда, 31 декабря 2014 г.

Создание фотомозаик с помощью языка Wolfram Language (Mathematica)




Скачать перевод в виде документа Mathematica, который содержит весь код использованный в статье, можно здесь (архив, ~3 МБ).

Введение




До Нового 2015-го года осталось уже менее суток:

In[1]:=


ImageMosaic_2.png


Out[1]=


ImageMosaic_3.png


Мне хотелось бы поздравить всех с Наступающим Новым 2015-м годом и рассказать о том, как вы можете сделать своим близким необычный подарок в виде фотомозаики, созданной с помощью системы Mathematica 10 и языка Wolfram Language.


Идея фотомозаики в целом довольно проста: создать изображение на основе коллекции других изображений небольшого размера.


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



  • Простой способ: разбить изображение на фрагменты фиксированного размера, после чего подобрать каждому фрагменту наиболее “похожее” на него изображение из заданной коллекции и заменить этот фрагмент на него. В результате, чем меньше размер фрагмента и больше коллекция, тем качественнее будет фотомозаика.





  • Сложный способ: по сути повторяет первый способ за исключением того, что разбиение исходного изображения производится некоторым “адаптивным” алгоритмом на фрагменты различного размера.




Для упрощения рассматриваемой задачи будем создавать мозаику из квадратных миниатюр.



Создание коллекции изображений




Безусловно, можно использовать любую коллекцию изображений, которая у вас есть, будь то семейные фото или фотографии из путешествия.

Я не думаю, что мои коллекции такого рода будут очень интересны большинству читателей, поэтому в качестве коллекции я буду использовать набор изображений какого-нибудь известного человека. В качестве такого человека я возьму того, кто известен абсолютно всем, а именно — Арнольда Шварценеггера.


Для создания коллекции изображений воспользуемся парсером с сайта Zimbio:


In[2]:=


ImageMosaic_4.png


In[3]:=


ImageMosaic_5.png


Импортируем все имеющиеся фото из профиля Арнольда:


In[4]:=


ImageMosaic_6.png


Всего было импортировано 5436 фото:


In[5]:=


ImageMosaic_7.png


Out[5]=


ImageMosaic_8.png


Общий “вес” которых равен почти 5 ГБ.


In[6]:=


ImageMosaic_9.png


Out[6]=


ImageMosaic_10.png


Можем посмотреть на коллекцию мельком, составив коллаж из 150 случайно выбранных изображений:


In[7]:=


ImageMosaic_11.png


Out[7]=


ImageMosaic_12.png


Простая фотомозаика




Приступим к созданию простой фотомозаики.

Для начала укажем директорию, в которой хранится коллекция наших изображений:


In[8]:=


ImageMosaic_13.png


Теперь подгрузим пути к каждому из изображений:


In[9]:=


ImageMosaic_14.png


Out[9]//Short=


ImageMosaic_15.png


Сохраним число изображений в отдельной переменной:


In[10]:=


ImageMosaic_16.png


Out[10]=


ImageMosaic_17.png


Теперь создадим коллекцию миниатюр изображений, так как, очевидно, нам не потребуются изображения в их исходном размере. Размер каждой из миниатюр не бедет превышать 150x150 пикселей (по умолчанию).


In[11]:=


ImageMosaic_18.gif


In[13]:=


ImageMosaic_19.png


In[14]:=


ImageMosaic_20.png


Подгрузим пути к каждой из миниатюр:


In[15]:=


ImageMosaic_21.png


Теперь загрузим все миниатюры в систему:


In[16]:=


ImageMosaic_22.png


Вычислим для каждой из миниатюр ее средний RGB цвет:


In[17]:=


ImageMosaic_23.png


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


In[18]:=


ImageMosaic_24.gif


Out[18]=


ImageMosaic_25.png


Создадим функцию, составляющую фотомозаику:


In[20]:=


ImageMosaic_26.png


Зададим изображение, мозаику которого мы хотим получить:


In[21]:=


ImageMosaic_27.png


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


In[22]:=


ImageMosaic_28.png


Out[22]=


ImageMosaic_29.png


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


Для того, чтобы избавиться от этого, установим случайный выбор из 10 ближайших миниатюр:


In[23]:=


ImageMosaic_30.png


Out[23]=


ImageMosaic_31.png


Безусловно, с помощью этого алгоритма можно создавать любые мозаики такого рода:


In[24]:=


ImageMosaic_32.png


Out[24]=


ImageMosaic_33.png


Адаптивная фотомозаика




Создадим функцию, которая будет разбивать изображение на меньшие изображения адаптивным способом.

Функция adaptiveImagePartition работает следующим образом:



  • она представляет собой итеративное адаптивное разбиение с помощью шагов, приведенных ниже;

  • функция toParts вызывает функцию parts применительно к каждому изображению (или исходному изображению на первом шаге);

  • функция parts дробит изображение на 4 равные части (прямыми, проведенными через середины противолежащих сторон изображения) и отдает результат функции toParts;

  • для каждого из четырех полученных фрагментов вычисляется его средний цвет, после чего ищутся попарные расстояния между средними цветами с помощью функции ColorDistance (согласно стандарту CIE2000), затем ищется среднее значение расстояния. Если оно больше значения prec, то исходное изображение заменяется на четыре новых, в противном случае изображение оставляется в прежнем виде;

  • к полученному набору изображений применяется правило обработки rule.




In[25]:=

ImageMosaic_34.png


In[26]:=


ImageMosaic_35.png


In[27]:=


ImageMosaic_36.png


Зададим базовое изображение:


In[28]:=


ImageMosaic_37.png


Посмотрим на шаги работы созданной функции:


In[29]:=


ImageMosaic_38.png


Out[29]=


ImageMosaic_39.png


Изменив обработчик, мы можем получить адаптивную пикселизацию:


In[30]:=


ImageMosaic_40.png


Out[30]=


ImageMosaic_41.png


Наконец, если в качестве обработчика указать замену фрагмента изображения на ближайшую миниатюру, то получим:


In[31]:=


ImageMosaic_42.png


Out[31]=


ImageMosaic_43.png


Заключение




Надеюсь, что мой пост смог вас порадовать и заинтересовать. Безусловно, можно создать еще более сложные алгоритмы для фотомозаик, учитывающие: не только средний цвет, но и доминантные цвета фрагментов и миниатюр (DominantColors); морфологию изображений; более сложное адаптивное разбиение и пр. Но, думаю, созданных алгоритмов может быть уже вполне достаточно для того, чтобы сделать оригинальный подарок вашим близким к Наступающему Новому 2015-му году.

Ресурсы для изучения Wolfram Language (Mathematica) на русском языке: http://habrahabr.ru/post/244451


This entry passed through the Full-Text RSS service - if this is your content and you're reading it on someone else's site, please read the FAQ at http://fivefilters.org/content-only/faq.php#publishers.


Комментариев нет:

Отправить комментарий