<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="ru">
		<id>http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wafemand</id>
		<title>Викиконспекты - Вклад участника [ru]</title>
		<link rel="self" type="application/atom+xml" href="http://neerc.ifmo.ru/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Wafemand"/>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:%D0%92%D0%BA%D0%BB%D0%B0%D0%B4/Wafemand"/>
		<updated>2026-08-03T23:04:21Z</updated>
		<subtitle>Вклад участника</subtitle>
		<generator>MediaWiki 1.30.0</generator>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79876</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79876"/>
				<updated>2021-01-22T13:09:50Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Копирование элемента одного изображения и его вставка на другое изображение {{---}} один из наиболее используемых методов для создания  графического контента. Простая вставка, как правило, бросается в глаза и делает результат похожим на коллаж, во многих случаях этот эффект является нежелательным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки. }}&lt;br /&gt;
Основная трудность задачи заключается в том, что естественность результата зависит не только от бесшовности наложения, но и от схожести цветов и текстуры вставляемого и фонового изображений.  &lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Вставляемое изображение&lt;br /&gt;
! Фоновое изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Желаемый результат&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Diver bl diver.png|200px]]&lt;br /&gt;
| [[Файл:Diver bl sea.png|200px]]&lt;br /&gt;
| [[Файл:Diver bl2.png|200px]]&lt;br /&gt;
| [[Файл:Diver bl3.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$: Пример перепада яркости при простой вставке&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$: Результат применения блендинга Пуассона&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$ {{---}} область, заданная маской $M$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$.&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Нейронный перенос стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу нейронного переноса стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt; (конкретные слои указаны ниже в деталях реализации).&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} матрица значений выхода $l$-го слоя сети на изображении $I$. Выход $l$-го слоя сети имеет размерность $N_l \times W_l \times H_l$. Представим его как матрицу $N_l \times M_l$, где $N_l$ {{---}} количество фильтров в $l$-ом слое, $M_l$ {{---}} количество признаков ($M_l = W_l H_l$). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое. Столбец матрицы $F^l\left[I\right]$ размера $N_l$ назовём '''вектором активации'''.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. &lt;br /&gt;
$$G^l\left[S\right] \in \mathcal{R}^{N_l \times N_l},$$&lt;br /&gt;
$$G^l\left[S\right] = F^l\left[S\right]F^l\left[S\right]^T.$$}}&lt;br /&gt;
&lt;br /&gt;
Далее рассмотренны функции потерь, которые мы будем использовать.&lt;br /&gt;
&lt;br /&gt;
===Content loss===&lt;br /&gt;
&lt;br /&gt;
$F^l\left[I\right]$ отражает содержание изображения. Мы хотим чтобы содержание результата было как можно ближе к исходной картинке. Введём для этого такую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Style loss===&lt;br /&gt;
&lt;br /&gt;
$G^l\left[S\right]$ отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. Чтобы стиль результата был похож на стилевое изображение, введём следующую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{style}(S, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} \left(G^l_{ij}\left[S\right] - G^l_{ij}\left[O\right]\right)^2,$$&lt;br /&gt;
где $\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Gatys' loss===&lt;br /&gt;
&lt;br /&gt;
Скомбинируем $\mathcal{L}_{content}$ и $\mathcal{L}_{style}$ и получим функцию потерь, которая была использована в алгоритме Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
$$\mathcal{L}_{Gatys}(I, S, O) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O).$$&lt;br /&gt;
Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые мы выберем позднее. &lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили учитывать ещё одну функцию потерь, основанную на '''сопоставлении гистограмм'''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$, тогда Histogram loss будет выглядеть так:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
$$\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.$$&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью (Рис. $2$). Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Рис. $2$: Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм состоит из двух проходов. Первый проход делает грубую гармонизацию, а второй {{---}} более тщательную. Отличаются они '''стилевым маппингом''' и функциями потерь&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' назовём отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход состоит из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Рис. $3.2$: Результаты после второго прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Рис. $3.1$: Результаты после первого прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями (Рис. $3.1$). Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$:&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O, P).$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_5c.png|thumb|right|250px|Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5d.png|thumb|right|250px|Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5f.png|thumb|right|250px|Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5g.png|thumb|right|250px|Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5h.png|thumb|right|250px|Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода (Рис. $3.2$). Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью). Если применять второй проход сразу, то результаты получаются хуже (Рис. $4.2$).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты (Рис. $4.3$). Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём функцию потерь с такой модификацией $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{s1}(S, O, P) + w_{hist}\mathcal{L}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O),$$ &lt;br /&gt;
где $w_{style}, w_{hist}, w_{tv}$ {{---}} веса соответсвующих функций потерь.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5g.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5h.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Рис. $5$: Результат постобработки (без постобработки, после первой стадии, после второй стадии)&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты (Рис. $5$). Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в цветовое пространство [https://en.wikipedia.org/wiki/CIELAB_color_space $L*\alpha*\beta$] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Рис. $6$: Влияние $l_{ref}$ на результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1 (что будет если использовать другие слои видно на Рис. $6$).&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
| $\tau$&lt;br /&gt;
| $\tau$&lt;br /&gt;
| $\tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На рисунке $4.4$ результат алгоритма без подбора гиперпараметров. Видно, что самолёт ярче, чем остальное изображение. С подбором параметров получается более естественный результат (Рис. $4.5$).&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
Примеры взяты с [https://github.com/luanfujun/deep-painterly-harmonization/tree/master/results Github авторов].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|200px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:5_final_res.png|200px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|200px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:6_final_res.png|200px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|200px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:10_final_res.png|200px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Более новые подходы===&lt;br /&gt;
&lt;br /&gt;
* [https://arxiv.org/pdf/2006.00809.pdf Foreground-aware Semantic Representations for Image Harmonization]&lt;br /&gt;
* [https://arxiv.org/pdf/2009.09169.pdf BargainNet: Background-Guided Domain Translation for Image Harmonization]&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски.&lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$.&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$, совпадают.&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения (Рис. $7.1$ и $7.2$).&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}.$$ }}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
!Рис. $7.1$:&amp;lt;br&amp;gt;Исходное изображение&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Lenna#/media/File:Lenna_(test_image).png&amp;lt;/ref&amp;gt;&lt;br /&gt;
!Рис. $7.2$:&amp;lt;br&amp;gt;Применение фильтра Лапласа&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Lenna.png|220px]]&lt;br /&gt;
| [[Файл:Lenna_Laplacian_Neg.png|220px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для сохранения контуров изображений $S$ и $I$ в области вставки воспользуемся идеей из [[Блендинг изображений#Блендинг Пуассона|метода Пуассона]] и введём следующую функцию потерь&amp;lt;ref name='ZWS20'/&amp;gt;:&lt;br /&gt;
$$\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},$$&lt;br /&gt;
где $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* $\mathcal{L}_{content}$ для сохранения содержания накладываемого изображения $I$.&lt;br /&gt;
* $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$.&lt;br /&gt;
* $\mathcal{L}_{hist}$ для стабилизации переноса стиля.&lt;br /&gt;
* $\mathcal{L}_{tv}$ для удаления шумов.&lt;br /&gt;
* $\mathcal{L}_{grad}$ для сохранения контуров фона и изображения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- 0JAg0LXRidGRINCd0LDRgdGC0Y8g0L7Rh9C10L3RjCDQvNC40LvQsNGPIQ== --&amp;gt;&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$&lt;br /&gt;
Для решения задачи минимизации авторы статьи&amp;lt;ref name='ZWS20' /&amp;gt; используют алгоритм L-BFGS&amp;lt;ref name=&amp;quot;LBFGS&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Limited-memory_BFGS Limited-memory BFGS - Wikipedia&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Отметим, что $\mathcal{L}_{content}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\mathcal{L}_{total}(O) = w_{content}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$B$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(O) \leftarrow w_{cont}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results Github авторов]:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! После первого этапа&lt;br /&gt;
! После обоих этапов&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:1_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:1_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:3_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:3_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:5_second_pass.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
В статье использовались следующие значения коэффициентов:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{content}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!--Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 VGG-19, для $\mathcal{L}_{content}$ {{---}} conv2_2.--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Коэффициенты $\alpha$ и $\beta$&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_2 &lt;br /&gt;
! conv2_2&lt;br /&gt;
! conv3_3&lt;br /&gt;
! conv4_3 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results Github авторов]:&lt;br /&gt;
&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Neural_Style_Transfer|Neural Style Transfer]]&lt;br /&gt;
* [[Сверточные_нейронные_сети | Свёрточная нейронная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Histogram_matching Histogram matching]&lt;br /&gt;
* Patrick Perez, Michel Gangnet, Andrew Blake (2003), [https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing].&lt;br /&gt;
&amp;lt;!--* Karen Simonyan, Andrew Zisserman (2014), [https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]--&amp;gt;&lt;br /&gt;
* Leon A. Gatys, Alexander S. Ecker, Matthias Bethge (2016), [https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&lt;br /&gt;
&amp;lt;!--* Eric Risser, Pierre Wilmot, Connelly Barnes (2017), [https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses]--&amp;gt;&lt;br /&gt;
&amp;lt;!--* Aravindh Mahendran, Andrea Vedaldi (2015), [https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them]--&amp;gt;&lt;br /&gt;
&amp;lt;!--* Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016), [https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution]--&amp;gt;&lt;br /&gt;
&amp;lt;!--* Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017), [https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy]--&amp;gt;&lt;br /&gt;
* Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018), [https://arxiv.org/pdf/1804.03189.pdf Deep Painterly Harmonization]&lt;br /&gt;
* Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020), [https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79771</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79771"/>
				<updated>2021-01-21T18:46:32Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Источники информации&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Копирование элемента одного изображения и его вставка на другое изображение {{---}} один из наиболее используемых методов для создания  графического контента. Простая вставка, как правило, бросается в глаза и делает результат похожим на коллаж, во многих случаях этот эффект является нежелательным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки. }}&lt;br /&gt;
