Изменения

Перейти к: навигация, поиск

Блендинг изображений

2723 байта добавлено, 04:33, 7 января 2021
Почти дописал второй проход, попытался увеличить междустрочный интервал у кода, но безуспешно...
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.
<font size="3em"> '''fun''' $SinglePassHarmonization$( $I$, <font color="green"> // Входное изображение </font> Mask$M$, <font color="green"> // Маска </font> $S$, <font color="green"> // Стилевое изображение </font>
$\pi$, <font color="green"> // Алгоритм построения стилевого маппинга </font>
$\mathcal{L}$ <font color="green"> // Функция потерь </font>
):
F_I :<font color= "green">// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 </font> $F[I] \leftarrow ComputeNeuralActivations(I)$ F_S := $F[S] \leftarrow ComputeNeuralActivations(S)$ P :<font color= "green">// Строим стилевой маппинг </font> $P \leftarrow \pi$(F_IF[I], MaskM, F_SF[S])$ <font color="green">// Градиентным спуском ищем изображение $O := $, которое минимизирует $\mathcal{L}$ </font> $O \leftarrow Reconstruct(I, MaskM, S, P, $\mathcal{L})$)
'''return''' $O$</font>
===Первый проход===
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм <code>IndependentMapping</code> для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).
<font size="3em"> '''fun''' $IndependentMapping$( F_I$F[I]$, <font color="green"> // Выходы слоёв после входного изображения </font> $Mask$, <font color="green"> // Маска </font> F_S $F[S]$ <font color="green"> // Выходы слоёв после стилевого изображения </font>
):
'''for''' $l '''\in''' range([1, : L)]$: <font color="green"> // L = количество слоёв сети </font> '''for''' $j '''\in''' range([1, M[l: M_l])$: <font color="green"> // M[l] = количество признаков на выходе l-го слоя сети </font> '''if''' $j '''\in''' Resize(Mask, l)$: <font color="green"> // рассматриваем патчи только внутри маски, которую нужно масштабираовать в соответсвии с размером слоя $l $ </font> $p(j) := \leftarrow NearestNeighborIndex(F_IF[I], j, F_SF[S])$ P := $P_l \leftarrow MakeStyleMapping(p) $ <font color="green"> // Делаем стилевой маппинг для слоя $l$ с помощью функции $p(j) $ </font> '''return''' $P$</font>
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.
===Второй проход===
<div style="font-size:130%; line-height: 3em;">Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм <code>ConsistentMapping</code> построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои.Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью). </div> <pre style="font-size:130%; line-height: 2em;">'''fun''' ConsistentMapping( $F[I]$, <font color="green"> // Выходы слоёв после входного изображения </font> $Mask$, <font color="green"> // Маска </font> $F[S]$ <font color="green"> // Выходы слоёв после стилевого изображения </font>): <font color="green">// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ </font> '''for''' $j \in [1 : M_{l_{ref}}]$: '''if''' $j \in Resize(Mask, l_{ref})$: $p_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$  <font color="green">// Далее обеспечиваем пространсвенную согласованность </font> '''for''' $j \in [1 : M_{l_{ref}}]$: '''if''' $j \in Resize(Mask, l_{ref})$: $q \leftarrow p_0(j)$ $CSet \leftarrow \{q\}$ <font color="green">// Инициализируем множество кандидатов на новый маппинг </font> '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: <font color="green">// Перебираем все смежные патчи </font> $CSet \leftarrow CSet \cup \{p_0(j + o) - o\}$ <font color="green">// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении </font> $p(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{p_0(j + o)}\|^2$ P := MakeStyleMapping(p) <font color="green"> // Делаем стилевой маппинг с помощью функции p(j) </font> '''return''' P</pre>
{{Определение
===Итоговый алгоритм===
<font size="3em">
'''fun''' Harmonization(
I, <font color="green"> // Входное изображение </font>
S <font color="green"> // Стилевое изображение </font>
):
<font color="green"> // Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. </font>
I' := SinglePassHarmonization(I, Mask, S, IndependentMapping, $\mathcal{L}_1$)
<font color="green"> // Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. </font>
O := SinglePassHarmonization(I', Mask, S, ConsistentMapping, $\mathcal{L}_2$)
'''return''' O
</font>
* '''TODO''' как подбирать гиперпараметры $w_{style}$, $w_{hist}$, $w_{tv}$, $\alpha$, $\beta$, $\gamma$
58
правок

Навигация