Блендинг изображений — различия между версиями

Материал из Викиконспекты
Перейти к: навигация, поиск
м
(Метки: правка с мобильного устройства, правка из мобильной версии)
м (Точка, точка, запятая)
Строка 28: Строка 28:
 
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки.  
 
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки.  
  
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$
+
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.
  
 
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.
 
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.
 
$$
 
$$
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}
+
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.
 
$$
 
$$
 
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.
 
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.
Строка 40: Строка 40:
 
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.
 
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.
  
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $(p, q)$ таких, что $q \in N_p$, введем $v_{pq} = I_p - I_q$
+
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $(p, q)$ таких, что $q \in N_p$, введем $v_{pq} = I_p - I_q$.
  
 
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такое $O$, чтобы разность $O_p$ и $O_q$ была близка к $v_{pq}$. Для этого решим задачу минимизации:
 
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такое $O$, чтобы разность $O_p$ и $O_q$ была близка к $v_{pq}$. Для этого решим задачу минимизации:
  
 
$$
 
$$
\underset{O_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; \left(O_p - O_q - v_{pq}\right)^2, \text{где } O_p = S_p, p \in \partial \Omega
+
\underset{O_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; \left(O_p - O_q - v_{pq}\right)^2, \text{где } O_p = S_p, p \in \partial \Omega.
 
$$
 
$$
  
 
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.  
 
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.  
$$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; \left(O_p - O_q - v_{pq}\right)^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 \left(O_p - O_q - v_{pq}\right) - \underset{q \in N_p}{\sum} 2 \left(O_q - O_p - v_{qp}\right) = 2 \underset{q \in N_p}{\sum} 2 \left(O_p - O_q - v_{pq}\right)$$.
+
$$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; \left(O_p - O_q - v_{pq}\right)^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 \left(O_p - O_q - v_{pq}\right) - \underset{q \in N_p}{\sum} 2 \left(O_q - O_p - v_{qp}\right) = 2 \underset{q \in N_p}{\sum} 2 \left(O_p - O_q - v_{pq}\right).$$
  
 
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.
 
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.
Строка 63: Строка 63:
 
O_p,\; \text{если } p \in int(\Omega) \\
 
O_p,\; \text{если } p \in int(\Omega) \\
 
S_p,\; \text{иначе }  
 
S_p,\; \text{иначе }  
\end{cases}
+
\end{cases}.
 
$$
 
$$
  
Строка 79: Строка 79:
 
|definition =
 
|definition =
 
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения.  
 
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения.  
$$G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l}$$
+
$$G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l},$$
$$G^l\left[I\right] = F^l\left[I\right]F^l\left[I\right]^T$$}}
+
$$G^l\left[I\right] = F^l\left[I\right]F^l\left[I\right]^T.$$}}
  
 
===Алгоритм Гатиса<ref name="GEB16">[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks] Leon A. Gatys, Alexander S. Ecker, Matthias Bethge (2016)</ref>===
 
===Алгоритм Гатиса<ref name="GEB16">[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks] Leon A. Gatys, Alexander S. Ecker, Matthias Bethge (2016)</ref>===
Строка 114: Строка 114:
 
|definition =
 
|definition =
 
$\mathcal{L}^{\gamma}_{hist}(S, O) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} \left(F^l_{ij}\left[O\right] - R\left(F^l_{ij}\left[O\right]\right)\right)^2$ {{---}} функция потерь гистограмм, где
 