Основная трудность задачи заключается в том, что естественность результата зависит не только от бесшовности наложения, но и от схожести цветов и текстуры вставляемого и фонового изображений.  &lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$: Пример перепада яркости при простой вставке&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$: Результат применения блендинга Пуассона&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$ {{---}} область, заданная маской $M$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$.&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Нейронный перенос стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу нейронного переноса стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt; (конкретные слои указаны ниже в деталях реализации).&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} матрица значений выхода $l$-го слоя сети на изображении $I$. Выход $l$-го слоя сети имеет размерность $N_l \times W_l \times H_l$. Представим его как матрицу $N_l \times M_l$, где $N_l$ {{---}} количество фильтров в $l$-ом слое, $M_l$ {{---}} количество признаков ($M_l = W_l H_l$). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое. Столбец матрицы $F^l\left[I\right]$ размера $N_l$ назовём '''вектором активации'''.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. &lt;br /&gt;
$$G^l\left[S\right] \in \mathcal{R}^{N_l \times N_l},$$&lt;br /&gt;
$$G^l\left[S\right] = F^l\left[S\right]F^l\left[S\right]^T.$$}}&lt;br /&gt;
&lt;br /&gt;
Далее рассмотренны функции потерь, которые мы будем использовать.&lt;br /&gt;
&lt;br /&gt;
===Content loss===&lt;br /&gt;
&lt;br /&gt;
$F^l\left[I\right]$ отражает содержание изображения. Мы хотим чтобы содержание результата было как можно ближе к исходной картинке. Введём для этого такую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Style loss===&lt;br /&gt;
&lt;br /&gt;
$G^l\left[S\right]$ отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. Чтобы стиль результата был похож на стилевое изображение, введём следующую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{style}(S, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} \left(G^l_{ij}\left[S\right] - G^l_{ij}\left[O\right]\right)^2,$$&lt;br /&gt;
где $\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Gatys' loss===&lt;br /&gt;
&lt;br /&gt;
Скомбинируем $\mathcal{L}_{content}$ и $\mathcal{L}_{style}$ и получим функцию потерь, которая была использована в алгоритме Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
$$\mathcal{L}_{Gatys}(I, S, O) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O).$$&lt;br /&gt;
Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые мы выберем позднее. &lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили учитывать ещё одну функцию потерь, основанную на '''сопоставлении гистограмм'''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$, тогда Histogram loss будет выглядеть так:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
$$\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.$$&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью (Рис. $2$). Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Рис. $2$: Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм состоит из двух проходов. Первый проход делает грубую гармонизацию, а второй {{---}} более тщательную. Отличаются они '''стилевым маппингом''' и функциями потерь&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' назовём отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход состоит из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Рис. $3.2$: Результаты после второго прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Рис. $3.1$: Результаты после первого прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями (Рис. $3.1$). Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$:&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O, P).$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_5c.png|thumb|right|250px|Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5d.png|thumb|right|250px|Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5f.png|thumb|right|250px|Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5g.png|thumb|right|250px|Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5h.png|thumb|right|250px|Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода (Рис. $3.2$). Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью). Если применять второй проход сразу, то результаты получаются хуже (Рис. $4.2$).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты (Рис. $4.3$). Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём функцию потерь с такой модификацией $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{s1}(S, O, P) + w_{hist}\mathcal{L}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O),$$ &lt;br /&gt;
где $w_{style}, w_{hist}, w_{tv}$ {{---}} веса соответсвующих функций потерь.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5g.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5h.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Рис. $5$: Результат постобработки (без постобработки, после первой стадии, после второй стадии)&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты (Рис. $5$). Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в цветовое пространство [https://en.wikipedia.org/wiki/CIELAB_color_space $L*\alpha*\beta$] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Рис. $6$: Влияние $l_{ref}$ на результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1 (что будет если использовать другие слои видно на Рис. $6$).&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
| $\tau$&lt;br /&gt;
| $\tau$&lt;br /&gt;
| $\tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На рисунке $4.4$ результат алгоритма без подбора гиперпараметров. Видно, что самолёт ярче, чем остальное изображение. С подбором параметров получается более естественный результат (Рис. $4.5$).&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
Примеры взяты с [https://github.com/luanfujun/deep-painterly-harmonization/tree/master/results гитхаба авторов].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|200px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:5_final_res.png|200px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|200px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:6_final_res.png|200px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|200px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:10_final_res.png|200px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски.&lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$.&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$, совпадают.&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения (Рис. $7.1$ и $7.2$).&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}.$$ }}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
!Рис. $7.1$:&amp;lt;br&amp;gt;Исходное изображение&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Lenna#/media/File:Lenna_(test_image).png&amp;lt;/ref&amp;gt;&lt;br /&gt;
!Рис. $7.2$:&amp;lt;br&amp;gt;Применение фильтра Лапласа&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Lenna.png|220px]]&lt;br /&gt;
| [[Файл:Lenna_Laplacian_Neg.png|220px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для сохранения контуров изображений $S$ и $I$ в области вставки воспользуемся идеей из [[Блендинг изображений#Блендинг Пуассона|метода Пуассона]] и введём следующую функцию потерь&amp;lt;ref name='ZWS20'/&amp;gt;:&lt;br /&gt;
$$\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},$$&lt;br /&gt;
где $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* $\mathcal{L}_{content}$ для сохранения содержания накладываемого изображения $I$.&lt;br /&gt;
* $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$.&lt;br /&gt;
* $\mathcal{L}_{hist}$ для стабилизации переноса стиля.&lt;br /&gt;
* $\mathcal{L}_{tv}$ для удаления шумов.&lt;br /&gt;
* $\mathcal{L}_{grad}$ для сохранения контуров фона и изображения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- 0JAg0LXRidGRINCd0LDRgdGC0Y8g0L7Rh9C10L3RjCDQvNC40LvQsNGPIQ== --&amp;gt;&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$&lt;br /&gt;
Для решения задачи минимизации авторы статьи&amp;lt;ref name='ZWS20' /&amp;gt; используют алгоритм L-BFGS&amp;lt;ref name=&amp;quot;LBFGS&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Limited-memory_BFGS Limited-memory BFGS - Wikipedia&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Отметим, что $\mathcal{L}_{content}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\mathcal{L}_{total}(O) = w_{content}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$B$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(O) \leftarrow w_{cont}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results гитхаба авторов]:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! После первого этапа&lt;br /&gt;
! После обоих этапов&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:1_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:1_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:3_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:3_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:5_second_pass.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
В статье использовались следующие значения коэффициентов:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{content}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!--Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 VGG-19, для $\mathcal{L}_{content}$ {{---}} conv2_2.--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Коэффициенты $\alpha$ и $\beta$&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_2 &lt;br /&gt;
! conv2_2&lt;br /&gt;
! conv3_3&lt;br /&gt;
! conv4_3 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results гитхаба авторов]:&lt;br /&gt;
&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Neural_Style_Transfer|Neural Style Transfer]]&lt;br /&gt;
* [[Сверточные_нейронные_сети | Свёрточная нейронная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Источники информации==&lt;br /&gt;
* [https://en.wikipedia.org/wiki/Histogram_matching Histogram matching]&lt;br /&gt;
* Patrick Perez, Michel Gangnet, Andrew Blake (2003), [https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing].&lt;br /&gt;
&amp;lt;!--* Karen Simonyan, Andrew Zisserman (2014), [https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition]--&amp;gt;&lt;br /&gt;
* Leon A. Gatys, Alexander S. Ecker, Matthias Bethge (2016), [https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&lt;br /&gt;
&amp;lt;!--* Eric Risser, Pierre Wilmot, Connelly Barnes (2017), [https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses]--&amp;gt;&lt;br /&gt;
&amp;lt;!--* Aravindh Mahendran, Andrea Vedaldi (2015), [https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them]--&amp;gt;&lt;br /&gt;
&amp;lt;!--* Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016), [https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution]--&amp;gt;&lt;br /&gt;
&amp;lt;!--* Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017), [https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy]--&amp;gt;&lt;br /&gt;
* Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018), [https://arxiv.org/pdf/1804.03189.pdf Deep Painterly Harmonization]&lt;br /&gt;
* Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020), [https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79754</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79754"/>
				<updated>2021-01-21T18:10:23Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: табличка с коэффициентами&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Копирование элемента одного изображения и его вставка на другое изображение {{---}} один из наиболее используемых методов для создания  графического контента. Простая вставка, как правило, бросается в глаза и делает результат похожим на коллаж, во многих случаях этот эффект является нежелательным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки. }}&lt;br /&gt;
Основная трудность задачи заключается в том, что естественность результата зависит не только от бесшовности наложения, но и от схожести цветов и текстуры вставляемого и фонового изображений.  &lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$: Пример перепада яркости при простой вставке&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$: Результат применения блендинга Пуассона&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$ {{---}} область, заданная маской $M$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$.&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Нейронный перенос стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу нейронного переноса стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt; (конкретные слои указаны ниже в деталях реализации).&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} матрица значений выхода $l$-го слоя сети на изображении $I$. Выход $l$-го слоя сети имеет размерность $N_l \times W_l \times H_l$. Представим его как матрицу $N_l \times M_l$, где $N_l$ {{---}} количество фильтров в $l$-ом слое, $M_l$ {{---}} количество признаков ($M_l = W_l H_l$). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое. Столбец матрицы $F^l\left[I\right]$ размера $N_l$ назовём '''вектором активации'''.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. &lt;br /&gt;
$$G^l\left[S\right] \in \mathcal{R}^{N_l \times N_l},$$&lt;br /&gt;
$$G^l\left[S\right] = F^l\left[S\right]F^l\left[S\right]^T.$$}}&lt;br /&gt;
&lt;br /&gt;
Далее рассмотренны функции потерь, которые мы будем использовать.&lt;br /&gt;
&lt;br /&gt;
===Content loss===&lt;br /&gt;
&lt;br /&gt;
$F^l\left[I\right]$ отражает содержание изображения. Мы хотим чтобы содержание результата было как можно ближе к исходной картинке. Введём для этого такую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Style loss===&lt;br /&gt;
&lt;br /&gt;
$G^l\left[S\right]$ отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. Чтобы стиль результата был похож на стилевое изображение, введём следующую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{style}(S, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} \left(G^l_{ij}\left[S\right] - G^l_{ij}\left[O\right]\right)^2,$$&lt;br /&gt;
где $\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Gatys' loss===&lt;br /&gt;
&lt;br /&gt;
Скомбинируем $\mathcal{L}_{content}$ и $\mathcal{L}_{style}$ и получим функцию потерь, которая была использована в алгоритме Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
$$\mathcal{L}_{Gatys}(I, S, O) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O).$$&lt;br /&gt;
Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые мы выберем позднее. &lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили учитывать ещё одну функцию потерь, основанную на '''сопоставлении гистограмм'''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$, тогда Histogram loss будет выглядеть так:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
$$\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.$$&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью (Рис. $2$). Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Рис. $2$: Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм состоит из двух проходов. Первый проход делает грубую гармонизацию, а второй {{---}} более тщательную. Отличаются они '''стилевым маппингом''' и функциями потерь&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' назовём отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход состоит из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Рис. $3.2$: Результаты после второго прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Рис. $3.1$: Результаты после первого прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями (Рис. $3.1$). Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$:&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O, P).$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_5c.png|thumb|right|250px|Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5d.png|thumb|right|250px|Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5f.png|thumb|right|250px|Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5g.png|thumb|right|250px|Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5h.png|thumb|right|250px|Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода (Рис. $3.2$). Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью). Если применять второй проход сразу, то результаты получаются хуже (Рис. $4.2$).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты (Рис. $4.3$). Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём функцию потерь с такой модификацией $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{s1}(S, O, P) + w_{hist}\mathcal{L}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O),$$ &lt;br /&gt;
где $w_{style}, w_{hist}, w_{tv}$ {{---}} веса соответсвующих функций потерь.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5g.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5h.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Рис. $5$: Результат постобработки (без постобработки, после первой стадии, после второй стадии)&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты (Рис. $5$). Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в цветовое пространство [https://en.wikipedia.org/wiki/CIELAB_color_space $L*\alpha*\beta$] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Рис. $6$: Влияние $l_{ref}$ на результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1 (что будет если использовать другие слои видно на Рис. $6$).&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
| $\tau$&lt;br /&gt;
| $\tau$&lt;br /&gt;
| $\tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На рисунке $4.4$ результат алгоритма без подбора гиперпараметров. Видно, что самолёт ярче, чем остальное изображение. С подбором параметров получается более естественный результат (Рис. $4.5$).&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
Примеры взяты с [https://github.com/luanfujun/deep-painterly-harmonization/tree/master/results гитхаба авторов].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|200px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:5_final_res.png|200px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|200px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:6_final_res.png|200px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|200px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:10_final_res.png|200px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски.&lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$.&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$, совпадают.&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения (Рис. $7.1$ и $7.2$).&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}.$$ }}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
!Рис. $7.1$:&amp;lt;br&amp;gt;Исходное изображение&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Lenna#/media/File:Lenna_(test_image).png&amp;lt;/ref&amp;gt;&lt;br /&gt;
!Рис. $7.2$:&amp;lt;br&amp;gt;Применение фильтра Лапласа&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Lenna.png|220px]]&lt;br /&gt;
| [[Файл:Lenna_Laplacian_Neg.png|220px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для сохранения контуров изображений $S$ и $I$ в области вставки воспользуемся идеей из [[Блендинг изображений#Блендинг Пуассона|метода Пуассона]] и введём следующую функцию потерь&amp;lt;ref name='ZWS20'/&amp;gt;:&lt;br /&gt;
$$\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},$$&lt;br /&gt;
где $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* $\mathcal{L}_{content}$ для сохранения содержания накладываемого изображения $I$.&lt;br /&gt;
* $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$.&lt;br /&gt;
* $\mathcal{L}_{hist}$ для стабилизации переноса стиля.&lt;br /&gt;
* $\mathcal{L}_{tv}$ для удаления шумов.&lt;br /&gt;
* $\mathcal{L}_{grad}$ для сохранения контуров фона и изображения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- 0JAg0LXRidGRINCd0LDRgdGC0Y8g0L7Rh9C10L3RjCDQvNC40LvQsNGPIQ== --&amp;gt;&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$&lt;br /&gt;
Для решения задачи минимизации авторы статьи&amp;lt;ref name='ZWS20' /&amp;gt; используют алгоритм L-BFGS&amp;lt;ref name=&amp;quot;LBFGS&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Limited-memory_BFGS Limited-memory BFGS - Wikipedia&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Отметим, что $\mathcal{L}_{content}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\mathcal{L}_{total}(O) = w_{content}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$B$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(O) \leftarrow w_{cont}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results гитхаба авторов]:&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! После первого этапа&lt;br /&gt;
! После обоих этапов&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:1_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:1_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:3_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:3_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:5_second_pass.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
В статье использовались следующие значения коэффициентов:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{content}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&amp;lt;!--Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 VGG-19, для $\mathcal{L}_{content}$ {{---}} conv2_2.--&amp;gt;&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Коэффициенты $\alpha$ и $\beta$&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_2 &lt;br /&gt;
! conv2_2&lt;br /&gt;
! conv3_3&lt;br /&gt;
! conv4_3 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results гитхаба авторов]:&lt;br /&gt;
&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Neural_Style_Transfer|Neural Style Transfer]]&lt;br /&gt;
* [[Сверточные_нейронные_сети | Свёрточная нейронная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79692</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=79692"/>
				<updated>2021-01-21T16:59:30Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Ссылки на картинки и на их источники&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Копирование элемента одного изображения и его вставка на другое изображение {{---}} один из наиболее используемых методов для создания  графического контента. Простая вставка, как правило, бросается в глаза и делает результат похожим на коллаж, во многих случаях этот эффект является нежелательным.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки. }}&lt;br /&gt;