$\mathcal{L}^{\gamma}_{hist}(S, O) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} \left(F^l_{ij}\left[O\right] - R\left(F^l_{ij}\left[O\right]\right)\right)^2$ {{---}} функция потерь гистограмм, где
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}
+
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.}}
  
 
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.
 
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.
Строка 201: Строка 201:
 
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}^{\beta}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$.
 
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}^{\beta}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$.
  
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P) \text{, где } w_{style} \text{ {{---}} вес стилевой функции потерь}$$
+
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P) \text{, где } w_{style} \text{ {{---}} вес стилевой функции потерь.}$$
  
 
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски<ref>https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349</ref>.
 
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски<ref>https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349</ref>.
Строка 250: Строка 250:
 
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.
 
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.
  
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{s1}(S, O, P) + w_{hist}\mathcal{L}^{\gamma}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O) \text{, где } w_{style}, w_{hist}, w_{tv} \text{ {{---}} веса соответсвующих функций потерь}$$
+
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{s1}(S, O, P) + w_{hist}\mathcal{L}^{\gamma}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O) \text{, где } w_{style}, w_{hist}, w_{tv} \text{ {{---}} веса соответсвующих функций потерь.}$$
  
 
{| class="wikitable" style="background-color:#FFF; text-align:center"
 
{| class="wikitable" style="background-color:#FFF; text-align:center"
Строка 265: Строка 265:
 
===Итоговый алгоритм===
 
===Итоговый алгоритм===
  
Теперь осталось запустить две стадии  
+
Теперь осталось запустить две стадии:
  
 
<font size="3em">
 
<font size="3em">
Строка 286: Строка 286:
 
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье<ref name="LPSB18"/>):
 
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье<ref name="LPSB18"/>):
 
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.
 
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.
# С помощью алгоритма PatchMatch<ref name="BSFG09">https://www.researchgate.net/profile/Eli_Shechtman/publication/220184392_PatchMatch_A_Randomized_Correspondence_Algorithm_for_Structural_Image_Editing/links/02e7e520897b12bf0f000000.pdf Connelly Barnes, Eli Shechtman, Adam Finkelstein, Dan B Goldman (2009)</ref> и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)
+
# С помощью алгоритма PatchMatch<ref name="BSFG09">https://www.researchgate.net/profile/Eli_Shechtman/publication/220184392_PatchMatch_A_Randomized_Correspondence_Algorithm_for_Structural_Image_Editing/links/02e7e520897b12bf0f000000.pdf Connelly Barnes, Eli Shechtman, Adam Finkelstein, Dan B Goldman (2009)</ref> и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).
  
 
===Подбор гиперпараметров===
 
===Подбор гиперпараметров===
Строка 352: Строка 352:
 
|}
 
|}
  
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = \underset{i,j}{\mathrm{med}}\left\{\left(O^l_{i, j} - O^l_{i-1, j}\right)^2 + \left(O^l_{i, j} - O^l_{i, j-1}\right)^2\right\}$<ref>[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$</ref>
+
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = \underset{i,j}{\mathrm{med}}\left\{\left(O^l_{i, j} - O^l_{i-1, j}\right)^2 + \left(O^l_{i, j} - O^l_{i, j-1}\right)^2\right\}$<ref>[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.</ref>
  
 
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:
 
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:
Строка 440: Строка 440:
 
|definition =
 
|definition =
 
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения.
 
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения.
$$\mathbf{D}^2=\begin{bmatrix}0 & 1 & 0\\1 & -4 & 1\\0 & 1 & 0\end{bmatrix}$$ }}
+
$$\mathbf{D}^2=\begin{bmatrix}0 & 1 & 0\\1 & -4 & 1\\0 & 1 & 0\end{bmatrix}.$$ }}
 