Основная трудность задачи заключается в том, что естественность результата зависит не только от бесшовности наложения, но и от схожести цветов и текстуры вставляемого и фонового изображений.  &lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$: Пример перепада яркости при простой вставке&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$: Результат применения блендинга Пуассона&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$ {{---}} область, заданная маской $M$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$.&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Нейронный перенос стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу нейронного переноса стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt; (конкретные слои будут указаны ниже).&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} матрица значений выхода $l$-го слоя сети на изображении $I$. Выход $l$-го слоя сети имеет размерность $N_l \times W_l \times H_l$. Представим его как матрицу $N_l \times M_l$, где $N_l$ {{---}} количество фильтров в $l$-ом слое, $M_l$ {{---}} количество признаков ($M_l = W_l H_l$). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое. Столбец матрицы $F^l\left[I\right]$ размера $N_l$ назовём '''вектором активации'''.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. &lt;br /&gt;
$$G^l\left[S\right] \in \mathcal{R}^{N_l \times N_l},$$&lt;br /&gt;
$$G^l\left[S\right] = F^l\left[S\right]F^l\left[S\right]^T.$$}}&lt;br /&gt;
&lt;br /&gt;
Далее рассмотренны функции потерь, которые мы будем использовать.&lt;br /&gt;
&lt;br /&gt;
===Content loss===&lt;br /&gt;
&lt;br /&gt;
$F^l\left[I\right]$ отражает содержание изображения. Мы хотим чтобы содержание результата было как можно ближе к исходной картинке. Введём для этого такую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Style loss===&lt;br /&gt;
&lt;br /&gt;
$G^l\left[S\right]$ отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. Чтобы стиль результата был похож на стилевое изображение, введём следующую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{style}(S, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} \left(G^l_{ij}\left[S\right] - G^l_{ij}\left[O\right]\right)^2,$$&lt;br /&gt;
где $\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Gatys' loss===&lt;br /&gt;
&lt;br /&gt;
Скомбинируем $\mathcal{L}_{content}$ и $\mathcal{L}_{style}$ и получим функцию потерь, которая была использована в алгоритме Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
$$\mathcal{L}_{Gatys}(I, S, O) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O).$$&lt;br /&gt;
Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые мы выберем позднее. &lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили учитывать ещё одну функцию потерь, основанную на '''сопоставлении гистограмм'''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$, тогда Histogram loss будет выглядеть так:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
$$\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.$$&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью (Рис. $2$). Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Рис. $2$: Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм состоит из двух проходов. Первый проход делает грубую гармонизацию, а второй {{---}} более тщательную. Отличаются они '''стилевым маппингом''' и функциями потерь&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' назовём отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход состоит из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Рис. $3.2$: Результаты после второго прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Рис. $3.1$: Результаты после первого прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями (Рис. $3.1$). Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$:&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O, P).$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_5c.png|thumb|right|250px|Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5d.png|thumb|right|250px|Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5f.png|thumb|right|250px|Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5g.png|thumb|right|250px|Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
[[Файл:LPSB18_Figure_5h.png|thumb|right|250px|Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода (Рис. $3.2$). Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью). Если применять второй проход сразу, то результаты получаются хуже (Рис. $4.2$).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты (Рис. $4.3$). Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём функцию потерь с такой модификацией $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{s1}(S, O, P) + w_{hist}\mathcal{L}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O),$$ &lt;br /&gt;
где $w_{style}, w_{hist}, w_{tv}$ {{---}} веса соответсвующих функций потерь.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| Рис. $4.1$: Только первый проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.2$: Только второй проход&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.3$: Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.4$: Оба прохода&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
| Рис. $4.5$: Финальный результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5g.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5h.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Рис. $5$: Результат постобработки (без постобработки, после первой стадии, после второй стадии)&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты (Рис. $5$). Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в цветовое пространство [https://en.wikipedia.org/wiki/CIELAB_color_space $L*\alpha*\beta$] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Рис. $6$: Влияние $l_{ref}$ на результат&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1 (что будет если использовать другие слои видно на Рис. $6$).&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На рисунке $4.4$ результат алгоритма без подбора гиперпараметров. Видно, что самолёт ярче, чем остальное изображение. С подбором параметров получается более естественный результат (Рис. $4.5$).&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
Примеры взяты с [https://github.com/luanfujun/deep-painterly-harmonization/tree/master/results гитхаба авторов].&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|200px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:5_final_res.png|200px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|200px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:6_final_res.png|200px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|200px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|200px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|200px]]&lt;br /&gt;
| [[Файл:10_final_res.png|200px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски.&lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$.&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$, совпадают.&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&amp;lt;ref name='ZWS20'/&amp;gt;&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения (Рис. $7.1$ и $7.2$).&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}.$$ }}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
!Рис. $7.1$:&amp;lt;br&amp;gt;Исходное изображение&amp;lt;ref&amp;gt;https://en.wikipedia.org/wiki/Lenna#/media/File:Lenna_(test_image).png&amp;lt;/ref&amp;gt;&lt;br /&gt;
!Рис. $7.2$:&amp;lt;br&amp;gt;Применение фильтра Лапласа&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Lenna.png|220px]]&lt;br /&gt;
| [[Файл:Lenna_Laplacian_Neg.png|220px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для сохранения контуров изображений $S$ и $I$ в области вставки воспользуемся идеей из [[Блендинг изображений#Блендинг Пуассона|метода Пуассона]] и введём следующую функцию потерь&amp;lt;ref name='ZWS20'/&amp;gt;:&lt;br /&gt;
$$\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},$$&lt;br /&gt;
где $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* $\mathcal{L}_{content}$ для сохранения содержания накладываемого изображения $I$.&lt;br /&gt;
* $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$.&lt;br /&gt;
* $\mathcal{L}_{hist}$ для стабилизации переноса стиля.&lt;br /&gt;
* $\mathcal{L}_{tv}$ для удаления шумов.&lt;br /&gt;
* $\mathcal{L}_{grad}$ для сохранения контуров фона и изображения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- 0JAg0LXRidGRINCd0LDRgdGC0Y8g0L7Rh9C10L3RjCDQvNC40LvQsNGPIQ== --&amp;gt;&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$&lt;br /&gt;
Для решения задачи минимизации авторы статьи&amp;lt;ref name='ZWS20' /&amp;gt; используют алгоритм L-BFGS&amp;lt;ref name=&amp;quot;LBFGS&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Limited-memory_BFGS Limited-memory BFGS - Wikipedia&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Отметим, что $\mathcal{L}_{content}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\mathcal{L}_{total}(O) = w_{content}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$B$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(O) \leftarrow w_{cont}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results гитхаба авторов]&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! После первого этапа&lt;br /&gt;
! После обоих этапов&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:1_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:1_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:3_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:3_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:5_second_pass.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{content}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 $VGG$, для $\mathcal{L}_{content}$ {{---}} conv2_2.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
Примеры с [https://github.com/owenzlz/DeepImageBlending/tree/master/results гитхаба авторов]&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Neural_Style_Transfer|Neural Style Transfer]]&lt;br /&gt;
* [[Сверточные_нейронные_сети | Свёрточная нейронная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5h.png&amp;diff=79677</id>
		<title>Файл:LPSB18 Figure 5h.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5h.png&amp;diff=79677"/>
				<updated>2021-01-21T16:33:00Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5g.png&amp;diff=79676</id>
		<title>Файл:LPSB18 Figure 5g.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5g.png&amp;diff=79676"/>
				<updated>2021-01-21T16:32:49Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=78468</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=78468"/>
				<updated>2021-01-14T19:42:55Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Убрал лоссы из определений, переработал раздел с переносом стиля.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. }}&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$.&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Нейронный перенос стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу нейронного переноса стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt; (конкретные слои будут указаны ниже).&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} матрица значений выхода $l$-го слоя сети на изображении $I$. Выход $l$-го слоя сети имеет размерность $N_l \times W_l \times H_l$. Представим его как матрицу $N_l \times M_l$, где $N_l$ {{---}} количество фильтров в $l$-ом слое, $M_l$ {{---}} количество признаков ($M_l = W_l H_l$). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое. Столбец матрицы $F^l\left[I\right]$ размера $N_l$ назовём '''вектором активации'''.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. &lt;br /&gt;
$$G^l\left[S\right] \in \mathcal{R}^{N_l \times N_l},$$&lt;br /&gt;
$$G^l\left[S\right] = F^l\left[S\right]F^l\left[S\right]^T.$$}}&lt;br /&gt;
&lt;br /&gt;
Далее рассмотренны функции потерь, которые мы будем использовать.&lt;br /&gt;
&lt;br /&gt;
===Content loss===&lt;br /&gt;
&lt;br /&gt;
$F^l\left[I\right]$ отражает содержание изображения. Мы хотим чтобы содержание результата было как можно ближе к исходной картинке. Введём для этого такую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Style loss===&lt;br /&gt;
&lt;br /&gt;
$G^l\left[S\right]$ отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. Чтобы стиль результата был похож на стилевое изображение, введём следующую функцию потерь:&lt;br /&gt;
$$\mathcal{L}_{style}(S, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} \left(G^l_{ij}\left[S\right] - G^l_{ij}\left[O\right]\right)^2,$$&lt;br /&gt;
где $\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
===Gatys' loss===&lt;br /&gt;
&lt;br /&gt;
Скомбинируем $\mathcal{L}_{content}$ и $\mathcal{L}_{style}$ и получим функцию потерь, которая была использована в алгоритме Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
$$\mathcal{L}_{Gatys}(I, S, O) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O).$$&lt;br /&gt;
Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые мы выберем позднее. &lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили учитывать ещё одну функцию потерь, основанную на '''сопоставлении гистограмм'''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$, тогда Histogram loss будет выглядеть так:&lt;br /&gt;
$$\mathcal{L}_{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,$$&lt;br /&gt;
где $\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
$$\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.$$&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм состоит из двух проходов. Первый проход делает грубую гармонизацию, а второй {{---}} более тщательную. Отличаются они '''стилевым маппингом''' и функциями потерь&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' назовём отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход состоит из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$:&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(S, O, P).$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём функцию потерь с такой модификацией $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_2(I, S, O, P) = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{s1}(S, O, P) + w_{hist}\mathcal{L}_{hist}(S, O) + w_{tv}\mathcal{L}_{tv}(O),$$ &lt;br /&gt;
где $w_{style}, w_{hist}, w_{tv}$ {{---}} веса соответсвующих функций потерь.&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Только второй проход&lt;br /&gt;
! Только первый проход&lt;br /&gt;
! Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в цветовое пространство [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения.&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}.$$ }}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
!Исходное изображение&lt;br /&gt;
!Применение фильтра Лапласа&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Lenna.png|200px]]&lt;br /&gt;
| [[Файл:Lenna_Laplacian_Neg.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для сохранения контуров изображений $S$ и $I$ в области вставки воспользуемся идеей из [[Блендинг изображений#Блендинг Пуассона|метода Пуассона]] и введём следующую функцию потерь&amp;lt;ref name='ZWS20'/&amp;gt;:&lt;br /&gt;
$$\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},$$&lt;br /&gt;
где $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* $\mathcal{L}_{content}$ для сохранения содержания накладываемого изображения $I$.&lt;br /&gt;
* $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$.&lt;br /&gt;
* $\mathcal{L}_{hist}$ для стабилизации переноса стиля.&lt;br /&gt;
* $\mathcal{L}_{tv}$ для удаления шумов.&lt;br /&gt;
* $\mathcal{L}_{grad}$ для сохранения контуров фона и изображения.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- 0JAg0LXRidGRINCd0LDRgdGC0Y8g0L7Rh9C10L3RjCDQvNC40LvQsNGPIQ== --&amp;gt;&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \mathcal{L}_{total}(Z) = w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B).$$&lt;br /&gt;
Отметим, что $\mathcal{L}_{content}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{content}\mathcal{L}_{content}(I, M, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\mathcal{L}_{total}(O) = w_{content}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O).$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$B$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(O) \leftarrow w_{cont}\mathcal{L}_{content}(B, O) + w_{style}\mathcal{L}_{style}(S, O) + w_{tv}\mathcal{L}_{tv}(O) + w_{hist}\mathcal{L}_{hist}(S, O)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! После первого этапа&lt;br /&gt;
! После обоих этапов&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:1_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:1_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:3_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:3_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:5_second_pass.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{content}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 $VGG$, для $\mathcal{L}_{content}$ {{---}} conv2_2.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Neural_Style_Transfer|Neural Style Transfer]]&lt;br /&gt;
* [[Сверточные_нейронные_сети | Свёрточная нейронная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=78403</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=78403"/>
				<updated>2021-01-14T17:20:43Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Точка, точка, запятая&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. }}&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$.&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}.&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$.&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}.&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $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]$ отражает содержание изображения.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. &lt;br /&gt;
$$G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l},$$&lt;br /&gt;
$$G^l\left[I\right] = F^l\left[I\right]F^l\left[I\right]^T.$$}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь.}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это столбец $F_l$.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y \times W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}^{\beta}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь.}$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь.}$$&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Только второй проход&lt;br /&gt;
! Только первый проход&lt;br /&gt;
! Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 5em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так, чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур).&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$.&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения.&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}.$$ }}&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
!Исходное изображение&lt;br /&gt;
!Применение фильтра Лапласа&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Lenna.png|200px]]&lt;br /&gt;
| [[Файл:Lenna_Laplacian_Neg.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Чтобы комбинировать решение задачи бесшовного наложения [[Блендинг изображений#Блендинг Пуассона|методом Пуассона]] с остальными ограничениями, авторы статьи&amp;lt;ref name='ZWS20'/&amp;gt; предлагают использовать функцию потерь  $\mathcal{L}_{grad}$. Для сохранения контуров изображений $S$ и $I$ в области вставки используется дискретный оператор Лапласа.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$. }}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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).$$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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).$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, который инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$B$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
     &amp;lt;span style=&amp;quot;display: inline-block; width: 3em&amp;quot;&amp;gt;$S$ &amp;lt;/span&amp;gt; &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! После первого этапа&lt;br /&gt;
! После обоих этапов&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:1_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:1_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:3_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:3_second_pass.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_first_pass.png|300px]]&lt;br /&gt;
| [[Файл:5_second_pass.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{cont}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои conv1_2, conv2_2, conv3_3, conv4_3 $VGG$, для $\mathcal{L}_{cont}$ {{---}} conv2_2.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==См. также==&lt;br /&gt;
* [[Neural_Style_Transfer|Neural Style Transfer]]&lt;br /&gt;
* [[Сверточные_нейронные_сети | Свёрточная нейронная сеть]]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;br /&gt;
&lt;br /&gt;
[[Категория: Машинное обучение]]&lt;br /&gt;
[[Категория: Нейронные сети]]&lt;br /&gt;
[[Категория: Сверточные нейронные сети]]&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77544</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77544"/>
				<updated>2021-01-11T18:17:00Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Глубокая гармонизация картинhttps://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. }}&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $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]$ отражает содержание изображения.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. &lt;br /&gt;
$$G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l}$$&lt;br /&gt;
$$G^l\left[I\right] = F^l\left[I\right]F^l\left[I\right]^T$$}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; ($3$ картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; ($4$ картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений с использованием функции потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это столбец $F_l$.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре выхода свёрточного слоя, с центром в $(x, y)$, где $j = y \times W_l + x$.}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм $IndependentMapping$ для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что в $\mathcal{L}^{\beta}_{style}$ к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (таким образом мы хотим переносить сложные текстуры более качественно, например, мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in \left\{N, NE, E, SE, S, SW, W, NW\right\}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Только второй проход&lt;br /&gt;
! Только первый проход&lt;br /&gt;
! Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать $18$ различных стилей. Эти стили были разделены на $3$ категории с разными $\tau$. Используя $Softmax$ можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения.&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}$$ }}&lt;br /&gt;
&lt;br /&gt;
** TODO картиночка**&lt;br /&gt;
&lt;br /&gt;
Чтобы комбинировать решение задачи бесшовного наложения [[Блендинг изображений#Блендинг Пуассона|методом Пуассона]] с остальными ограничениями, авторы статьи&amp;lt;ref name='ZWS20'/&amp;gt; предлагают использовать функцию потерь  $\mathcal{L}_{grad}$. Для сохранения контуров изображений $S$ и $I$ в области вставки используется дискретный оператор Лапласа.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$. }}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{cont}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои $conv{1_2}, conv{2_2}, conv{3_3}, conv{4_3}$ $VGG$, для $\mathcal{L}_{cont}$ {{---}} $conv{2_2}$.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77532</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77532"/>
				<updated>2021-01-11T17:26:24Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Трансфер стиля */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. }}&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  Идея подхода ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \underset{\Omega}{\iint} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $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}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Добавим условие $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}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(I, S, O) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(I, S, O)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $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]$ отражает содержание изображения.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения. &lt;br /&gt;
$$G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l}$$&lt;br /&gt;
$$G^l\left[I\right] = F^l\left[I\right]F^l\left[I\right]^T$$}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Дискретный оператор Лапласа''' (фильтр Лапласа) $\mathbf{D}^2$ {{---}} аналог непрерывного оператора Лапласа $\nabla^2$, который позволяет выделять контуры изображения.&lt;br /&gt;
$$\mathbf{D}^2=\begin{bmatrix}0 &amp;amp; 1 &amp;amp; 0\\1 &amp;amp; -4 &amp;amp; 1\\0 &amp;amp; 1 &amp;amp; 0\end{bmatrix}$$ }}&lt;br /&gt;
&lt;br /&gt;
** TODO картиночка**&lt;br /&gt;
&lt;br /&gt;
Чтобы комбинировать решение задачи бесшовного наложения [[Блендинг изображений#Блендинг Пуассона|методом Пуассона]] с остальными ограничениями, авторы статьи&amp;lt;ref name='ZWS20'/&amp;gt; предлагают использовать функцию потерь  $\mathcal{L}_{grad}$. Для сохранения контуров изображений $S$ и $I$ в области вставки используется дискретный оператор Лапласа.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$. }}&lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{cont}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои $conv{1_2}, conv{2_2}, conv{3_3}, conv{4_3}$ $VGG$, для $\mathcal{L}_{cont}$ {{---}} $conv{2_2}$.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77503</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77503"/>
				<updated>2021-01-11T14:55:31Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Второй проход */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм $ConsistentMapping$ построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
Чтобы комбинировать решение задачи бесшовного наложения [[Блендинг изображений#Блендинг Пуассона|методом Пуассона]] с остальными ограничениями, авторы статьи&amp;lt;ref name='ZWS20'/&amp;gt; предлагают использовать функцию потерь  $\mathcal{L}_{grad}$, являющуюся приближением уравнения Пуассона $(2)$. $\mathcal{L}_{grad}$ минимизирует разность градиента искомого изображения $B$ и суммы градиентов входных изображений $S$ и $I$. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{cont}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои $conv{1_2}, conv{2_2}, conv{3_3}, conv{4_3}$ $VGG$, для $\mathcal{L}_{cont}$ {{---}} $conv{2_2}$.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77502</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77502"/>
				<updated>2021-01-11T14:55:03Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Второй проход */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_I$ возьмем градиент вставляемого изображения $I$: $v_I = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $ConsistentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
Чтобы комбинировать решение задачи бесшовного наложения [[Блендинг изображений#Блендинг Пуассона|методом Пуассона]] с остальными ограничениями, авторы статьи&amp;lt;ref name='ZWS20'/&amp;gt; предлагают использовать функцию потерь  $\mathcal{L}_{grad}$, являющуюся приближением уравнения Пуассона $(2)$. $\mathcal{L}_{grad}$ минимизирует разность градиента искомого изображения $B$ и суммы градиентов входных изображений $S$ и $I$. &lt;br /&gt;
&lt;br /&gt;
Рассмотрим область $\overline{\Omega} = \{\;p \;| \;M_p = 0\; \}$. Заметим, что градиент $I$ в $\overline{\Omega}$ равен нулю. Тогда градиенты $S$ и $B$ совпадают, и задача минимизации $\mathcal{L}_{grad}$ решается только в области вставки.  &lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Детали реализации===&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Веса функций потерь&lt;br /&gt;
|-&lt;br /&gt;
! Этап&lt;br /&gt;
! $w_{grad}$&lt;br /&gt;
! $w_{cont}$&lt;br /&gt;
! $w_{style}$&lt;br /&gt;
! $w_{hist}$&lt;br /&gt;
! $w_{tv}$ &lt;br /&gt;
|-&lt;br /&gt;
! $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^5$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|-&lt;br /&gt;
! $2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^7$&lt;br /&gt;
| $1$&lt;br /&gt;
| $10^{-6}$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ используются слои $conv{1_2}, conv{2_2}, conv{3_3}, conv{4_3}$ $VGG$, для $\mathcal{L}_{cont}$ {{---}} $conv{2_2}$.&lt;br /&gt;
&lt;br /&gt;
На обоих этапах максимальное количество итераций алгоритма L-BFGS {{---}} $1000$. &lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77411</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77411"/>
				<updated>2021-01-11T03:57:07Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Первый проход */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' при посчёте градиента $\mathcal{L}^{\alpha}_{content}$ используются только пиксели внутри маски&amp;lt;ref&amp;gt;https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77410</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77410"/>
				<updated>2021-01-11T03:41:31Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Я узнал что такое \underset&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $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$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77409</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77409"/>
				<updated>2021-01-11T03:31:14Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Глубокая гармонизация картинhttps://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом $\pi$ cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь $\mathcal{L}$.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \left\|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\right\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77408</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77408"/>
				<updated>2021-01-11T03:27:51Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Первый проход */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} вес стилевой функции потерь}$$&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \left\|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\right\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77407</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77407"/>
				<updated>2021-01-11T03:27:06Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Второй проход */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$$&lt;br /&gt;
&lt;br /&gt;
где $w_{style}$ {{---}} вес стилевой функции потерь&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \left\|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\right\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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{ {{---}} веса соответсвующих функций потерь}$$&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77406</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77406"/>
				<updated>2021-01-11T03:23:56Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Чуть более красивые скобочки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \left\{ p\;|\;M_p = 1 \right\}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_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&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\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)$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R\left(F^l_{ij}\left[O\right]\right)$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\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'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$$&lt;br /&gt;
&lt;br /&gt;
где $w_{style}$ {{---}} вес стилевой функции потерь&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \left\{P_0(j + o) - o\right\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \left\|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\right\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\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\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W \left[\nabla^2 f(B) - \left(\nabla^2 f(S) + \nabla^2 f(I)\right) \right]^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77405</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77405"/>
				<updated>2021-01-11T03:06:09Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Чуть лучше (надеюсь) стиль картинок&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \{ p\;|\;M_p = 1 \}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2, \text{где } O_p = S_p, p \in \partial \Omega&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(S, O) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R(F^l_{ij}\left[O\right])$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;float:right; clear:right;&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&lt;br /&gt;
|}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2c.png|250px|thumb|none|Результаты после второго прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_2b.png|250px|thumb|none|Результаты после первого прохода]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
&lt;br /&gt;
$$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$$&lt;br /&gt;
&lt;br /&gt;
где $w_{style}$ {{---}} вес стилевой функции потерь&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки, после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|right|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- Настя лапочка :3 --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W [\,\nabla^2 f(B) - (\nabla^2 f(S) + \nabla^2 f(I)) ]\,^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 2stage.png|thumb|none|200px|Результат после обоих этапов]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div class=&amp;quot;tright&amp;quot; style=&amp;quot;clear:none&amp;quot;&amp;gt;[[Файл:Deep bl 1stage.png|thumb|none|200px|Результат первого этапа]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77404</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77404"/>
				<updated>2021-01-11T02:26:40Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Допилил код напильничком)&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \{ p\;|\;M_p = 1 \}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2, \text{где } O_p = S_p, p \in \partial \Omega&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(S, O) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R(F^l_{ij}\left[O\right])$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$M$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$S$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\pi$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 2em&amp;quot;&amp;gt;$\mathcal{L}$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех слоёв от $1$ до $L$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &lt;br /&gt;
      &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Для всех столбцов от $1$ до $M_l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём самый похожий стилевой патч и записываем его в маппинг. &amp;lt;/font&amp;gt; &lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[I]$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$F[S]$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$I$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$Mask$,&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    &amp;lt;span style=&amp;quot;display: inline-block; width: 4em&amp;quot;&amp;gt;$S$&amp;lt;/span&amp;gt;&amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W [\,\nabla^2 f(B) - (\nabla^2 f(S) + \nabla^2 f(I)) ]\,^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
[[Файл:Deep bl 1stage.png|thumb|right|200px|Результат первого этапа]]&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
[[Файл:Deep bl 2stage.png|thumb|right|200px|Результат после обоих этапов]]&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77403</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77403"/>
				<updated>2021-01-11T02:07:33Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Трансфер стиля */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===  TODO заголовок ===&lt;br /&gt;
Пусть замкнутое множество $P \subset \mathbb{R}^2$ {{---}} область, на которой определено изображение $S$, а замкнутое множество $\Omega \subset P$ с границей $\partial\Omega$ и внутренностью $int(\Omega)$ {{---}} область вставки изображения $I$.&lt;br /&gt;
&lt;br /&gt;
Пусть $f_S$ {{---}} скалярная функция, определенная на $P \setminus int(\Omega)$, задает фоновое изображение $S$; $f$ {{---}} неизвестная скалярная функция, определенная на $int(\Omega)$, задает, каким образом должно выглядеть результат блендинга в области вставки. &lt;br /&gt;
&lt;br /&gt;
$v_I$ {{---}} векторное поле, определенное на $\Omega$. В качестве $v_i$ возьмем градиент вставляемого изображения $I$: $v_i = \nabla f_I$&lt;br /&gt;
&lt;br /&gt;
Нашей задачей является поиск такой функции $f$, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции $f$ и векторного поля $v_I$, считая, что $f = f_S$ на границе $\Omega$.&lt;br /&gt;
$$&lt;br /&gt;
\underset{f}{\mathrm{min}} \int\int_{\Omega} |\nabla f - v_I|^2, \text{где } f|_{\partial \Omega} = f_S|_{\partial \Omega}&lt;br /&gt;
$$&lt;br /&gt;
Решение задачи минимизации является единственным решением уравнения Пуассона для граничных условий Дирихле.&lt;br /&gt;
$$\nabla^2 f = \nabla^2 f_I \text{ на } \Omega,  f|_{\partial \Omega} = f_S|_{\partial \Omega}, \text{где } \nabla^2 \text{{{---}} оператор Лапласа.}$$&lt;br /&gt;
&lt;br /&gt;
=== Дискретный случай ===&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \{ p\;|\;M_p = 1 \}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2, \text{где } O_p = S_p, p \in \partial \Omega&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
{{main|Neural Style Transfer}}&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===Алгоритм Гатиса&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=content_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=style_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: '''A)''' $O_0 = I$; '''B)''' $O_0 = S$; '''C)''' $O_0 = random$, $4$ примера инициализированы различными белыми шумами ]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=hist_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(S, O) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R(F^l_{ij}\left[O\right])$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=tv_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из $3$ частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:&lt;br /&gt;
* Используемая для вставки часть $I$ вырезана с помощью маски &lt;br /&gt;
* $M$ и $I$ выровнены относительно $S$&lt;br /&gt;
* Размеры матриц, задающих $M, S, I$ совпадают&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:&lt;br /&gt;
* [[Блендинг_изображений#content_loss_def|Функция потерь содержания]] $\mathcal{L}_{cont}$ для сохранения содержания накладываемого изображения $I$&lt;br /&gt;
* [[Блендинг_изображений#style_loss_def|Функция потерь стиля]] $\mathcal{L}_{style}$ для переноса стиля изображения $S$ на $I$&lt;br /&gt;
* [[Блендинг_изображений#hist_loss_def|Гистограмная функция потерь]] $\mathcal{L}_{hist}$ для стабилизации переноса стиля&lt;br /&gt;
* [[Блендинг_изображений#tv_loss_def|Функция потерь полного отклонения]] $\mathcal{L}_{tv}$ для удаления шумов&lt;br /&gt;
* [[Блендинг_изображений#grad_loss_def|Градиентная функция потерь]] $\mathcal{L}_{grad}$ для бесшовности наложения&lt;br /&gt;
&lt;br /&gt;
Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;. &lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Простой вставкой''' (англ. ''copy and paste'') $CAP(M, S, I)$ будем назвать изображение, полученное наложением части изображения $I$, заданной маской $M$, на изображение $S$.&lt;br /&gt;
 $CAP(M, S, I) = I \odot M + S \odot (1 - M)$, где $\odot$ {{---}} покомпонентное умножение. }}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|id=grad_loss_def&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{grad}(S, I, M, O) = \displaystyle\frac{1}{2HW}\displaystyle\sum_{m=1}^H \displaystyle\sum_{n=1}^W [\,\nabla^2 f(B) - (\nabla^2 f(S) + \nabla^2 f(I)) ]\,^2_{mn}$ {{---}} градиентная функция потерь (англ. ''Possion gradient loss''). $\nabla^2$ {{---}} оператор Лапласа. $H, W$ {{---}} высота и ширина изображений. $B = CAP(M, S, O)$ {{---}} блендинговое изображение, оптимизируемое относительно $O$. }}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