{| class="wikitable" style="float:right; clear:right;"
 
{| class="wikitable" style="float:right; clear:right;"
 
!Исходное изображение
 
!Исходное изображение
Строка 461: Строка 461:
 
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы.  
 
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы.  
 
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:
 
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{cont}\mathcal{L}_{cont}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B) $$
+
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{cont}\mathcal{L}_{cont}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$
 
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.
 
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.
  
Строка 489: Строка 489:
  
 
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:
 
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:
$$\mathcal{L}_{total}(O) = w_{cont}\mathcal{L}_{cont}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$$
+
$$\mathcal{L}_{total}(O) = w_{cont}\mathcal{L}_{cont}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$
  
 
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.
 
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.

Версия 20:20, 14 января 2021

Определение:
Блендинг изображений (англ. image blending) — метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами.


Блендинг Пуассона

Рис. $1.1$. Пример перепада яркости при простой вставке
Рис. $1.2$. Результат применения блендинга Пуассона

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

Замечание: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.

Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ — изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:

Фоновое
изображение $S$
Накладываемое
изображение $I$
Маска $M$
Poisson cat.jpg Poisson cherry.jpg Poisson cherry mask.png

Идея подхода

Пусть замкнутое множество $P \subset \mathbb{R}^2$ — область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ — область вставки изображения $I$.

Пусть $f_S$ — скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ — неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки.

$v_I$ — векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.

Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$. $$ \underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}. $$ Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле. $$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega, f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{— оператор Лапласа.}$$

Дискретный случай

Пусть $p$ — координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ — координаты границы вставляемой области, а $int(\Omega)$ — внутренность области.

Пусть $N_p$ — множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $(p, q)$ таких, что $q \in N_p$, введем $v_{pq} = I_p - I_q$.

Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такое $O$, чтобы разность $O_p$ и $O_q$ была близка к $v_{pq}$. Для этого решим задачу минимизации:

$$ \underset{O_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; \left(O_p - O_q - v_{pq}\right)^2, \text{где } O_p = S_p, p \in \partial \Omega. $$

Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. $$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; \left(O_p - O_q - v_{pq}\right)^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 \left(O_p - O_q - v_{pq}\right) - \underset{q \in N_p}{\sum} 2 \left(O_q - O_p - v_{qp}\right) = 2 \underset{q \in N_p}{\sum} 2 \left(O_p - O_q - v_{pq}\right).$$

Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.

Добавим условие $O_p = S_p, p \in \partial \Omega$: $\;|N_p| O_p - \underset{q \in N_p \cap int(\Omega)}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.

Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid[1].

Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: $$ B_p = \begin{cases} O_p,\; \text{если } p \in int(\Omega) \\ S_p,\; \text{иначе } \end{cases}. $$

Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.[2]

Трансфер стиля

Основная статья: Neural Style Transfer

Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв свёрточной нейронной сети VGG-19[3].

Основная идея генерации изображения — решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ — итоговое изображение, $\mathcal{L}(I, S, O)$ — функция потерь. Такую задачу можно решать градиентным спуском в пространстве изображений используя метод обратного распространения ошибки.

Определение:
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ — выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, где $N_l$ — количество фильтров в $l$-ом слое, $M_l$ — количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ — $j$-ый признак $i$-го фильтра в $l$-ом слое. $F^l\left[I\right]$ отражает содержание изображения.


Определение:
Матрица Грама (англ. Gram matrix) — матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения.

$$G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l},$$

$$G^l\left[I\right] = F^l\left[I\right]F^l\left[I\right]^T.$$


Алгоритм Гатиса[4]

Определение:
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} \left(F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right]\right)^2$ — функция потерь содержания, где $\alpha_l$ — вклад $l$-го слоя в функцию потерь[5].


Определение:
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} \left(G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right]\right)^2$ — функция потерь стиля, где $\beta_l$ — вклад $l$-го слоя в функцию потерь[5].


Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$[5]. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.

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

Начальная инициализация: A) $O_0 = I$; B) $O_0 = S$; C) $O_0 = random$, $4$ примера инициализированы различными белыми шумами

Histogram Loss

Авторы другой статьи[6] показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на сопоставлении гистограмм.

Определение:
Сопоставление гистограмм (англ. Histogram matching) — метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой[7].


Определение:
Пусть $R = histmatch(S, O)$ — отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.


Определение:
$\mathcal{L}^{\gamma}_{hist}(S, O) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} \left(F^l_{ij}\left[O\right] - R\left(F^l_{ij}\left[O\right]\right)\right)^2$ — функция потерь гистограмм, где $\gamma_l$ — вклад $l$-го слоя в функцию потерь.


Замечание: Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.

Total variation loss

Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения[8][9].

Определение:
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} \left(O^l_{i, j} - O^l_{i-1, j}\right)^2 + \left(O^l_{i, j} - O^l_{i, j-1}\right)^2$ — общая вариационная потеря (англ. Total variation loss).


Глубокая гармонизация картин[10]

Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей[4][9][6].

Пример работы алгоритма Deep Image Analogy[11] ($3$ картинка) и Deep Painterly Harmonization[10] ($4$ картинка)

Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй — более тщательную. Отличаться они будут стилевым маппингом и функциями потерь.


Определение:
Стилевым маппингом мы будем называть отображение $P : \mathcal{R}^{N_l \times M_l} \rightarrow \mathcal{R}^{N_l \times M_l}$, которое некоторым образом переставляет столбцы матрицы (не обязательно обратимо, то есть столбцы могут теряться и копироваться). Более формально, пусть $p(j)$ — новая позиция столбца $j$, тогда $P(Q)_{i, p(j)} = Q_{ij}$.


Один проход будет состоять из $3$ частей:

  1. Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.
  2. Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.
  3. Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.

 fun $SinglePassHarmonization$(
   $I$,// Входное изображение 
   $M$,// Маска 
   $S$,// Стилевое изображение 
   $\pi$,// Алгоритм построения стилевого маппинга 
   $\mathcal{L}$// Функция потерь 
 ):
   // Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 
   $F[I] \leftarrow ComputeNeuralActivations(I)$
   $F[S] \leftarrow ComputeNeuralActivations(S)$
   // Строим стилевой маппинг 
   $P \leftarrow \pi(F[I], M, F[S])$
   // Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ 
   $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$
   return $O$

Первый проход

Определение:
Вектор активации (англ. activation vector) — это столбец $F_l$.


Определение:
Патчем (англ. patch) для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y \times W_l + x$.


Результаты после второго прохода
Результаты после первого прохода

Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).

 fun $IndependentMapping$(
   $F[I]$,// Выходы слоёв после входного изображения 
   $Mask$,// Маска 
   $F[S]$// Выходы слоёв после стилевого изображения 
 ):
   // Для всех слоёв от $1$ до $L$ 
   for $l \in [1 : L]$: 
     // Для всех столбцов от $1$ до $M_l$ 
     for $j \in [1 : M_l]$:
       // Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ 
       if $j \in Resize(Mask, l)$:
         // Берём самый похожий стилевой патч и записываем его в маппинг.  
         $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$
   return $P$

В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}^{\beta}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$.

$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P) \text{, где } w_{style} \text{ — вес стилевой функции потерь.}$$

Замечание: при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски[12].

Второй проход

Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью).

 fun $ConsistentMapping$(
   $F[I]$,// Выходы слоёв после входного изображения 
   $Mask$,// Маска 
   $F[S]$// Выходы слоёв после стилевого изображения 
 ):
   // Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ 
   for $j \in [1 : M_{l_{ref}}]$:
     if $j \in Resize(Mask, l_{ref})$:
       $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$
 
   // Далее обеспечиваем пространсвенную согласованность 
   for $j \in [1 : M_{l_{ref}}]$:
     if $j \in Resize(Mask, l_{ref})$:
       $q \leftarrow P_0(j)$
       // Инициализируем множество кандидатов на новый маппинг 
       $CSet \leftarrow \{q\}$
       // Перебираем все смежные патчи 
       for $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: 
         // Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении 
         $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$
       // Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей 
       $P_{l_{ref}}(j) \leftarrow \underset{c \in CSet}{\mathrm{argmin}}\displaystyle\sum_o \left\|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\right\|^2$
 
   // Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои 
   for $l \in [1 : L] \setminus \{l_{ref}\}$:
     for $j \in [1 : M_l]$:
       if $j \in Resize(Mask, l)$:
         // Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$
         $j' \leftarrow ChangeResolution(l, l_{ref}, j)$
         // Берём маппинг для позиции $j'$
         $q \leftarrow P_{l_{ref}}(j')$
         // Переносим позицию $q$ обратно на слой $l$
         $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$
   return $P$

При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.

$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{s1}(S, O, P) + w_{hist}\mathcal{L}^{\gamma}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O) \text{, где } w_{style}, w_{hist}, w_{tv} \text{ — веса соответсвующих функций потерь.}$$