[[Файл:Deep bl 1stage.png|thumb|right|200px|Результат первого этапа]]&lt;br /&gt;
На первом этапе изображение $I$ накладывается на фоновое изображение $S$ таким образом, чтобы были незаметны швы. &lt;br /&gt;
Построение начинается с белого шума $Z$, который оптимизируется в области вставки путем минимизации суммарной функции потерь $\mathcal{L}_{total}$, представленной взвешенной суммой всех функций потерь, описанных выше:&lt;br /&gt;
$$ \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) $$&lt;br /&gt;
Отметим, что $\mathcal{L}_{cont}$ зависит от маски и отвечает за сохранение содержания $I$ в области вставки.&lt;br /&gt;
&lt;br /&gt;
Отличительной чертой этого этапа является использование функции потерь $\mathcal{L}_{grad}$, приближающей градиент результата к градиенту $I$ в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.&lt;br /&gt;
&lt;br /&gt;
В результате получается подготовительное блендинг-изображение $B$:&lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
Z_p,\; \text{если } M_p = 1 \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow CAP(M, S, Z)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $CAP(M, S, Z)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
[[Файл:Deep bl 2stage.png|thumb|right|200px|Результат после обоих этапов]]&lt;br /&gt;
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения $B$ таким образом, чтобы стиль изображения был наиболее близок к стилю $S$. &lt;br /&gt;
&lt;br /&gt;
В отличие от предыдущего этапа, функция потерь не включает в себя $\mathcal{L}_{grad}$:&lt;br /&gt;
$$\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)$$&lt;br /&gt;
&lt;br /&gt;
Минимизация происходит относительно результата алгоритма $O$, которой инициализируется изображением $B$.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77053</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=77053"/>
				<updated>2021-01-09T16:07:31Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Лишние todo и замечание про hist loss&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|300px|Рис. $1.1$. Пример перепада яркости при простой вставке]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|300px|Рис. $1.2$. Результат применения блендинга Пуассона]]&lt;br /&gt;
&lt;br /&gt;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. $1.1$). Метод Пуассона заключается в сглаживании этого перепада (рис. $1.2$) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $S$ изображение, которое служит фоном, а за $I$ {{---}} изображение, вставляемое поверх $S$. Область вставки будем задавать двоичной маской $M$, содержащей единицы в области наложения. Например:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Фоновое &amp;lt;br/&amp;gt; изображение $S$&lt;br /&gt;
! Накладываемое &amp;lt;br/&amp;gt; изображение $I$&lt;br /&gt;
! Маска $M$&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:Poisson_cat.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|200px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|200px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты $(x, y)$ пикселя двухмерного изображения. За $Img_p$ обозначим значение пикселя с координатами $p$ изображения $Img$. Пусть $\Omega = \{ p\;|\;M_p = 1 \}$. Тогда $\partial \Omega$ {{---}} координаты границы вставляемой области, а $int(\Omega)$ {{---}} внутренность области.&lt;br /&gt;
&lt;br /&gt;
Пусть $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$&lt;br /&gt;
&lt;br /&gt;
Введем переменные $O_p, p \in \Omega$. Так как мы хотим сделать результат бесшовным, пиксели $O_p, p \in \partial\Omega$, сделаем равными $S_p$. Для $p, q \in int(\Omega),\; q \in N_p$ постараемся найти такие значения $O_p, O_q$, чтобы их разность была близка к $v_{pq}$. Для этого решим задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$$&lt;br /&gt;
\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2, \text{где } O_p = S_p, p \in \partial \Omega&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in int(\Omega)$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. &lt;br /&gt;
$$\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $\;|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} S_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid&amp;lt;ref name=&amp;quot;PGB03&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Получаем значения пикселей $O_p$, $p \in int(\Omega)$. Тогда результат $B$ блендинга Пуассона будет следующим: &lt;br /&gt;
$$&lt;br /&gt;
B_p =&lt;br /&gt;
\begin{cases}&lt;br /&gt;
O_p,\; \text{если } p \in int(\Omega) \\&lt;br /&gt;
S_p,\; \text{иначе } &lt;br /&gt;
\end{cases}&lt;br /&gt;
$$&lt;br /&gt;
&lt;br /&gt;
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель $I_{p1}$ был меньше $I_{p2}$, то после преобразования $I_{p1}$ не станет больше $I_{p2}$), однако само значение градиета может получиться другим.&amp;lt;ref name='clear_poisson'&amp;gt;https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
'''Замечание:''' Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку $\displaystyle\frac{\partial \mathcal{L}_{hist}}{\partial F^l_{ij}\left[O\right]}$ является нулём почти везде, авторы предлагают при подсчёте производной считать $R(F^l_{ij}\left[O\right])$ константой, которая не зависит от $O$.&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения $S$ бесшовно накладывается входное изображение $I$, получается подготовительное блендинг-изображение $B$. На втором этапе $B$ модифицируется таким образом, чтобы результат по стилю был похож на $S$.&lt;br /&gt;
&lt;br /&gt;
'''Примеры входных данных:'''&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! '''Стилевое &amp;lt;br/&amp;gt; изображение $S$'''&lt;br /&gt;
| [[Файл:Deep bl s1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl s3.png|150px]]&lt;br /&gt;
|-&lt;br /&gt;
! '''Накладываемое &amp;lt;br/&amp;gt; изображение $I$'''&lt;br /&gt;
| [[Файл:Deep bl i1.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i2.png|150px]]&lt;br /&gt;
| [[Файл:Deep bl i3.png|150px]]&lt;br /&gt;
|}&lt;br /&gt;
=== Первый этап ===&lt;br /&gt;
[[Файл:Deep bl 1stage.png|thumb|right|200px|Результат первого этапа]]&lt;br /&gt;
Построение подготовительного изображения начинается с белого шума. Для подсчета $\mathcal{L}_{style}$ и $\mathcal{L}_{content}$ авторами статьи&amp;lt;ref name='ZWS20'/&amp;gt; использовалась сеть VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;/&amp;gt;, обученная на ImageNet&amp;lt;ref name=&amp;quot;ImageNet&amp;quot;&amp;gt;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&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Для удобства введем вспомогательную функцию применения маски:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вставка части изображения $I$, определенной маской $M$,&amp;lt;/font&amp;gt;&lt;br /&gt;
  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// на изображение $S$ &amp;lt;/font&amp;gt;&lt;br /&gt;
  '''fun''' $ApplyMask(M, I, S)$:&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// За $\odot$ обозначим покомпонентное произведение &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''return''' $I \odot M + S \odot (1 - M)$&lt;br /&gt;
&amp;lt;/font&amp;gt; &lt;br /&gt;
&lt;br /&gt;
Алгоритм первого этапа:&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SeamlessBlending$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем первое приближение белым шумом &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow RandomNoise() $&lt;br /&gt;
    $B \leftarrow ApplyMask(M, Z, S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \leftarrow w_{grad}\mathcal{L}_{grad}(I, S, B) + w_{cont}\mathcal{L}_{cont}(I, Z) + w_{style}\mathcal{L}_{style}(S, B) + w_{tv}\mathcal{L}_{tv}(B) + w_{hist}\mathcal{L}_{hist}(S, B)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $Z$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Z \leftarrow Reconstruct(\mathcal{L}_{total}, Z)$&lt;br /&gt;
    '''return''' $ApplyMask(M, Z, S)$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Второй этап ===&lt;br /&gt;
[[Файл:Deep bl 2stage.png|thumb|right|200px|Результат после обоих этапов]]&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $StyleRefinement$(&lt;br /&gt;
    $B$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Подготовительное блендинг-изображение, результат первого этапа &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    $O \leftarrow B$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Определим суммарную функцию потерь с весами слагаемых $w$&amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}_{total}(Z) \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)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// С помощью алгоритма L-BFGS ищем изображение $O$, которое минимизирует $\mathcal{L}_{total}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(\mathcal{L}_{total}, O)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Примеры ===&lt;br /&gt;
[[Файл:МЛ блендинг пример.png|1000px]]&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76689</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76689"/>
				<updated>2021-01-07T20:13:21Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: перенос таблицы&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
*картинка (можно вставить картинку с дайвером, если сможем её обработать гармонизатором)*&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
*картинка с дайвером (там видно, что пузырики с фонового изображения остались поверх дайвера)*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
todo Note: Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки. Метод Пуассона заключается в сглаживании этого перепада с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
todo Note: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $A$ изображение, которое служит фоном, а за $B$ {{---}} изображение, вставляемое поверх $A$.&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты пикселя двухмерного изображения (т.е. $(x, y)$). $A_p$ {{---}} значения пикселя фонового изображение, $B_p$ {{---}} значение пикселя вставляемого изображения. Пусть $\Omega$ {{---}} множество координат $p$, на которых определено вставляемое изображение $B$. $\partial \Omega$ {{---}} координаты границы вставляемой области.&lt;br /&gt;
&lt;br /&gt;
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $&amp;lt;p, q&amp;gt;$ таких, что $q \in N_p$, введем $v_{pq} = B_p - B_q$&lt;br /&gt;
&lt;br /&gt;
Обозначим результат блендинга за $O$. Для того чтобы найти значение пикселей в месте наложения $B$, решаем задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2$, где $O_p = A_p$ для $p \in \partial \Omega$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in \Omega$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.&lt;br /&gt;
&lt;br /&gt;
Для $p \in \Omega$: $\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} A_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Решаем систему уравнений и получаем значения $O_p$ для $p \in \Omega$.&lt;br /&gt;
&lt;br /&gt;
todo: Поскольку система уравнений sparse symmetric positive-defined, можно использовать следующие итеративные алгоритмы: Gauss-Seidel, V-cycle multigrid.&lt;br /&gt;
&lt;br /&gt;
Заметим, что метод Пуассона сдвигает цвета накладываемого изображения и сохраняет свойства градиента (прям всегда? нужно подумоть), туду&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Poisson blending для самых маленьких&lt;br /&gt;
&lt;br /&gt;
https://erkaman.github.io/posts/poisson_blending.html&lt;br /&gt;
&lt;br /&gt;
Another thing that we wish to remark is that even though poisson blending shifts the color of the source image, it still preserves the features of it. In the original source image, f4 is smaller than f3, f5 is greater than f4, and so on, and this also applies to our recovered image. This information was encoded by the gradients of the source image. However, it is also important to realize that poisson blending does not exactly preserve the gradients. In the recovered image, the gradient f3,4 assumes the value 7−4=3, but it was 26−22=4 in the original source image. In the previous section, the gradients of the recovered image were identical to the gradients of the original image. But with poisson blending, the gradients of a completely different image are pasted into another image, and the result of this is that the solver is not always able to recover an image whose gradients exactly match the specified gradients. But the solver tries to find an image whose gradients match as close as possible, and in practice, poisson blending yields good results, which we shall show examples of in the following section.&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' Figure 2b, 5c ()&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Примеры===&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
kekkekek  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76688</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76688"/>
				<updated>2021-01-07T20:11:38Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Итоговый алгоритм */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
*картинка (можно вставить картинку с дайвером, если сможем её обработать гармонизатором)*&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
*картинка с дайвером (там видно, что пузырики с фонового изображения остались поверх дайвера)*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
todo Note: Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки. Метод Пуассона заключается в сглаживании этого перепада с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
todo Note: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $A$ изображение, которое служит фоном, а за $B$ {{---}} изображение, вставляемое поверх $A$.&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты пикселя двухмерного изображения (т.е. $(x, y)$). $A_p$ {{---}} значения пикселя фонового изображение, $B_p$ {{---}} значение пикселя вставляемого изображения. Пусть $\Omega$ {{---}} множество координат $p$, на которых определено вставляемое изображение $B$. $\partial \Omega$ {{---}} координаты границы вставляемой области.&lt;br /&gt;
&lt;br /&gt;
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $&amp;lt;p, q&amp;gt;$ таких, что $q \in N_p$, введем $v_{pq} = B_p - B_q$&lt;br /&gt;
&lt;br /&gt;
Обозначим результат блендинга за $O$. Для того чтобы найти значение пикселей в месте наложения $B$, решаем задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2$, где $O_p = A_p$ для $p \in \partial \Omega$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in \Omega$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.&lt;br /&gt;
&lt;br /&gt;
Для $p \in \Omega$: $\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} A_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Решаем систему уравнений и получаем значения $O_p$ для $p \in \Omega$.&lt;br /&gt;
&lt;br /&gt;
todo: Поскольку система уравнений sparse symmetric positive-defined, можно использовать следующие итеративные алгоритмы: Gauss-Seidel, V-cycle multigrid.&lt;br /&gt;
&lt;br /&gt;
Заметим, что метод Пуассона сдвигает цвета накладываемого изображения и сохраняет свойства градиента (прям всегда? нужно подумоть), туду&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Poisson blending для самых маленьких&lt;br /&gt;
&lt;br /&gt;
https://erkaman.github.io/posts/poisson_blending.html&lt;br /&gt;
&lt;br /&gt;
Another thing that we wish to remark is that even though poisson blending shifts the color of the source image, it still preserves the features of it. In the original source image, f4 is smaller than f3, f5 is greater than f4, and so on, and this also applies to our recovered image. This information was encoded by the gradients of the source image. However, it is also important to realize that poisson blending does not exactly preserve the gradients. In the recovered image, the gradient f3,4 assumes the value 7−4=3, but it was 26−22=4 in the original source image. In the previous section, the gradients of the recovered image were identical to the gradients of the original image. But with poisson blending, the gradients of a completely different image are pasted into another image, and the result of this is that the solver is not always able to recover an image whose gradients exactly match the specified gradients. But the solver tries to find an image whose gradients match as close as possible, and in practice, poisson blending yields good results, which we shall show examples of in the following section.&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' Figure 2b, 5c ()&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
Теперь осталось запустить две стадии &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $Harmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $I' \leftarrow SinglePassHarmonization(I, Mask, S, IndependentMapping, \mathcal{L}_1)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O  \leftarrow SinglePassHarmonization(I', Mask, S, ConsistentMapping, \mathcal{L}_2)$&lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! Исходное изображение&lt;br /&gt;
! Простая вставка&lt;br /&gt;
! Результат&lt;br /&gt;
! Постобработка&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:5_target.jpg|300px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:5_final_res.png|300px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|300px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:6_final_res.png|300px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|300px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|300px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|300px]]&lt;br /&gt;
| [[Файл:10_final_res.png|300px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|300px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
kekkekek  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_final_res.png&amp;diff=76687</id>
		<title>Файл:10 final res.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_final_res.png&amp;diff=76687"/>
				<updated>2021-01-07T20:10:43Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_final_res.png&amp;diff=76686</id>
		<title>Файл:6 final res.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_final_res.png&amp;diff=76686"/>
				<updated>2021-01-07T20:10:34Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_final_res.png&amp;diff=76685</id>
		<title>Файл:5 final res.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_final_res.png&amp;diff=76685"/>
				<updated>2021-01-07T20:10:24Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_target.jpg&amp;diff=76682</id>
		<title>Файл:10 target.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_target.jpg&amp;diff=76682"/>
				<updated>2021-01-07T19:59:57Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_naive.jpg&amp;diff=76681</id>
		<title>Файл:10 naive.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_naive.jpg&amp;diff=76681"/>
				<updated>2021-01-07T19:59:41Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_final_res2.png&amp;diff=76680</id>
		<title>Файл:10 final res2.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:10_final_res2.png&amp;diff=76680"/>
				<updated>2021-01-07T19:59:28Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_target.jpg&amp;diff=76679</id>
		<title>Файл:6 target.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_target.jpg&amp;diff=76679"/>
				<updated>2021-01-07T19:59:18Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_naive.jpg&amp;diff=76678</id>
		<title>Файл:6 naive.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_naive.jpg&amp;diff=76678"/>
				<updated>2021-01-07T19:59:10Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_final_res2.png&amp;diff=76677</id>
		<title>Файл:6 final res2.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:6_final_res2.png&amp;diff=76677"/>
				<updated>2021-01-07T19:59:00Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_target.jpg&amp;diff=76676</id>
		<title>Файл:5 target.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_target.jpg&amp;diff=76676"/>
				<updated>2021-01-07T19:58:52Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_naive.jpg&amp;diff=76675</id>
		<title>Файл:5 naive.jpg</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_naive.jpg&amp;diff=76675"/>
				<updated>2021-01-07T19:58:43Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_final_res2.png&amp;diff=76674</id>
		<title>Файл:5 final res2.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_final_res2.png&amp;diff=76674"/>
				<updated>2021-01-07T19:58:33Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76668</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76668"/>
				<updated>2021-01-07T19:47:27Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Подбор гиперпараметров */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
*картинка (можно вставить картинку с дайвером, если сможем её обработать гармонизатором)*&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
*картинка с дайвером (там видно, что пузырики с фонового изображения остались поверх дайвера)*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
todo Note: Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки. Метод Пуассона заключается в сглаживании этого перепада с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
todo Note: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $A$ изображение, которое служит фоном, а за $B$ {{---}} изображение, вставляемое поверх $A$.&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты пикселя двухмерного изображения (т.е. $(x, y)$). $A_p$ {{---}} значения пикселя фонового изображение, $B_p$ {{---}} значение пикселя вставляемого изображения. Пусть $\Omega$ {{---}} множество координат $p$, на которых определено вставляемое изображение $B$. $\partial \Omega$ {{---}} координаты границы вставляемой области.&lt;br /&gt;
&lt;br /&gt;
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $&amp;lt;p, q&amp;gt;$ таких, что $q \in N_p$, введем $v_{pq} = B_p - B_q$&lt;br /&gt;
&lt;br /&gt;
Обозначим результат блендинга за $O$. Для того чтобы найти значение пикселей в месте наложения $B$, решаем задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2$, где $O_p = A_p$ для $p \in \partial \Omega$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in \Omega$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.&lt;br /&gt;
&lt;br /&gt;
Для $p \in \Omega$: $\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} A_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Решаем систему уравнений и получаем значения $O_p$ для $p \in \Omega$.&lt;br /&gt;
&lt;br /&gt;
todo: Поскольку система уравнений sparse symmetric positive-defined, можно использовать следующие итеративные алгоритмы: Gauss-Seidel, V-cycle multigrid.&lt;br /&gt;
&lt;br /&gt;
Заметим, что метод Пуассона сдвигает цвета накладываемого изображения и сохраняет свойства градиента (прям всегда? нужно подумоть), туду&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Poisson blending для самых маленьких&lt;br /&gt;
&lt;br /&gt;
https://erkaman.github.io/posts/poisson_blending.html&lt;br /&gt;
&lt;br /&gt;
Another thing that we wish to remark is that even though poisson blending shifts the color of the source image, it still preserves the features of it. In the original source image, f4 is smaller than f3, f5 is greater than f4, and so on, and this also applies to our recovered image. This information was encoded by the gradients of the source image. However, it is also important to realize that poisson blending does not exactly preserve the gradients. In the recovered image, the gradient f3,4 assumes the value 7−4=3, but it was 26−22=4 in the original source image. In the previous section, the gradients of the recovered image were identical to the gradients of the original image. But with poisson blending, the gradients of a completely different image are pasted into another image, and the result of this is that the solver is not always able to recover an image whose gradients exactly match the specified gradients. But the solver tries to find an image whose gradients match as close as possible, and in practice, poisson blending yields good results, which we shall show examples of in the following section.&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' Figure 2b, 5c ()&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' Harmonization(&lt;br /&gt;
    I, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    Mask, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    S  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    I' := SinglePassHarmonization(I, Mask, S, IndependentMapping, $\mathcal{L}_1$)&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    O  := SinglePassHarmonization(I', Mask, S, ConsistentMapping, $\mathcal{L}_2$)&lt;br /&gt;
    '''return''' O&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' красивые картинки&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|400px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1.&lt;br /&gt;
Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
kekkekek  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76666</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76666"/>
				<updated>2021-01-07T19:45:33Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Постобработка */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
*картинка (можно вставить картинку с дайвером, если сможем её обработать гармонизатором)*&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
*картинка с дайвером (там видно, что пузырики с фонового изображения остались поверх дайвера)*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
todo Note: Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки. Метод Пуассона заключается в сглаживании этого перепада с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
todo Note: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $A$ изображение, которое служит фоном, а за $B$ {{---}} изображение, вставляемое поверх $A$.&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты пикселя двухмерного изображения (т.е. $(x, y)$). $A_p$ {{---}} значения пикселя фонового изображение, $B_p$ {{---}} значение пикселя вставляемого изображения. Пусть $\Omega$ {{---}} множество координат $p$, на которых определено вставляемое изображение $B$. $\partial \Omega$ {{---}} координаты границы вставляемой области.&lt;br /&gt;
&lt;br /&gt;
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $&amp;lt;p, q&amp;gt;$ таких, что $q \in N_p$, введем $v_{pq} = B_p - B_q$&lt;br /&gt;
&lt;br /&gt;
Обозначим результат блендинга за $O$. Для того чтобы найти значение пикселей в месте наложения $B$, решаем задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2$, где $O_p = A_p$ для $p \in \partial \Omega$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in \Omega$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.&lt;br /&gt;
&lt;br /&gt;
Для $p \in \Omega$: $\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} A_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Решаем систему уравнений и получаем значения $O_p$ для $p \in \Omega$.&lt;br /&gt;
&lt;br /&gt;
todo: Поскольку система уравнений sparse symmetric positive-defined, можно использовать следующие итеративные алгоритмы: Gauss-Seidel, V-cycle multigrid.&lt;br /&gt;
&lt;br /&gt;
Заметим, что метод Пуассона сдвигает цвета накладываемого изображения и сохраняет свойства градиента (прям всегда? нужно подумоть), туду&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Poisson blending для самых маленьких&lt;br /&gt;
&lt;br /&gt;
https://erkaman.github.io/posts/poisson_blending.html&lt;br /&gt;
&lt;br /&gt;
Another thing that we wish to remark is that even though poisson blending shifts the color of the source image, it still preserves the features of it. In the original source image, f4 is smaller than f3, f5 is greater than f4, and so on, and this also applies to our recovered image. This information was encoded by the gradients of the source image. However, it is also important to realize that poisson blending does not exactly preserve the gradients. In the recovered image, the gradient f3,4 assumes the value 7−4=3, but it was 26−22=4 in the original source image. In the previous section, the gradients of the recovered image were identical to the gradients of the original image. But with poisson blending, the gradients of a completely different image are pasted into another image, and the result of this is that the solver is not always able to recover an image whose gradients exactly match the specified gradients. But the solver tries to find an image whose gradients match as close as possible, and in practice, poisson blending yields good results, which we shall show examples of in the following section.&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' Figure 2b, 5c ()&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' Harmonization(&lt;br /&gt;
    I, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    Mask, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    S  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    I' := SinglePassHarmonization(I, Mask, S, IndependentMapping, $\mathcal{L}_1$)&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    O  := SinglePassHarmonization(I', Mask, S, ConsistentMapping, $\mathcal{L}_2$)&lt;br /&gt;
    '''return''' O&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' красивые картинки&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_6abc.png|400px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощью алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|250px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1, Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
kekkekek  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76665</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76665"/>
				<updated>2021-01-07T19:41:25Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: /* Второй проход */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
*картинка (можно вставить картинку с дайвером, если сможем её обработать гармонизатором)*&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
*картинка с дайвером (там видно, что пузырики с фонового изображения остались поверх дайвера)*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
todo Note: Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки. Метод Пуассона заключается в сглаживании этого перепада с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
todo Note: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $A$ изображение, которое служит фоном, а за $B$ {{---}} изображение, вставляемое поверх $A$.&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты пикселя двухмерного изображения (т.е. $(x, y)$). $A_p$ {{---}} значения пикселя фонового изображение, $B_p$ {{---}} значение пикселя вставляемого изображения. Пусть $\Omega$ {{---}} множество координат $p$, на которых определено вставляемое изображение $B$. $\partial \Omega$ {{---}} координаты границы вставляемой области.&lt;br /&gt;
&lt;br /&gt;
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $&amp;lt;p, q&amp;gt;$ таких, что $q \in N_p$, введем $v_{pq} = B_p - B_q$&lt;br /&gt;
&lt;br /&gt;
Обозначим результат блендинга за $O$. Для того чтобы найти значение пикселей в месте наложения $B$, решаем задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2$, где $O_p = A_p$ для $p \in \partial \Omega$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in \Omega$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.&lt;br /&gt;
&lt;br /&gt;
Для $p \in \Omega$: $\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} A_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Решаем систему уравнений и получаем значения $O_p$ для $p \in \Omega$.&lt;br /&gt;
&lt;br /&gt;
todo: Поскольку система уравнений sparse symmetric positive-defined, можно использовать следующие итеративные алгоритмы: Gauss-Seidel, V-cycle multigrid.&lt;br /&gt;
&lt;br /&gt;
Заметим, что метод Пуассона сдвигает цвета накладываемого изображения и сохраняет свойства градиента (прям всегда? нужно подумоть), туду&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Poisson blending для самых маленьких&lt;br /&gt;
&lt;br /&gt;
https://erkaman.github.io/posts/poisson_blending.html&lt;br /&gt;
&lt;br /&gt;
Another thing that we wish to remark is that even though poisson blending shifts the color of the source image, it still preserves the features of it. In the original source image, f4 is smaller than f3, f5 is greater than f4, and so on, and this also applies to our recovered image. This information was encoded by the gradients of the source image. However, it is also important to realize that poisson blending does not exactly preserve the gradients. In the recovered image, the gradient f3,4 assumes the value 7−4=3, but it was 26−22=4 in the original source image. In the previous section, the gradients of the recovered image were identical to the gradients of the original image. But with poisson blending, the gradients of a completely different image are pasted into another image, and the result of this is that the solver is not always able to recover an image whose gradients exactly match the specified gradients. But the solver tries to find an image whose gradients match as close as possible, and in practice, poisson blending yields good results, which we shall show examples of in the following section.&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' Figure 2b, 5c ()&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5c.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' Harmonization(&lt;br /&gt;
    I, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    Mask, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    S  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    I' := SinglePassHarmonization(I, Mask, S, IndependentMapping, $\mathcal{L}_1$)&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    O  := SinglePassHarmonization(I', Mask, S, ConsistentMapping, $\mathcal{L}_2$)&lt;br /&gt;
    '''return''' O&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' красивые картинки&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_5f.png|250px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощбю алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|250px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1, Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