Только второй проход Только первый проход Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$
LPSB18 Figure 5c.png LPSB18 Figure 5d.png LPSB18 Figure 5f.png

Итоговый алгоритм

Теперь осталось запустить две стадии:

 fun $Harmonization$(
   $I$,// Входное изображение 
   $Mask$,// Маска 
   $S$// Стилевое изображение 
 ):
   // Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. 
   $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$
   // Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. 
   $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$
   return $O$

Постобработка

Результат постобработки (без постобработки, после первой стадии, после второй стадии)

Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье[10]):

  1. Переведём изображение в CIELAB и применим Guided filter для a и b каналов.
  2. С помощью алгоритма PatchMatch[13] и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).

Подбор гиперпараметров

Влияние $l_{ref}$ на результат

Возьмём $l_{ref}$ = conv4_1. Выберем следующие веса для слоёв:

Первый проход
Параметр conv1_1 conv2_1 conv3_1 conv4_1 conv5_1
$\alpha$ $0$ $0$ $0$ $1$ $0$
$\beta$ $0$ $0$ $1/3$ $1/3$ $1/3$
Второй проход
Параметр conv1_1 conv2_1 conv3_1 conv4_1 conv5_1
$\alpha$ $0$ $0$ $0$ $1$ $0$
$\beta$ $1/4$ $1/4$ $1/4$ $1/4$ $0$
$\gamma$ $1/2$ $0$ $0$ $1/2$ $0$

Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = \underset{i,j}{\mathrm{med}}\left\{\left(O^l_{i, j} - O^l_{i-1, j}\right)^2 + \left(O^l_{i, j} - O^l_{i, j-1}\right)^2\right\}$[14]

Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:

Категория стиля Примеры стилей $\tau$
Слабый Барокко, Высокое Возрождение $1$
Средний Абстрактное Искусство, Постимпрессионизм $5$
Сильный Кубизм, Экспрессионизм $10$

Примеры

Исходное изображение Простая вставка Результат Постобработка
5 target.jpg 5 naive.jpg 5 final res.png 5 final res2.png
6 target.jpg 6 naive.jpg 6 final res.png 6 final res2.png
10 target.jpg 10 naive.jpg 10 final res.png 10 final res2.png

Глубокий блендинг

Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.

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

  • Используемая для вставки часть $I$ вырезана с помощью маски
  • $M$ и $I$ выровнены относительно $S$
  • Размеры матриц, задающих $M, S, I$ совпадают

Примеры входных данных:

Стилевое
изображение $S$
Deep bl s1.png Deep bl s2.png Deep bl s3.png
Накладываемое
изображение $I$
Deep bl i1.png Deep bl i2.png Deep bl i3.png

На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:

Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи[15] использовалась сеть VGG-19[3], обученная на ImageNet[16].


Определение:
Простой вставкой (англ. copy and paste) $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$. $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ — покомпонентное умножение.


Определение:
Дискретный оператор Лапласа (фильтр Лапласа) $\mathbf{D}^2$ — аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения. $$\mathbf{D}^2=\begin{bmatrix}0 & 1 & 0\\1 & -4 & 1\\0 & 1 & 0\end{bmatrix}.$$
Исходное изображение Применение фильтра Лапласа
Lenna.png Lenna Laplacian Neg.png

Чтобы комбинировать решение задачи бесшовного наложения методом Пуассона с остальными ограничениями, авторы статьи[15] предлагают использовать функцию потерь $\mathcal{L}_{grad}$. Для сохранения контуров изображений $S$ и $I$ в области вставки используется дискретный оператор Лапласа.