kekkekek  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76654</id>
		<title>Блендинг изображений</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%91%D0%BB%D0%B5%D0%BD%D0%B4%D0%B8%D0%BD%D0%B3_%D0%B8%D0%B7%D0%BE%D0%B1%D1%80%D0%B0%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9&amp;diff=76654"/>
				<updated>2021-01-07T19:12:48Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Добавлены картинки&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Гармонизация изображений''' (англ. ''image harmonization'') {{---}} метод, позволяющий наложить часть одного изображения поверх другого таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и с соответсвующими цветами и текстурами &amp;lt;ref name='ZWS20'&amp;gt;[https://openaccess.thecvf.com/content_WACV_2020/papers/Zhang_Deep_Image_Blending_WACV_2020_paper.pdf Deep Image Blending] Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
*картинка (можно вставить картинку с дайвером, если сможем её обработать гармонизатором)*&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Блендинг изображений''' (англ. ''image blending'') {{---}} метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. В отличие от гармонизации, блендинг сам определяет какие пиксели фонового изображения нужно заменить.&amp;lt;ref name='ZWS20'/&amp;gt;}}&lt;br /&gt;
*картинка с дайвером (там видно, что пузырики с фонового изображения остались поверх дайвера)*&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
todo Note: Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (Poisson blending), хотя оригинальная статья называлась Poisson Image Editing&amp;lt;ref name=&amp;quot;PGB03&amp;quot;&amp;gt;[https://www.cs.jhu.edu/~misha/Fall07/Papers/Perez03.pdf Poisson Image Editing] Patrick Perez, Michel Gangnet, Andrew Blake (2003)&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки. Метод Пуассона заключается в сглаживании этого перепада с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.&lt;br /&gt;
&lt;br /&gt;
todo Note: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.&lt;br /&gt;
&lt;br /&gt;
Давайте обозначим за $A$ изображение, которое служит фоном, а за $B$ {{---}} изображение, вставляемое поверх $A$.&lt;br /&gt;
&lt;br /&gt;
Пусть $p$ {{---}} координаты пикселя двухмерного изображения (т.е. $(x, y)$). $A_p$ {{---}} значения пикселя фонового изображение, $B_p$ {{---}} значение пикселя вставляемого изображения. Пусть $\Omega$ {{---}} множество координат $p$, на которых определено вставляемое изображение $B$. $\partial \Omega$ {{---}} координаты границы вставляемой области.&lt;br /&gt;
&lt;br /&gt;
Пусть $N_p$ {{---}} множество соседей $p$ (максимум четыре пикселя, имеющих общую границу с $p$, т.е. пиксели со следующими координатами: $(x + 1, y), (x - 1, y), (x, y + 1), (x, y - 1)$). Для всех пар $&amp;lt;p, q&amp;gt;$ таких, что $q \in N_p$, введем $v_{pq} = B_p - B_q$&lt;br /&gt;
&lt;br /&gt;
Обозначим результат блендинга за $O$. Для того чтобы найти значение пикселей в месте наложения $B$, решаем задачу минимизации:&lt;br /&gt;
&lt;br /&gt;
$\underset{f_p,\; p \in \Omega}{\mathrm{min}}\; \underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2$, где $O_p = A_p$ для $p \in \partial \Omega$&lt;br /&gt;
&lt;br /&gt;
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных $O_p, p \in \Omega$. Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю.&lt;br /&gt;
&lt;br /&gt;
Для $p \in \Omega$: $\frac{\partial{\underset{p, q \in \Omega}{\sum}\; (O_p - O_q - v_{pq})^2}}{\partial O_p} = \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq}) - \underset{q \in N_p}{\sum} 2 (O_q - O_p - v_{qp}) = 2 \underset{q \in N_p}{\sum} 2 (O_p - O_q - v_{pq})$.&lt;br /&gt;
&lt;br /&gt;
Приравнивая к нулю, получаем: $|N_p| O_p - \underset{q \in N_p}{\sum} O_q = \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Для точек, граничащих с $\partial \Omega$:  $|N_p| O_p - \underset{q \in N_p \cap \Omega}{\sum} O_q = \underset{q \in N_p \cap \partial \Omega}{\sum} A_q + \underset{q \in N_p}{\sum} v_{pq}$.&lt;br /&gt;
&lt;br /&gt;
Решаем систему уравнений и получаем значения $O_p$ для $p \in \Omega$.&lt;br /&gt;
&lt;br /&gt;
todo: Поскольку система уравнений sparse symmetric positive-defined, можно использовать следующие итеративные алгоритмы: Gauss-Seidel, V-cycle multigrid.&lt;br /&gt;
&lt;br /&gt;
Заметим, что метод Пуассона сдвигает цвета накладываемого изображения и сохраняет свойства градиента (прям всегда? нужно подумоть), туду&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Poisson blending для самых маленьких&lt;br /&gt;
&lt;br /&gt;
https://erkaman.github.io/posts/poisson_blending.html&lt;br /&gt;
&lt;br /&gt;
Another thing that we wish to remark is that even though poisson blending shifts the color of the source image, it still preserves the features of it. In the original source image, f4 is smaller than f3, f5 is greater than f4, and so on, and this also applies to our recovered image. This information was encoded by the gradients of the source image. However, it is also important to realize that poisson blending does not exactly preserve the gradients. In the recovered image, the gradient f3,4 assumes the value 7−4=3, but it was 26−22=4 in the original source image. In the previous section, the gradients of the recovered image were identical to the gradients of the original image. But with poisson blending, the gradients of a completely different image are pasted into another image, and the result of this is that the solver is not always able to recover an image whose gradients exactly match the specified gradients. But the solver tries to find an image whose gradients match as close as possible, and in practice, poisson blending yields good results, which we shall show examples of in the following section.&lt;br /&gt;
&lt;br /&gt;
==Трансфер стиля==&lt;br /&gt;
&lt;br /&gt;
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения $S$ на изображение $I$. Для этого используются выходы скрытых слоёв [[Сверточные нейронные сети | свёрточной нейронной сети]] VGG-19&amp;lt;ref name=&amp;quot;SZ14&amp;quot;&amp;gt;[https://arxiv.org/pdf/1409.1556.pdf Very Deep Convolutional Networks for Large-Scale Image Recognition] Karen Simonyan, Andrew Zisserman (2014)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Основная идея генерации изображения {{---}} решение оптимизационной задачи $\mathcal{L}(O, I, S) \xrightarrow[O]{} min$, где $O$ {{---}} итоговое изображение, $\mathcal{L}(O, I, S)$ {{---}} [[Функция потерь и эмпирический риск | функция потерь]]. Такую задачу можно решать градиентным спуском в пространстве изображений используя [[обратное распространение ошибки | метод обратного распространения ошибки]].&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $F^l\left[I\right] \in \mathcal{R}^{N_l \times M_l}$ {{---}} выход $l$-го слоя сети на изображении $I$. Представим его как матрицу $N_l \times M_l$, &lt;br /&gt;
где $N_l$ {{---}} количество фильтров в $l$-ом слое, &lt;br /&gt;
$M_l$ {{---}} количество признаков (высота, умноженная на ширину). Тогда $F^l_{ij}\left[I\right]$ {{---}} $j$-ый признак $i$-го фильтра в $l$-ом слое.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Матрица Грама''' (англ. ''Gram matrix'') {{---}} матрица попарных скалярных произведений. В нашем случае матрица отражает корреляцию между выходами фильтров. $G^l\left[I\right] \in \mathcal{R}^{N_l \times N_l} = F^l\left[I\right]F^l\left[I\right]^T$.}}&lt;br /&gt;
&lt;br /&gt;
===[https://rn-unison.github.io/articulos/style_transfer.pdf Image Style Transfer Using Convolutional Neural Networks]&amp;lt;ref name=&amp;quot;GEB16&amp;quot;&amp;gt;[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)&amp;lt;/ref&amp;gt;.===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\alpha}_{content}(I, O) = \displaystyle\sum_l \frac{\alpha_l}{2 N_l M_l}\displaystyle\sum_{i, j} (F^l_{ij}\left[I\right] - F^l_{ij}\left[O\right])^2$ {{---}} функция потерь содержания, где &lt;br /&gt;
$\alpha_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;&amp;gt;Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\beta}_{style}(I, O) = \displaystyle\sum_l \frac{\beta_l}{2N_l^2} \displaystyle\sum_{i, j} (G^l_{ij}\left[I\right] - G^l_{ij}\left[O\right])^2$ {{---}} функция потерь стиля, где &lt;br /&gt;
$\beta_l$ {{---}} вклад $l$-го слоя в функцию потерь&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;.}}&lt;br /&gt;
&lt;br /&gt;
Итоговой функцией потерь будет $\mathcal{L}_{Gatys} = \mathcal{L}_{content}(I, O) + w_{style}\mathcal{L}_{style}(I, O)$&amp;lt;ref name=&amp;quot;NotOriginalDef&amp;quot;/&amp;gt;. Вес $w_{style}$, векторы $\alpha$ и $\beta$ являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.&lt;br /&gt;
&lt;br /&gt;
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение $I$, изображение $S$ или белый шум {{---}} алгоритм даёт похожие результаты в этих случаях.&lt;br /&gt;
&lt;br /&gt;
[[Файл:GEB16_Figure_6.png|1000px|thumb|center|Начальная инициализация: A) $O_0 = I$, B) $O_0 = S$, C) $O_0 = random$]]&lt;br /&gt;
&lt;br /&gt;
===Histogram Loss===&lt;br /&gt;
&lt;br /&gt;
Авторы другой статьи&amp;lt;ref name=&amp;quot;WRB17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1701.08893.pdf Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses] Eric Risser, Pierre Wilmot, Connelly Barnes (2017)&amp;lt;/ref&amp;gt; показывают, что результаты, полученные с помощью $\mathcal{L}_{Gatys}$ нестабильны и предложили другую функцию потерь, основанную на ''сопоставлении гистограмм''.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сопоставление гистограмм''' (англ. ''Histogram matching'') {{---}} метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой&amp;lt;ref name=&amp;quot;HistMatch&amp;quot;&amp;gt;https://en.wikipedia.org/wiki/Histogram_matching&amp;lt;/ref&amp;gt;.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
Пусть $R = histmatch(S, O)$ {{---}} отображение пикселей такое, что гистограмма $S$ совпадает с гистограммой $R(O)$.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}^{\gamma}_{hist}(O, S) = \displaystyle\sum_l \gamma_l \displaystyle\sum_{i, j} (F^l_{ij}\left[O\right] - R(F^l_{ij}\left[O\right]))^2$ {{---}} функция потерь гистограмм, где&lt;br /&gt;
$\gamma_l$ {{---}} вклад $l$-го слоя в функцию потерь}}&lt;br /&gt;
&lt;br /&gt;
===Total variation loss===&lt;br /&gt;
&lt;br /&gt;
Также добавим ещё одну функцию потерь, которая должна делать картинку более гладкой&amp;lt;ref name=&amp;quot;MV15&amp;quot;&amp;gt;[https://arxiv.org/pdf/1412.0035.pdf Understanding Deep Image Representations by Inverting Them] Aravindh Mahendran, Andrea Vedaldi (2015)&amp;lt;/ref&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;&amp;gt;[https://arxiv.org/pdf/1603.08155.pdf Perceptual Losses for Real-Time Style Transfer and Super-Resolution] Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)&amp;lt;/ref&amp;gt;.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_{tv}(O) = \displaystyle\sum_{i, j} (O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2$ {{---}} общая вариационная потеря (англ. ''Total variation loss'').}}&lt;br /&gt;
&lt;br /&gt;
==Глубокая гармонизация картин&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;&amp;gt;https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)&amp;lt;/ref&amp;gt;==&lt;br /&gt;
&lt;br /&gt;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&amp;lt;ref name=&amp;quot;GEB16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;JAFF16&amp;quot;/&amp;gt;&amp;lt;ref name=&amp;quot;WRB17&amp;quot;/&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_1.png|1000px|thumb|center|Пример работы алгоритма ''Deep Image Analogy''&amp;lt;ref name=&amp;quot;LYY*17&amp;quot;&amp;gt;[https://arxiv.org/pdf/1705.01088.pdf Visual Attribute Transfer through Deep Image Analogy] Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)&amp;lt;/ref&amp;gt; (3 картинка) и ''Deep Painterly Harmonization''&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt; (4 картинка)]]&lt;br /&gt;
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй {{---}} более тщательную. Отличаться они будут '''стилевым маппингом''' и функциями потерь.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Стилевым маппингом''' мы будем называть отображение $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}$.}}&lt;br /&gt;
&lt;br /&gt;
Один проход будет состоять из 3 частей:&lt;br /&gt;
# Входное $I$ и стилевое $S$ изображения подаются на вход нейронной сети VGG-19, так мы получаем $F^l_{ij}\left[I\right]$ и $F^l_{ij}\left[S\right]$.&lt;br /&gt;
# Для каждого слоя $l$ некоторым алгоритмом cтроится стилевой маппинг $P_l$, который сопоставляет столбцам из $F_l[I]$ столбцы из $F_l[S]$.&lt;br /&gt;
# Изображение $O$ восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь.&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' $SinglePassHarmonization$(&lt;br /&gt;
    $I$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $M$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $S$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\pi$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Алгоритм построения стилевого маппинга &amp;lt;/font&amp;gt;&lt;br /&gt;
    $\mathcal{L}$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Функция потерь &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим матрицы $F[I]$ и $F[S]$ с помощью свёрточной сети VGG-19 &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[I] \leftarrow ComputeNeuralActivations(I)$&lt;br /&gt;
    $F[S] \leftarrow ComputeNeuralActivations(S)$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Строим стилевой маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
    $P \leftarrow \pi(F[I], M, F[S])$&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Градиентным спуском ищем изображение $O$, которое минимизирует $\mathcal{L}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    $O \leftarrow Reconstruct(I, M, S, P, \mathcal{L})$&lt;br /&gt;
 &lt;br /&gt;
    '''return''' $O$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Первый проход===&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Вектор активации''' (англ. ''activation vector'') {{---}} это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы $F_l$ являются векторами активации.}}&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Патчем''' (англ. ''patch'') для столбца $j$ будем называть тензор $3 \times 3 \times N_l$, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце $j$}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2b.png|250px|thumb|right|Результаты после первого прохода]]&lt;br /&gt;
&lt;br /&gt;
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм &amp;lt;code&amp;gt;IndependentMapping&amp;lt;/code&amp;gt; для построения стилевого маппинга. Этот алгоритм для каждого столбца $j$ в $F_l[I]$ ищет столбец $p(j)$ в $F_l[S]$, такой что евклидово расстояние между патчем $F_l[I]$ с центром $j$ и патчем $F_l[S]$ с центром $p(j)$ минимально (метод ближайшего соседа).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;  &lt;br /&gt;
  '''fun''' $IndependentMapping$(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    '''for''' $l \in [1 : L]$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // L = количество слоёв сети &amp;lt;/font&amp;gt;&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$: &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt; // рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя $l$ &amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
    '''return''' $P$&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
В первом проходе используется модифицированная функция потерь $\mathcal{L}_{Gatys}$, с тем лишь отличием, что к $F_l[S]$ применяется стилевой маппинг $P_l$.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\mathcal{L}_1(I, S, O, P) = \mathcal{L}^{\alpha}_{content}(I, O) + w_{style}\mathcal{L}^{\beta}_{style}(S, O, P)$, где $w_{style}$ {{---}} вес стилевой функции потерь}}&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' Figure 2b, 5c ()&lt;br /&gt;
&lt;br /&gt;
===Второй проход===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_2c.png|250px|thumb|right|Результаты после второго прохода]]&lt;br /&gt;
&lt;br /&gt;
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм &amp;lt;code&amp;gt;ConsistentMapping&amp;lt;/code&amp;gt; построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое $l_{ref}$ и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в $F_l[S]$ остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' ConsistentMapping(&lt;br /&gt;
    $F[I]$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после входного изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
    $Mask$, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    $F[S]$ &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Выходы слоёв после стилевого изображения &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Сначала посчитаем маппинг как в IndependentMapping только для слоя $l_{ref}$ &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $P_0(j) \leftarrow NearestNeighborIndex(F[I], j, F[S])$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Далее обеспечиваем пространсвенную согласованность &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $j \in [1 : M_{l_{ref}}]$:&lt;br /&gt;
      '''if''' $j \in Resize(Mask, l_{ref})$:&lt;br /&gt;
        $q \leftarrow P_0(j)$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Инициализируем множество кандидатов на новый маппинг &amp;lt;/font&amp;gt;&lt;br /&gt;
        $CSet \leftarrow \{q\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Перебираем все смежные патчи &amp;lt;/font&amp;gt;&lt;br /&gt;
        '''for''' $o \in {N, NE, E, SE, S, SW, W, NW}$: &lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении &amp;lt;/font&amp;gt;&lt;br /&gt;
          $CSet \leftarrow CSet \cup \{P_0(j + o) - o\}$&lt;br /&gt;
        &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей &amp;lt;/font&amp;gt;&lt;br /&gt;
        $P_{l_{ref}}(j) \leftarrow argmin_{c \in CSet}\displaystyle\sum_o \|(F_{l_{ref}}[S]_c - F_{l_{ref}}[S]_{P_0(j + o)}\|^2$&lt;br /&gt;
  &lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Теперь нужно перенести маппинг для $l_{ref}$ на остальные слои &amp;lt;/font&amp;gt;&lt;br /&gt;
    '''for''' $l \in [1 : L] \setminus \{l_{ref}\}$:&lt;br /&gt;
      '''for''' $j \in [1 : M_l]$:&lt;br /&gt;
        '''if''' $j \in Resize(Mask, l)$:&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Вычисляем позицию $j'$ на слое $l_{ref}$ соответствующую позиции $j$ на слое $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $j' \leftarrow ChangeResolution(l, l_{ref}, j)$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Берём маппинг для позиции $j'$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $q \leftarrow P_{l_{ref}}(j')$&lt;br /&gt;
          &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Переносим позицию $q$ обратно на слой $l$&amp;lt;/font&amp;gt;&lt;br /&gt;
          $P_l(j) \leftarrow ChangeResolution(l_{ref}, l, q)$&lt;br /&gt;
    '''return''' P&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь $\mathcal{L}_{s1}$.&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
$\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)$, где $w_{style}$, $w_{hist}$, $w_{tv}$ {{---}} веса соответсвующих функций потерь}}&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
| [[Файл:LPSB18_Figure_5с.png|250px|thumb|none|Только второй проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5d.png|250px|thumb|none|Только первый проход]]&lt;br /&gt;
| [[Файл:LPSB18_Figure_5f.png|250px|thumb|none|Результат с $\mathcal{L}_{style}$ вместо $\mathcal{L}_{s1}$]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
===Итоговый алгоритм===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font size=&amp;quot;3em&amp;quot;&amp;gt;&lt;br /&gt;
  '''fun''' Harmonization(&lt;br /&gt;
    I, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Входное изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
    Mask, &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Маска &amp;lt;/font&amp;gt;&lt;br /&gt;
    S  &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;  // Стилевое изображение &amp;lt;/font&amp;gt;&lt;br /&gt;
  ):&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. &amp;lt;/font&amp;gt;&lt;br /&gt;
    I' := SinglePassHarmonization(I, Mask, S, IndependentMapping, $\mathcal{L}_1$)&lt;br /&gt;
    &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;// Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. &amp;lt;/font&amp;gt;&lt;br /&gt;
    O  := SinglePassHarmonization(I', Mask, S, ConsistentMapping, $\mathcal{L}_2$)&lt;br /&gt;
    '''return''' O&lt;br /&gt;
&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''TODO''' красивые картинки&lt;br /&gt;
&lt;br /&gt;
===Постобработка===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_5f.png|250px|thumb|right|Результат постобработки (без постобработки , после первой стадии, после второй стадии)]]&lt;br /&gt;
&lt;br /&gt;
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье&amp;lt;ref name=&amp;quot;LPSB18&amp;quot;/&amp;gt;):&lt;br /&gt;
# Переведём изображение в [https://en.wikipedia.org/wiki/CIELAB_color_space CIELAB] и применим [https://en.wikipedia.org/wiki/Guided_filter Guided filter] для a и b каналов.&lt;br /&gt;
# С помощбю алгоритма PatchMatch&amp;lt;ref name=&amp;quot;BSFG09&amp;quot;&amp;gt;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)&amp;lt;/ref&amp;gt; и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)&lt;br /&gt;
&lt;br /&gt;
===Подбор гиперпараметров===&lt;br /&gt;
&lt;br /&gt;
[[Файл:LPSB18_Figure_4.png|250px|thumb|none|Влияние $l_{ref}$ на результат]]&lt;br /&gt;
&lt;br /&gt;
Возьмём $l_{ref}$ = conv4_1, Выберем следующие веса для слоёв:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Первый проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
| $1/3$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|+ Второй проход&lt;br /&gt;
|-&lt;br /&gt;
! Параметр &lt;br /&gt;
! conv1_1 &lt;br /&gt;
! conv2_1  &lt;br /&gt;
! conv3_1 &lt;br /&gt;
! conv4_1  &lt;br /&gt;
! conv5_1 &lt;br /&gt;
|-&lt;br /&gt;
! $\alpha$ &lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\beta$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $1/4$&lt;br /&gt;
| $0$&lt;br /&gt;
|-&lt;br /&gt;
! $\gamma$ &lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
| $0$&lt;br /&gt;
| $1/2$&lt;br /&gt;
| $0$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Введём гиперпараметр $\tau$ и возьмём $w_{style} = w_{hist} = \tau$, $w_{tv} = \tau\frac{10}{1 + \exp(10^4 * noise(S) - 25)}$, где $noise(S) = med_{i,j}\left\{(O^l_{i, j} - O^l_{i-1, j}))^2 + (O^l_{i, j} - O^l_{i, j-1}))^2\right\}$&amp;lt;ref&amp;gt;[https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции $noise$&amp;lt;/ref&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Для того чтобы подбирать $\tau$ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными $\tau$. Используя Softmax можно интерполировать необходимый $\tau$ по следующей таблице:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
|-&lt;br /&gt;
! Категория стиля&lt;br /&gt;
! Примеры стилей&lt;br /&gt;
! $\tau$&lt;br /&gt;
|-&lt;br /&gt;
! Слабый&lt;br /&gt;
| Барокко, Высокое Возрождение&lt;br /&gt;
| $1$&lt;br /&gt;
|-&lt;br /&gt;
! Средний&lt;br /&gt;
| Абстрактное Искусство, Постимпрессионизм&lt;br /&gt;
| $5$&lt;br /&gt;
|-&lt;br /&gt;
! Сильный&lt;br /&gt;
| Кубизм, Экспрессионизм&lt;br /&gt;
| $10$&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Глубокий блендинг==&lt;br /&gt;
&lt;br /&gt;
kekkekek  &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Ссылки==&lt;br /&gt;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_2b.png&amp;diff=76649</id>
		<title>Файл:LPSB18 Figure 2b.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_2b.png&amp;diff=76649"/>
				<updated>2021-01-07T18:47:30Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: Wafemand загрузил новую версию Файл:LPSB18 Figure 2b.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_2c.png&amp;diff=76646</id>
		<title>Файл:LPSB18 Figure 2c.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_2c.png&amp;diff=76646"/>
				<updated>2021-01-07T18:45:57Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_6abc.png&amp;diff=76638</id>
		<title>Файл:LPSB18 Figure 6abc.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_6abc.png&amp;diff=76638"/>
				<updated>2021-01-07T18:26:15Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5f.png&amp;diff=76637</id>
		<title>Файл:LPSB18 Figure 5f.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5f.png&amp;diff=76637"/>
				<updated>2021-01-07T18:26:05Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5d.png&amp;diff=76636</id>
		<title>Файл:LPSB18 Figure 5d.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5d.png&amp;diff=76636"/>
				<updated>2021-01-07T18:25:56Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5c.png&amp;diff=76635</id>
		<title>Файл:LPSB18 Figure 5c.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_5c.png&amp;diff=76635"/>
				<updated>2021-01-07T18:25:43Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_4.png&amp;diff=76634</id>
		<title>Файл:LPSB18 Figure 4.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_4.png&amp;diff=76634"/>
				<updated>2021-01-07T18:25:32Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_2b.png&amp;diff=76633</id>
		<title>Файл:LPSB18 Figure 2b.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_2b.png&amp;diff=76633"/>
				<updated>2021-01-07T18:25:20Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_1.png&amp;diff=76632</id>
		<title>Файл:LPSB18 Figure 1.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:LPSB18_Figure_1.png&amp;diff=76632"/>
				<updated>2021-01-07T18:25:09Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:GEB16_Figure_5.png&amp;diff=76631</id>
		<title>Файл:GEB16 Figure 5.png</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:GEB16_Figure_5.png&amp;diff=76631"/>
				<updated>2021-01-07T18:24:52Z</updated>
		
		<summary type="html">&lt;p&gt;Wafemand: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Wafemand</name></author>	</entry>

	</feed>