Определение:
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[ \mathbf{D}^2 B - \left(\mathbf{D}^2 S + \mathbf{D}^2 I\right) \right]^2_{mn}$ — градиентная функция потерь (англ. Possion gradient loss). $H, W$ — высота и ширина изображений. $B = CAP(M, S, O)$ — блендинговое изображение, оптимизируемое относительно $O$.


Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.

Первый этап

На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше: $$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{cont}\mathcal{L}_{cont}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$ Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.

Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.

В результате получается подготовительное блендинг-изображение $B$.

 fun $SeamlessBlending$(
   $I$,   // Входное изображение 
   $M$,   // Маска 
   $S$    // Стилевое изображение 
 ):
   // Инициализируем первое приближение белым шумом 
   $Z \leftarrow RandomNoise() $
   $B \leftarrow CAP(M, S, Z)$
   // Определим суммарную функцию потерь с весами слагаемых $w$
   $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{cont}\mathcal{L}_{cont}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$
   // С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ 
   $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$
   return $CAP(M, S, Z)$

Второй этап

Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$.

В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$: $$\mathcal{L}_{total}(O) = w_{cont}\mathcal{L}_{cont}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$

Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.

 fun $StyleRefinement$(
    $B$,   // Подготовительное блендинг-изображение, результат первого этапа 
    $M$,   // Маска 
    $S$    // Стилевое изображение 
 ):
   $O \leftarrow B$
   // Определим суммарную функцию потерь с весами слагаемых $w$
   $\mathcal{L}_{total}(O) \leftarrow w_{cont}\mathcal{L}_{cont}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$
   // С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ 
   $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$
   return $O$

После первого этапа После обоих этапов
1 first pass.png 1 second pass.png
3 first pass.png 3 second pass.png
5 first pass.png 5 second pass.png

Детали реализации

Веса функций потерь
Этап $w_{grad}$ $w_{cont}$ $w_{style}$ $w_{hist}$ $w_{tv}$
$1$ $10^5$ $1$ $10^5$ $1$ $10^{-6}$
$2$ $0$ $1$ $10^7$ $1$ $10^{-6}$

Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 $VGG$, для $\mathcal{L}_{cont}$ — conv2_2.

На обоих этапах максимальное количество итераций алгоритма L-BFGS — $1000$.

Примеры

МЛ блендинг пример.png

См. также

Примечания

  1. Poisson Image Editing Patrick Perez, Michel Gangnet, Andrew Blake (2003)
  2. https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких
  3. 3,0 3,1 Very Deep Convolutional Networks for Large-Scale Image Recognition Karen Simonyan, Andrew Zisserman (2014)
  4. 4,0 4,1 Image Style Transfer Using Convolutional Neural Networks Leon A. Gatys, Alexander S. Ecker, Matthias Bethge (2016)
  5. 5,0 5,1 5,2 Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.
  6. 6,0 6,1 Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses Eric Risser, Pierre Wilmot, Connelly Barnes (2017)
  7. https://en.wikipedia.org/wiki/Histogram_matching
  8. Understanding Deep Image Representations by Inverting Them Aravindh Mahendran, Andrea Vedaldi (2015)
  9. 9,0 9,1 Perceptual Losses for Real-Time Style Transfer and Super-Resolution Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)
  10. 10,0 10,1 10,2 https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)
  11. Visual Attribute Transfer through Deep Image Analogy Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)
  12. https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349
  13. https://www.researchgate.net/profile/Eli_Shechtman/publication/220184392_PatchMatch_A_Randomized_Correspondence_Algorithm_for_Structural_Image_Editing/links/02e7e520897b12bf0f000000.pdf Connelly Barnes, Eli Shechtman, Adam Finkelstein, Dan B Goldman (2009)
  14. [https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.
  15. 15,0 15,1 Deep Image Blending Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)
  16. https://image-net.org/papers/imagenet_cvpr09.pdf J. Deng, W. Dong, R. Socher, L.-J. Li, K. Li, and L. FeiFei. Imagenet: A large-scale hierarchical image database