<?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=Npostnikova</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=Npostnikova"/>
		<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/Npostnikova"/>
		<updated>2026-08-04T13:37:09Z</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=80279</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=80279"/>
				<updated>2021-01-23T12:21:46Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Эксперимент с вертикальными картинками&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|180px]]&lt;br /&gt;
| [[Файл:Diver bl sea.png|180px]]&lt;br /&gt;
| [[Файл:Diver bl2.png|180px]]&lt;br /&gt;
| [[Файл:Diver bl3.png|180px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Блендинг Пуассона==&lt;br /&gt;
[[Файл:Poisson int1.png|thumb|right|250px|Рисунок $1.1$: Пример перепада яркости при простой вставке&amp;lt;ref name='ZWS20'/&amp;gt;]]&lt;br /&gt;
[[Файл:Poisson int2.png|thumb|right|250px|Рисунок $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|155px]]&lt;br /&gt;
| [[Файл:Poisson_cherry.jpg|155px]]&lt;br /&gt;
| [[Файл:Poisson_cherry_mask.png|155px]]&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;
&amp;lt;div class=&amp;quot;oo-ui-panelLayout-scrollable&amp;quot; style=&amp;quot;display: block; vertical-align:middle; height: auto; max-width: auto; float: center&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_1.png|750px|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$ картинка)]]&amp;lt;/div&amp;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;
{{Определение&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|180px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|180px]]&lt;br /&gt;
| [[Файл:5_final_res.png|180px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|180px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|180px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|180px]]&lt;br /&gt;
| [[Файл:6_final_res.png|180px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|180px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|180px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|180px]]&lt;br /&gt;
| [[Файл:10_final_res.png|180px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|180px]]&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|800px]]&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>Npostnikova</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=80263</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=80263"/>
				<updated>2021-01-23T11:49:37Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Чертовы вылезающие картиночки&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|180px]]&lt;br /&gt;
| [[Файл:Diver bl sea.png|180px]]&lt;br /&gt;
| [[Файл:Diver bl2.png|180px]]&lt;br /&gt;
| [[Файл:Diver bl3.png|180px]]&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;
&amp;lt;div class=&amp;quot;oo-ui-panelLayout-scrollable&amp;quot; style=&amp;quot;display: block; vertical-align:middle; height: auto; max-width: auto; float: center&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_1.png|750px|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$ картинка)]]&amp;lt;/div&amp;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;
{{Определение&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|180px]]&lt;br /&gt;
| [[Файл:5_naive.jpg|180px]]&lt;br /&gt;
| [[Файл:5_final_res.png|180px]]&lt;br /&gt;
| [[Файл:5_final_res2.png|180px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:6_target.jpg|180px]]&lt;br /&gt;
| [[Файл:6_naive.jpg|180px]]&lt;br /&gt;
| [[Файл:6_final_res.png|180px]]&lt;br /&gt;
| [[Файл:6_final_res2.png|180px]]&lt;br /&gt;
|-&lt;br /&gt;
| [[Файл:10_target.jpg|180px]]&lt;br /&gt;
| [[Файл:10_naive.jpg|180px]]&lt;br /&gt;
| [[Файл:10_final_res.png|180px]]&lt;br /&gt;
| [[Файл:10_final_res2.png|180px]]&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|800px]]&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>Npostnikova</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=80262</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=80262"/>
				<updated>2021-01-23T11:34:33Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Глубокая гармонизация картин */&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;
&amp;lt;div class=&amp;quot;oo-ui-panelLayout-scrollable&amp;quot; style=&amp;quot;display: block; vertical-align:middle; height: auto; max-width: auto; float: center&amp;quot;&amp;gt;[[Файл:LPSB18_Figure_1.png|750px|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$ картинка)]]&amp;lt;/div&amp;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;
{{Определение&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>Npostnikova</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=80251</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=80251"/>
				<updated>2021-01-23T11:00:38Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Рис сделать рисунком&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>Npostnikova</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=79870</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=79870"/>
				<updated>2021-01-22T11:38:25Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Картиночки&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 гитхаба авторов].&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>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Diver_bl_diver.png&amp;diff=79869</id>
		<title>Файл:Diver bl diver.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:Diver_bl_diver.png&amp;diff=79869"/>
				<updated>2021-01-22T11:26:25Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Diver_bl_sea.png&amp;diff=79868</id>
		<title>Файл:Diver bl sea.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:Diver_bl_sea.png&amp;diff=79868"/>
				<updated>2021-01-22T11:25:41Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Diver_bl3.png&amp;diff=79866</id>
		<title>Файл:Diver bl3.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:Diver_bl3.png&amp;diff=79866"/>
				<updated>2021-01-22T11:19:10Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Diver_bl2.png&amp;diff=79865</id>
		<title>Файл:Diver bl2.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:Diver_bl2.png&amp;diff=79865"/>
				<updated>2021-01-22T11:18:29Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Diver_bl1.png&amp;diff=79864</id>
		<title>Файл:Diver bl1.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:Diver_bl1.png&amp;diff=79864"/>
				<updated>2021-01-22T11:18:01Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79813</id>
		<title>Модель сущность-связь</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79813"/>
				<updated>2021-01-21T20:11:22Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Object Definition Language */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сущностью''' (англ. ''entity'') называют некоторый объект, обладающий именем и атрибутами.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибутом''' (англ. ''attribute'') называют некоторую характеристику объекта, содержащую имя атрибута и домен и обладающую некоторыми свойствами. }}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Student сущность.png|400px|thumb|right|Пример сущности $Student$]]&lt;br /&gt;
&lt;br /&gt;
Домен не указывает конкретный физический тип, однако позволяет указать, какие атрибуты будут иметь одинаковый тип в физической модели. Так, например, атрибуты $FirstName$ и $LastName$ сущности $Student$ будут обладать одним физическим типом.&lt;br /&gt;
&lt;br /&gt;
'''Типы доменов:'''&lt;br /&gt;
* Простой {{---}} атомарное значение, например, $id$&lt;br /&gt;
* Составной {{---}} состоящий из нескольких значений, например, &amp;lt;code&amp;gt;passport { series: char(4), number: char(6) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&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;
[[Файл:ERM Student Group.png|400px|thumb|right|Пример связи]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Тип&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; |Один&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; | Много&lt;br /&gt;
|[[Файл:Db many.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|Обязательный&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding:3px&amp;quot;| Необязательный&lt;br /&gt;
|[[Файл:Db optional.png|50px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Можно выбрать значение по умолчанию, которое будет обозначаться сплошной линией без символов.&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Связь&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Значение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |По умолчанию&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:Many to many.png|120px]]&lt;br /&gt;
|Многие ко многим&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|Единственность, необязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to many.png|120px]]&lt;br /&gt;
|Один ко многим&lt;br /&gt;
|Единственность, обязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to one.png|120px]]&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;
|definition =&lt;br /&gt;
'''Ассоциацией''' (англ. ''association'') называется многосторонняя связь, нагруженная произвольными не ключевыми атрибутами.}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Association contract.png|400px|thumb|right|Графическое обозначение ассоциации]]&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Ассоциация обозначается прямоугольником с закругленными краями&lt;br /&gt;
* Может содержать не ключевые атрибуты&lt;br /&gt;
* Имеет произвольное количество концов с произвольными ролями и типами&lt;br /&gt;
&lt;br /&gt;
[[Файл:Db erm contract.png|400px|thumb|left|Пример с ассоциацией]]&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;
[[Файл:Association неопределнность нотации.png|thumb|right|350px|Пример неоднозначности интерпретации связей]]&lt;br /&gt;
Многостороннюю ассоциацию можно интерпретировать по-разному. Так, например, на рисунке может быть обозначено следующее:&lt;br /&gt;
* У каждого контракта есть один поручитель&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; (англ. ''Chen-like'', ''Look-across'')&lt;br /&gt;
|[[Файл:Chen-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Зафиксировав остальные сущности, получаем&amp;lt;br/&amp;gt; ограничение на рассматриваемую. &amp;lt;br/&amp;gt; У каждого контракта есть поручитель.&lt;br /&gt;
|-&lt;br /&gt;
|'''Ограничение по Мерис''' &amp;lt;br /&amp;gt; (англ. ''Merise-like'', ''Look-here'')&lt;br /&gt;
|[[Файл:Merise-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Ограничение непосредственно на сущность. &amp;lt;br/&amp;gt; Можно быть поручителем у одного контракта.&lt;br /&gt;
|}&lt;br /&gt;
Также существуют '''обобщенные ограничения''' (англ. ''generic''), позволяющие зафиксировать произвольное подмножество.&lt;br /&gt;
[[Файл:Все ограничения.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=== Выразительная мощность ограничений ===&lt;br /&gt;
* Для ассоциаций с двумя концами:&lt;br /&gt;
** Чен = Мерис = Обобщенные&lt;br /&gt;
* Для ассоциаций с тремя концами:&lt;br /&gt;
** Чен + Мерис = Обобщенные&lt;br /&gt;
* Для ассоциации с четырьмя и более концами:&lt;br /&gt;
** Чен + Мерис &amp;lt; Обобщенные&lt;br /&gt;
&lt;br /&gt;
== Слабые сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Слабой сущностью''' называется сущность, у которой недостаточно атрибутов для идентификации.}}&lt;br /&gt;
Слабая сущность обозначается прямоугольником с двойной границей.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Идентифицирующей связью''' называется связь, позволяющая слабой сущности получить атрибуты, необходимые для ее идентификации.}}&lt;br /&gt;
[[Файл:Weak entity.png|400px|thumb|right|Пример слабой сущности]]&lt;br /&gt;
Идентифицирующая связь обозначается двойной сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Например, название учебной группы уникально в рамках одного университета. Если же мы будем рассматривать несколько университетов, для идентификации группы будет недостаточно лишь ее названия. В таком случае можно считать группу слабой сущностью, для идентификации которой необходим университет.&lt;br /&gt;
&lt;br /&gt;
== Альтернативные нотации ==&lt;br /&gt;
Выше рассматривалась нотация '''Crow's foot''', предложенная Гордоном Эверестом.&lt;br /&gt;
===Нотация Питера Чена===&lt;br /&gt;
Модель Сущность-связь была предложена Питером Ченом в 1976 году, им же была предложена следующая графическая нотация:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Нотация Питера Чена.png|600px]]&lt;br /&gt;
&lt;br /&gt;
===UML-нотация===&lt;br /&gt;
Для каждой таблицы явно подписывается, что она обозначает (ассоциацию, сущность и т.д.). Ограничения прописываются в виде $i..k$ (например, $1..n$), это позволяет наложить ограничение $2..n$, что было невозможно в Crow's foot.&lt;br /&gt;
&lt;br /&gt;
[[Файл:UML-нотация.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Object Definition Language===&lt;br /&gt;
Позволяет задавать схему базы данных кодом.&lt;br /&gt;
&lt;br /&gt;
Рассмотрим пример. У студента есть идентификатор &amp;lt;code&amp;gt;Id&amp;lt;/code&amp;gt;, имя &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt;, а также ссылка на группу &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt;. Явно указываем, что противоположностью этой ссылки является соответствующее поле класса &amp;lt;code&amp;gt;Group&amp;lt;/code&amp;gt;: &amp;lt;code&amp;gt;inverse Group::students&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
У группы есть &amp;lt;code&amp;gt;Id&amp;lt;/code&amp;gt; и смножество студентов &amp;lt;code&amp;gt;students&amp;lt;/code&amp;gt;, учащихся в группе. Указываем, что у студентов ссылка хранится в поле &amp;lt;code&amp;gt;group&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
В данном примере выражена связь один ко многим: студент зачислен в одну группу, в каждой группе есть несколько студентов.&lt;br /&gt;
&lt;br /&gt;
  '''class''' Student {&lt;br /&gt;
    int Id;&lt;br /&gt;
    string Name;&lt;br /&gt;
    Group group inverse Group::students;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  '''class''' Group {&lt;br /&gt;
    int id;&lt;br /&gt;
    Set&amp;lt;Student&amp;gt; students inverse Student::group;&lt;br /&gt;
  }&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79798</id>
		<title>Модель сущность-связь</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79798"/>
				<updated>2021-01-21T19:53:47Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Ассоциации */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сущностью''' (англ. ''entity'') называют некоторый объект, обладающий именем и атрибутами.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибутом''' (англ. ''attribute'') называют некоторую характеристику объекта, содержащую имя атрибута и домен и обладающую некоторыми свойствами. }}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Student сущность.png|400px|thumb|right|Пример сущности $Student$]]&lt;br /&gt;
&lt;br /&gt;
Домен не указывает конкретный физический тип, однако позволяет указать, какие атрибуты будут иметь одинаковый тип в физической модели. Так, например, атрибуты $FirstName$ и $LastName$ сущности $Student$ будут обладать одним физическим типом.&lt;br /&gt;
&lt;br /&gt;
'''Типы доменов:'''&lt;br /&gt;
* Простой {{---}} атомарное значение, например, $id$&lt;br /&gt;
* Составной {{---}} состоящий из нескольких значений, например, &amp;lt;code&amp;gt;passport { series: char(4), number: char(6) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&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;
[[Файл:ERM Student Group.png|400px|thumb|right|Пример связи]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Тип&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; |Один&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; | Много&lt;br /&gt;
|[[Файл:Db many.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|Обязательный&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding:3px&amp;quot;| Необязательный&lt;br /&gt;
|[[Файл:Db optional.png|50px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Можно выбрать значение по умолчанию, которое будет обозначаться сплошной линией без символов.&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Связь&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Значение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |По умолчанию&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:Many to many.png|120px]]&lt;br /&gt;
|Многие ко многим&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|Единственность, необязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to many.png|120px]]&lt;br /&gt;
|Один ко многим&lt;br /&gt;
|Единственность, обязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to one.png|120px]]&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;
|definition =&lt;br /&gt;
'''Ассоциацией''' (англ. ''association'') называется многосторонняя связь, нагруженная произвольными не ключевыми атрибутами.}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Association contract.png|400px|thumb|right|Графическое обозначение ассоциации]]&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Ассоциация обозначается прямоугольником с закругленными краями&lt;br /&gt;
* Может содержать не ключевые атрибуты&lt;br /&gt;
* Имеет произвольное количество концов с произвольными ролями и типами&lt;br /&gt;
&lt;br /&gt;
[[Файл:Db erm contract.png|400px|thumb|left|Пример с ассоциацией]]&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;
[[Файл:Association неопределнность нотации.png|thumb|right|350px|Пример неоднозначности интерпретации связей]]&lt;br /&gt;
Многостороннюю ассоциацию можно интерпретировать по-разному. Так, например, на рисунке может быть обозначено следующее:&lt;br /&gt;
* У каждого контракта есть один поручитель&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; (англ. ''Chen-like'', ''Look-across'')&lt;br /&gt;
|[[Файл:Chen-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Зафиксировав остальные сущности, получаем&amp;lt;br/&amp;gt; ограничение на рассматриваемую. &amp;lt;br/&amp;gt; У каждого контракта есть поручитель.&lt;br /&gt;
|-&lt;br /&gt;
|'''Ограничение по Мерис''' &amp;lt;br /&amp;gt; (англ. ''Merise-like'', ''Look-here'')&lt;br /&gt;
|[[Файл:Merise-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Ограничение непосредственно на сущность. &amp;lt;br/&amp;gt; Можно быть поручителем у одного контракта.&lt;br /&gt;
|}&lt;br /&gt;
Также существуют '''обобщенные ограничения''' (англ. ''generic''), позволяющие зафиксировать произвольное подмножество.&lt;br /&gt;
[[Файл:Все ограничения.png|600px]]&lt;br /&gt;
&lt;br /&gt;
=== Выразительная мощность ограничений ===&lt;br /&gt;
* Для ассоциаций с двумя концами:&lt;br /&gt;
** Чен = Мерис = Обобщенные&lt;br /&gt;
* Для ассоциаций с тремя концами:&lt;br /&gt;
** Чен + Мерис = Обобщенные&lt;br /&gt;
* Для ассоциации с четырьмя и более концами:&lt;br /&gt;
** Чен + Мерис &amp;lt; Обобщенные&lt;br /&gt;
&lt;br /&gt;
== Слабые сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Слабой сущностью''' называется сущность, у которой недостаточно атрибутов для идентификации.}}&lt;br /&gt;
Слабая сущность обозначается прямоугольником с двойной границей.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Идентифицирующей связью''' называется связь, позволяющая слабой сущности получить атрибуты, необходимые для ее идентификации.}}&lt;br /&gt;
[[Файл:Weak entity.png|400px|thumb|right|Пример слабой сущности]]&lt;br /&gt;
Идентифицирующая связь обозначается двойной сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Например, название учебной группы уникально в рамках одного университета. Если же мы будем рассматривать несколько университетов, для идентификации группы будет недостаточно лишь ее названия. В таком случае можно считать группу слабой сущностью, для идентификации которой необходим университет.&lt;br /&gt;
&lt;br /&gt;
== Альтернативные нотации ==&lt;br /&gt;
Выше рассматривалась нотация '''Crow's foot''', предложенная Гордоном Эверестом.&lt;br /&gt;
===Нотация Питера Чена===&lt;br /&gt;
Модель Сущность-связь была предложена Питером Ченом в 1976 году, им же была предложена следующая графическая нотация:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Нотация Питера Чена.png|600px]]&lt;br /&gt;
&lt;br /&gt;
===UML-нотация===&lt;br /&gt;
Для каждой таблицы явно подписывается, что она обозначает (ассоциацию, сущность и т.д.). Ограничения прописываются в виде $i..k$ (например, $1..n$), это позволяет наложить ограничение $2..n$, что было невозможно в Crow's foot.&lt;br /&gt;
&lt;br /&gt;
[[Файл:UML-нотация.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Object Definition Language===&lt;br /&gt;
&lt;br /&gt;
  '''class''' Student {&lt;br /&gt;
    int Id;&lt;br /&gt;
    string Name;&lt;br /&gt;
    Group group inverse Group::Students;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  '''class''' Group {&lt;br /&gt;
    int id;&lt;br /&gt;
    Set&amp;lt;Student&amp;gt; students inverse Student::group;&lt;br /&gt;
  }&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79792</id>
		<title>Физическая модель базы данных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79792"/>
				<updated>2021-01-21T19:30:39Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Графическая нотация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&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;
Рассмотрим основные элементы схемы реляционной БД.&lt;br /&gt;
&lt;br /&gt;
== Таблицы ==&lt;br /&gt;
Каждая таблица состоит из строк и столбцов и предназначена для хранения информации об однотипных объектах. &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Запись''' — набор полей, содержащий информацию о конкретном объекте. Записям соответствуют строки таблицы. }}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Поле''' — значение определенного типа, отражающее конкретную характеристику объекта. Столбец таблицы содержит поля записей, отвечающие за одну характеристику. &lt;br /&gt;
}}&lt;br /&gt;
Пример таблицы, содержащей информацию о студентах:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center; padding:1000px&amp;quot;&lt;br /&gt;
!'''StudentId: int'''&lt;br /&gt;
!'''Name: varchar(60)'''&lt;br /&gt;
!'''Birth: Date'''&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Иван Иванов&lt;br /&gt;
|01.01.1998&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Петр Петров&lt;br /&gt;
|02.02.1999&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ключи ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Ключом''' называется набор полей, уникально идентифицирующий запись.}}&lt;br /&gt;
Выделяют следующие виды ключей:&lt;br /&gt;
* По структуре ключа:&lt;br /&gt;
** '''Простые''' (англ. ''simple'') {{---}} состоящие из одного поля,&lt;br /&gt;
** '''Составные''' (англ. ''composite'') {{---}} состоящие из нескольких полей.&lt;br /&gt;
* По «естественности»:&lt;br /&gt;
** '''Естественные''' (англ. ''natural'') {{---}} приходят из реальных данных, &lt;br /&gt;
** '''Суррогатные''' (англ. ''surrogate'') {{---}} генерируются СУБД или придумываются специально для идентификации записи. Использование суррогатного ключа может быть обусловлено тем, что естественный ключ является длинным, составным или вовсе отсутствует. &lt;br /&gt;
* По «приоритету»:&lt;br /&gt;
** '''Основной''' (англ. ''primary'') {{---}} ключ, используемый для того, чтобы ссылаться на таблицу. Использование различных ключей для ссылок считается плохой практикой.&lt;br /&gt;
** '''Дополнительные''' (англ. ''secondary'') {{---}} ключи, позволяющие поддерживать уникальность поля или набора полей. Их не следует использовать для ссылок на таблицу.&lt;br /&gt;
&lt;br /&gt;
Так, например, идентификатор студента будет простым суррогатным ключом, а серия и номер паспорта {{---}} составным естественным ключом.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Внешним ключом''' (или '''ссылкой''', англ. ''foreign key'') называют набор столбцов, соответствующий (как правило, основному) ключу другой или той же самой таблицы.}}&lt;br /&gt;
[[Файл:БД_ссылка_Students_Groups.png|400px|thumb|right|Пример ссылки на другую таблицу]]&lt;br /&gt;
Типы ссылок:&lt;br /&gt;
* '''Простые''' (англ. ''simple'') {{---}} ссылки, состоящие из одного поля,&lt;br /&gt;
* '''Составные''' (англ. ''composite'') {{---}} ссылки, состоящие из нескольких полей.&lt;br /&gt;
&lt;br /&gt;
== Графическая нотация ==&lt;br /&gt;
[[Файл:ФМ_графическая_нотация.png|400px|thumb|right|Пример графической нотации для таблицы $Students$]]&lt;br /&gt;
[[Файл:FK Student Group.png|400px|thumb|right|Пример внешней ссылки]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство поля&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''FKn'''&lt;br /&gt;
|Внешний ключ $n$ (англ. ''foreign key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Так как любое поле обладает либо свойством обязательности, либо свойством необязательности, будем считать поля необязательными по умолчанию, не указывая это свойство явно.&lt;br /&gt;
* Основной ключ можно выделить, подчеркнув поля, входящие в него, сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Внешний ключ обозначается стрелкой, над которой указывается уникальный идентификатор ключа $FKn$. Этим идентификатором также отмечаются поля, выступающие в роли ссылки. Когда имена полей в таблицах различаются, на ссылке можно указать соответствие между полями.&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
* Дейт К. Введение в системы баз данных (глава 14)&lt;br /&gt;
* Уидом Д., Ульман Д. Основы реляционных баз данных (глава 2)&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79787</id>
		<title>Модель сущность-связь</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79787"/>
				<updated>2021-01-21T19:29:05Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Сущности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сущностью''' (англ. ''entity'') называют некоторый объект, обладающий именем и атрибутами.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибутом''' (англ. ''attribute'') называют некоторую характеристику объекта, содержащую имя атрибута и домен и обладающую некоторыми свойствами. }}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Student сущность.png|400px|thumb|right|Пример сущности $Student$]]&lt;br /&gt;
&lt;br /&gt;
Домен не указывает конкретный физический тип, однако позволяет указать, какие атрибуты будут иметь одинаковый тип в физической модели. Так, например, атрибуты $FirstName$ и $LastName$ сущности $Student$ будут обладать одним физическим типом.&lt;br /&gt;
&lt;br /&gt;
'''Типы доменов:'''&lt;br /&gt;
* Простой {{---}} атомарное значение, например, $id$&lt;br /&gt;
* Составной {{---}} состоящий из нескольких значений, например, &amp;lt;code&amp;gt;passport { series: char(4), number: char(6) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&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;
[[Файл:ERM Student Group.png|400px|thumb|right|Пример связи]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Тип&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; |Один&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; | Много&lt;br /&gt;
|[[Файл:Db many.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|Обязательный&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding:3px&amp;quot;| Необязательный&lt;br /&gt;
|[[Файл:Db optional.png|50px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Можно выбрать значение по умолчанию, которое будет обозначаться сплошной линией без символов.&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Связь&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Значение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |По умолчанию&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:Many to many.png|120px]]&lt;br /&gt;
|Многие ко многим&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|Единственность, необязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to many.png|120px]]&lt;br /&gt;
|Один ко многим&lt;br /&gt;
|Единственность, обязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to one.png|120px]]&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;
|definition =&lt;br /&gt;
'''Ассоциацией''' (англ. ''association'') называется многосторонняя связь, нагруженная произвольными не ключевыми атрибутами.}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Association contract.png|400px|thumb|right|Графическое обозначение ассоциации]]&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Ассоциация обозначается прямоугольником с закругленными краями&lt;br /&gt;
* Может содержать не ключевые атрибуты&lt;br /&gt;
* Имеет произвольное количество концов с произвольными ролями и типами&lt;br /&gt;
&lt;br /&gt;
[[Файл:Db erm contract.png|400px|thumb|left|Пример с ассоциацией]]&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;
[[Файл:Association неопределнность нотации.png|thumb|right|350px|Пример неоднозначности интерпретации связей]]&lt;br /&gt;
Многостороннюю ассоциацию можно интерпретировать по-разному. Так, например, на рисунке может быть обозначено следующее:&lt;br /&gt;
* У каждого контракта есть один поручитель&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; (англ. ''Chen-like'', ''Look-across'')&lt;br /&gt;
|[[Файл:Chen-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Зафиксировав остальные сущности, получаем&amp;lt;br/&amp;gt; ограничение на рассматриваемую. &amp;lt;br/&amp;gt; У каждого контракта есть поручитель.&lt;br /&gt;
|-&lt;br /&gt;
|'''Ограничение по Мерис''' &amp;lt;br /&amp;gt; (англ. ''Merise-like'', ''Look-here'')&lt;br /&gt;
|[[Файл:Merise-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Ограничение непосредственно на сущность. &amp;lt;br/&amp;gt; Можно быть поручителем у одного контракта.&lt;br /&gt;
|}&lt;br /&gt;
Также существуют '''обобщенные ограничения''' (англ. ''generic''), позволяющие зафиксировать произвольное подмножество.&lt;br /&gt;
[[Файл:Все ограничения.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Слабые сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Слабой сущностью''' называется сущность, у которой недостаточно атрибутов для идентификации.}}&lt;br /&gt;
Слабая сущность обозначается прямоугольником с двойной границей.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Идентифицирующей связью''' называется связь, позволяющая слабой сущности получить атрибуты, необходимые для ее идентификации.}}&lt;br /&gt;
[[Файл:Weak entity.png|400px|thumb|right|Пример слабой сущности]]&lt;br /&gt;
Идентифицирующая связь обозначается двойной сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Например, название учебной группы уникально в рамках одного университета. Если же мы будем рассматривать несколько университетов, для идентификации группы будет недостаточно лишь ее названия. В таком случае можно считать группу слабой сущностью, для идентификации которой необходим университет.&lt;br /&gt;
&lt;br /&gt;
== Альтернативные нотации ==&lt;br /&gt;
Выше рассматривалась нотация '''Crow's foot''', предложенная Гордоном Эверестом.&lt;br /&gt;
===Нотация Питера Чена===&lt;br /&gt;
Модель Сущность-связь была предложена Питером Ченом в 1976 году, им же была предложена следующая графическая нотация:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Нотация Питера Чена.png|600px]]&lt;br /&gt;
&lt;br /&gt;
===UML-нотация===&lt;br /&gt;
Для каждой таблицы явно подписывается, что она обозначает (ассоциацию, сущность и т.д.). Ограничения прописываются в виде $i..k$ (например, $1..n$), это позволяет наложить ограничение $2..n$, что было невозможно в Crow's foot.&lt;br /&gt;
&lt;br /&gt;
[[Файл:UML-нотация.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Object Definition Language===&lt;br /&gt;
&lt;br /&gt;
  '''class''' Student {&lt;br /&gt;
    int Id;&lt;br /&gt;
    string Name;&lt;br /&gt;
    Group group inverse Group::Students;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  '''class''' Group {&lt;br /&gt;
    int id;&lt;br /&gt;
    Set&amp;lt;Student&amp;gt; students inverse Student::group;&lt;br /&gt;
  }&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79782</id>
		<title>Физическая модель базы данных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79782"/>
				<updated>2021-01-21T19:23:13Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&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;
Рассмотрим основные элементы схемы реляционной БД.&lt;br /&gt;
&lt;br /&gt;
== Таблицы ==&lt;br /&gt;
Каждая таблица состоит из строк и столбцов и предназначена для хранения информации об однотипных объектах. &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Запись''' — набор полей, содержащий информацию о конкретном объекте. Записям соответствуют строки таблицы. }}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Поле''' — значение определенного типа, отражающее конкретную характеристику объекта. Столбец таблицы содержит поля записей, отвечающие за одну характеристику. &lt;br /&gt;
}}&lt;br /&gt;
Пример таблицы, содержащей информацию о студентах:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center; padding:1000px&amp;quot;&lt;br /&gt;
!'''StudentId: int'''&lt;br /&gt;
!'''Name: varchar(60)'''&lt;br /&gt;
!'''Birth: Date'''&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Иван Иванов&lt;br /&gt;
|01.01.1998&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Петр Петров&lt;br /&gt;
|02.02.1999&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ключи ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Ключом''' называется набор полей, уникально идентифицирующий запись.}}&lt;br /&gt;
Выделяют следующие виды ключей:&lt;br /&gt;
* По структуре ключа:&lt;br /&gt;
** '''Простые''' (англ. ''simple'') {{---}} состоящие из одного поля,&lt;br /&gt;
** '''Составные''' (англ. ''composite'') {{---}} состоящие из нескольких полей.&lt;br /&gt;
* По «естественности»:&lt;br /&gt;
** '''Естественные''' (англ. ''natural'') {{---}} приходят из реальных данных, &lt;br /&gt;
** '''Суррогатные''' (англ. ''surrogate'') {{---}} генерируются СУБД или придумываются специально для идентификации записи. Использование суррогатного ключа может быть обусловлено тем, что естественный ключ является длинным, составным или вовсе отсутствует. &lt;br /&gt;
* По «приоритету»:&lt;br /&gt;
** '''Основной''' (англ. ''primary'') {{---}} ключ, используемый для того, чтобы ссылаться на таблицу. Использование различных ключей для ссылок считается плохой практикой.&lt;br /&gt;
** '''Дополнительные''' (англ. ''secondary'') {{---}} ключи, позволяющие поддерживать уникальность поля или набора полей. Их не следует использовать для ссылок на таблицу.&lt;br /&gt;
&lt;br /&gt;
Так, например, идентификатор студента будет простым суррогатным ключом, а серия и номер паспорта {{---}} составным естественным ключом.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Внешним ключом''' (или '''ссылкой''', англ. ''foreign key'') называют набор столбцов, соответствующий (как правило, основному) ключу другой или той же самой таблицы.}}&lt;br /&gt;
[[Файл:БД_ссылка_Students_Groups.png|400px|thumb|right|Пример ссылки на другую таблицу]]&lt;br /&gt;
Типы ссылок:&lt;br /&gt;
* '''Простые''' (англ. ''simple'') {{---}} ссылки, состоящие из одного поля,&lt;br /&gt;
* '''Составные''' (англ. ''composite'') {{---}} ссылки, состоящие из нескольких полей.&lt;br /&gt;
&lt;br /&gt;
== Графическая нотация ==&lt;br /&gt;
[[Файл:ФМ_графическая_нотация.png|400px|thumb|right|Пример графической нотации для таблицы $Students$]]&lt;br /&gt;
[[Файл:FK Student Group.png|400px|thumb|right|Пример внешней ссылки]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство поля&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''FKn'''&lt;br /&gt;
|Внешний ключ $n$ (англ. ''foreign key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Так как любое поле обладает либо свойством обязательности, либо свойством необязательности, будем считать поля необязательными по умолчанию, не указывая это свойство явно.&lt;br /&gt;
* Основной ключ можно выделить, подчеркнув атрибуты, входящие в него, сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Внешний ключ обозначается стрелкой, над которой указывается уникальный идентификатор ключа $FKn$. Этим идентификатором также отмечаются поля, выступающие в роли ссылки. Когда имена полей в таблицах различаются, на ссылке можно указать соответствие между полями.&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
* Дейт К. Введение в системы баз данных (глава 14)&lt;br /&gt;
* Уидом Д., Ульман Д. Основы реляционных баз данных (глава 2)&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79780</id>
		<title>Физическая модель базы данных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79780"/>
				<updated>2021-01-21T19:20:06Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Таблицы */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&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;
== Таблицы ==&lt;br /&gt;
Каждая таблица состоит из строк и столбцов и предназначена для хранения информации об однотипных объектах. &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Запись''' — набор полей, содержащий информацию о конкретном объекте. Записям соответствуют строки таблицы. }}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Поле''' — значение определенного типа, отражающее конкретную характеристику объекта. Столбец таблицы содержит поля записей, отвечающие за одну характеристику. &lt;br /&gt;
}}&lt;br /&gt;
Пример таблицы, содержащей информацию о студентах:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center; padding:1000px&amp;quot;&lt;br /&gt;
!'''StudentId: int'''&lt;br /&gt;
!'''Name: varchar(60)'''&lt;br /&gt;
!'''Birth: Date'''&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Иван Иванов&lt;br /&gt;
|01.01.1998&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Петр Петров&lt;br /&gt;
|02.02.1999&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ключи ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Ключом''' называется набор полей, уникально идентифицирующий запись.}}&lt;br /&gt;
Выделяют следующие виды ключей:&lt;br /&gt;
* По структуре ключа:&lt;br /&gt;
** '''Простые''' (англ. ''simple'') {{---}} состоящие из одного поля,&lt;br /&gt;
** '''Составные''' (англ. ''composite'') {{---}} состоящие из нескольких полей.&lt;br /&gt;
* По «естественности»:&lt;br /&gt;
** '''Естественные''' (англ. ''natural'') {{---}} приходят из реальных данных, &lt;br /&gt;
** '''Суррогатные''' (англ. ''surrogate'') {{---}} генерируются СУБД или придумываются специально для идентификации записи. Использование суррогатного ключа может быть обусловлено тем, что естественный ключ является длинным, составным или вовсе отсутствует. &lt;br /&gt;
* По «приоритету»:&lt;br /&gt;
** '''Основной''' (англ. ''primary'') {{---}} ключ, используемый для того, чтобы ссылаться на таблицу. Использование различных ключей для ссылок считается плохой практикой.&lt;br /&gt;
** '''Дополнительные''' (англ. ''secondary'') {{---}} ключи, позволяющие поддерживать уникальность поля или набора полей. Их не следует использовать для ссылок на таблицу.&lt;br /&gt;
&lt;br /&gt;
Так, например, идентификатор студента будет простым суррогатным ключом, а серия и номер паспорта {{---}} составным естественным ключом.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Внешним ключом''' (или '''ссылкой''', англ. ''foreign key'') называют набор столбцов, соответствующий (как правило, основному) ключу другой или той же самой таблицы.}}&lt;br /&gt;
[[Файл:БД_ссылка_Students_Groups.png|400px|thumb|right|Пример ссылки на другую таблицу]]&lt;br /&gt;
Типы ссылок:&lt;br /&gt;
* '''Простые''' (англ. ''simple'') {{---}} ссылки, состоящие из одного поля,&lt;br /&gt;
* '''Составные''' (англ. ''composite'') {{---}} ссылки, состоящие из нескольких полей.&lt;br /&gt;
&lt;br /&gt;
== Графическая нотация ==&lt;br /&gt;
[[Файл:ФМ_графическая_нотация.png|400px|thumb|right|Пример графической нотации для таблицы $Students$]]&lt;br /&gt;
[[Файл:FK Student Group.png|400px|thumb|right|Пример внешней ссылки]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство поля&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''FKn'''&lt;br /&gt;
|Внешний ключ $n$ (англ. ''foreign key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Так как любое поле обладает либо свойством обязательности, либо свойством необязательности, будем считать поля необязательными по умолчанию, не указывая это свойство явно.&lt;br /&gt;
* Основной ключ можно выделить, подчеркнув атрибуты, входящие в него, сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Внешний ключ обозначается стрелкой, над которой указывается уникальный идентификатор ключа $FKn$. Этим идентификатором также отмечаются поля, выступающие в роли ссылки. Когда имена полей в таблицах различаются, на ссылке можно указать соответствие между полями.&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
* Дейт К. Введение в системы баз данных (глава 14)&lt;br /&gt;
* Уидом Д., Ульман Д. Основы реляционных баз данных (глава 2)&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79778</id>
		<title>Физическая модель базы данных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79778"/>
				<updated>2021-01-21T19:07:09Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Графическая нотация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&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;
== Таблицы ==&lt;br /&gt;
Каждая таблица состоит из строк и столбцов и предназначена для хранения информации об однотипных объектах. &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Запись''' (строка таблицы) — набор полей, содержащий информацию о конкретном объекте.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Поле''' (столбец таблицы) — набор значений определенного типа, отвечающий за конкретную характеристику объекта. &lt;br /&gt;
}}&lt;br /&gt;
Пример таблицы, содержащей информацию о студентах:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center; padding:1000px&amp;quot;&lt;br /&gt;
!'''StudentId: int'''&lt;br /&gt;
!'''Name: varchar(60)'''&lt;br /&gt;
!'''Birth: Date'''&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Иван Иванов&lt;br /&gt;
|01.01.1998&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Петр Петров&lt;br /&gt;
|02.02.1999&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ключи ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Ключом''' называется набор полей, уникально идентифицирующий запись.}}&lt;br /&gt;
Выделяют следующие виды ключей:&lt;br /&gt;
* По структуре ключа:&lt;br /&gt;
** '''Простые''' (англ. ''simple'') {{---}} состоящие из одного поля,&lt;br /&gt;
** '''Составные''' (англ. ''composite'') {{---}} состоящие из нескольких полей.&lt;br /&gt;
* По «естественности»:&lt;br /&gt;
** '''Естественные''' (англ. ''natural'') {{---}} приходят из реальных данных, &lt;br /&gt;
** '''Суррогатные''' (англ. ''surrogate'') {{---}} генерируются СУБД или придумываются специально для идентификации записи. Использование суррогатного ключа может быть обусловлено тем, что естественный ключ является длинным, составным или вовсе отсутствует. &lt;br /&gt;
* По «приоритету»:&lt;br /&gt;
** '''Основной''' (англ. ''primary'') {{---}} ключ, используемый для того, чтобы ссылаться на таблицу. Использование различных ключей для ссылок считается плохой практикой.&lt;br /&gt;
** '''Дополнительные''' (англ. ''secondary'') {{---}} ключи, позволяющие поддерживать уникальность поля или набора полей. Их не следует использовать для ссылок на таблицу.&lt;br /&gt;
&lt;br /&gt;
Так, например, идентификатор студента будет простым суррогатным ключом, а серия и номер паспорта {{---}} составным естественным ключом.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Внешним ключом''' (или '''ссылкой''', англ. ''foreign key'') называют набор столбцов, соответствующий (как правило, основному) ключу другой или той же самой таблицы.}}&lt;br /&gt;
[[Файл:БД_ссылка_Students_Groups.png|400px|thumb|right|Пример ссылки на другую таблицу]]&lt;br /&gt;
Типы ссылок:&lt;br /&gt;
* '''Простые''' (англ. ''simple'') {{---}} ссылки, состоящие из одного поля,&lt;br /&gt;
* '''Составные''' (англ. ''composite'') {{---}} ссылки, состоящие из нескольких полей.&lt;br /&gt;
&lt;br /&gt;
== Графическая нотация ==&lt;br /&gt;
[[Файл:ФМ_графическая_нотация.png|400px|thumb|right|Пример графической нотации для таблицы $Students$]]&lt;br /&gt;
[[Файл:FK Student Group.png|400px|thumb|right|Пример внешней ссылки]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство поля&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''FKn'''&lt;br /&gt;
|Внешний ключ $n$ (англ. ''foreign key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Так как любое поле обладает либо свойством обязательности, либо свойством необязательности, будем считать поля необязательными по умолчанию, не указывая это свойство явно.&lt;br /&gt;
* Основной ключ можно выделить, подчеркнув атрибуты, входящие в него, сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Внешний ключ обозначается стрелкой, над которой указывается уникальный идентификатор ключа $FKn$. Этим идентификатором также отмечаются поля, выступающие в роли ссылки. Когда имена полей в таблицах различаются, на ссылке можно указать соответствие между полями.&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
* Дейт К. Введение в системы баз данных (глава 14)&lt;br /&gt;
* Уидом Д., Ульман Д. Основы реляционных баз данных (глава 2)&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79776</id>
		<title>Модель сущность-связь</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79776"/>
				<updated>2021-01-21T18:55:56Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Изменение размера картинок&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сущностью''' (англ. ''entity'') называют некоторый объект, обладающий именем и атрибутами.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибутом''' (англ. ''attribute'') называют некоторую характеристику объекта, содержащую имя атрибута и домен и обладающую некоторыми свойствами. }}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Student сущность.png|400px|thumb|right|Пример сущности $Student$]]&lt;br /&gt;
&lt;br /&gt;
Домен не указывает конкретный физический тип, однако позволяет указать, какие атрибуты будут иметь одинаковый тип в физической модели. Так, например, атрибуты $FirstName$ и $LastName$ сущности $Student$ будут обладать одним физическим типом.&lt;br /&gt;
&lt;br /&gt;
'''Типы доменов:'''&lt;br /&gt;
* Простой {{---}} атомарное значение, например, $id$&lt;br /&gt;
* Составной {{---}} состоящий из нескольких значений, например, &amp;lt;code&amp;gt;passport { series: char(4), number: char(6) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Связи ==&lt;br /&gt;
&lt;br /&gt;
[[Файл:ERM Student Group.png|400px|thumb|right|Пример связи]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Тип&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; |Один&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 3px&amp;quot; | Много&lt;br /&gt;
|[[Файл:Db many.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|Обязательный&lt;br /&gt;
|[[Файл:Db mandatory.png|50px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding:3px&amp;quot;| Необязательный&lt;br /&gt;
|[[Файл:Db optional.png|50px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Можно выбрать значение по умолчанию, которое будет обозначаться сплошной линией без символов.&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Связь&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Значение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |По умолчанию&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:Many to many.png|120px]]&lt;br /&gt;
|Многие ко многим&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|Единственность, необязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to many.png|120px]]&lt;br /&gt;
|Один ко многим&lt;br /&gt;
|Единственность, обязательность&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 2px&amp;quot;|[[Файл:One to one.png|120px]]&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;
|definition =&lt;br /&gt;
'''Ассоциацией''' (англ. ''association'') называется многосторонняя связь, нагруженная произвольными не ключевыми атрибутами.}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Association contract.png|400px|thumb|right|Графическое обозначение ассоциации]]&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Ассоциация обозначается прямоугольником с закругленными краями&lt;br /&gt;
* Может содержать не ключевые атрибуты&lt;br /&gt;
* Имеет произвольное количество концов с произвольными ролями и типами&lt;br /&gt;
&lt;br /&gt;
[[Файл:Db erm contract.png|400px|thumb|left|Пример с ассоциацией]]&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;
[[Файл:Association неопределнность нотации.png|thumb|right|350px|Пример неоднозначности интерпретации связей]]&lt;br /&gt;
Многостороннюю ассоциацию можно интерпретировать по-разному. Так, например, на рисунке может быть обозначено следующее:&lt;br /&gt;
* У каждого контракта есть один поручитель&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; (англ. ''Chen-like'', ''Look-across'')&lt;br /&gt;
|[[Файл:Chen-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Зафиксировав остальные сущности, получаем&amp;lt;br/&amp;gt; ограничение на рассматриваемую. &amp;lt;br/&amp;gt; У каждого контракта есть поручитель.&lt;br /&gt;
|-&lt;br /&gt;
|'''Ограничение по Мерис''' &amp;lt;br /&amp;gt; (англ. ''Merise-like'', ''Look-here'')&lt;br /&gt;
|[[Файл:Merise-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Ограничение непосредственно на сущность. &amp;lt;br/&amp;gt; Можно быть поручителем у одного контракта.&lt;br /&gt;
|}&lt;br /&gt;
Также существуют '''обобщенные ограничения''' (англ. ''generic''), позволяющие зафиксировать произвольное подмножество.&lt;br /&gt;
[[Файл:Все ограничения.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Слабые сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Слабой сущностью''' называется сущность, у которой недостаточно атрибутов для идентификации.}}&lt;br /&gt;
Слабая сущность обозначается прямоугольником с двойной границей.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Идентифицирующей связью''' называется связь, позволяющая слабой сущности получить атрибуты, необходимые для ее идентификации.}}&lt;br /&gt;
[[Файл:Weak entity.png|400px|thumb|right|Пример слабой сущности]]&lt;br /&gt;
Идентифицирующая связь обозначается двойной сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Например, название учебной группы уникально в рамках одного университета. Если же мы будем рассматривать несколько университетов, для идентификации группы будет недостаточно лишь ее названия. В таком случае можно считать группу слабой сущностью, для идентификации которой необходим университет.&lt;br /&gt;
&lt;br /&gt;
== Альтернативные нотации ==&lt;br /&gt;
Выше рассматривалась нотация '''Crow's foot''', предложенная Гордоном Эверестом.&lt;br /&gt;
===Нотация Питера Чена===&lt;br /&gt;
Модель Сущность-связь была предложена Питером Ченом в 1976 году, им же была предложена следующая графическая нотация:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Нотация Питера Чена.png|600px]]&lt;br /&gt;
&lt;br /&gt;
===UML-нотация===&lt;br /&gt;
Для каждой таблицы явно подписывается, что она обозначает (ассоциацию, сущность и т.д.). Ограничения прописываются в виде $i..k$ (например, $1..n$), это позволяет наложить ограничение $2..n$, что было невозможно в Crow's foot.&lt;br /&gt;
&lt;br /&gt;
[[Файл:UML-нотация.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Object Definition Language===&lt;br /&gt;
&lt;br /&gt;
  '''class''' Student {&lt;br /&gt;
    int Id;&lt;br /&gt;
    string Name;&lt;br /&gt;
    Group group inverse Group::Students;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  '''class''' Group {&lt;br /&gt;
    int id;&lt;br /&gt;
    Set&amp;lt;Student&amp;gt; students inverse Student::group;&lt;br /&gt;
  }&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Db_one.png&amp;diff=79772</id>
		<title>Файл:Db one.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:Db_one.png&amp;diff=79772"/>
				<updated>2021-01-21T18:46:50Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Npostnikova загрузил новую версию Файл:Db one.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ERM конец связи, один&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Db_many.png&amp;diff=79770</id>
		<title>Файл:Db many.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:Db_many.png&amp;diff=79770"/>
				<updated>2021-01-21T18:45:29Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Npostnikova загрузил новую версию Файл:Db many.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ERM конец связи, многие&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Db_optional.png&amp;diff=79769</id>
		<title>Файл:Db optional.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:Db_optional.png&amp;diff=79769"/>
				<updated>2021-01-21T18:45:07Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Npostnikova загрузил новую версию Файл:Db optional.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ERM конец связи, optional&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Db_optional.png&amp;diff=79768</id>
		<title>Файл:Db optional.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:Db_optional.png&amp;diff=79768"/>
				<updated>2021-01-21T18:44:32Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Npostnikova загрузил новую версию Файл:Db optional.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ERM конец связи, optional&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Db_many.png&amp;diff=79767</id>
		<title>Файл:Db many.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:Db_many.png&amp;diff=79767"/>
				<updated>2021-01-21T18:44:13Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Npostnikova загрузил новую версию Файл:Db many.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ERM конец связи, многие&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Db_one.png&amp;diff=79761</id>
		<title>Файл:Db one.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:Db_one.png&amp;diff=79761"/>
				<updated>2021-01-21T18:29:39Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Npostnikova загрузил новую версию Файл:Db one.png&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;ERM конец связи, один&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79753</id>
		<title>Модель сущность-связь</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%9C%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D1%81%D1%83%D1%89%D0%BD%D0%BE%D1%81%D1%82%D1%8C-%D1%81%D0%B2%D1%8F%D0%B7%D1%8C&amp;diff=79753"/>
				<updated>2021-01-21T18:08:37Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Слабые сущности */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Сущностью''' (англ. ''entity'') называют некоторый объект, обладающий именем и атрибутами.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Атрибутом''' (англ. ''attribute'') называют некоторую характеристику объекта, содержащую имя атрибута и домен и обладающую некоторыми свойствами. }}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Student сущность.png|400px|thumb|right|Пример сущности $Student$]]&lt;br /&gt;
&lt;br /&gt;
Домен не указывает конкретный физический тип, однако позволяет указать, какие атрибуты будут иметь одинаковый тип в физической модели. Так, например, атрибуты $FirstName$ и $LastName$ сущности $Student$ будут обладать одним физическим типом.&lt;br /&gt;
&lt;br /&gt;
'''Типы доменов:'''&lt;br /&gt;
* Простой {{---}} атомарное значение, например, $id$&lt;br /&gt;
* Составной {{---}} состоящий из нескольких значений, например, &amp;lt;code&amp;gt;passport { series: char(4), number: char(6) }&amp;lt;/code&amp;gt;&lt;br /&gt;
&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Связи ==&lt;br /&gt;
&lt;br /&gt;
[[Файл:ERM Student Group.png|400px|thumb|right|Пример связи]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Тип&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 10px&amp;quot; |Один&lt;br /&gt;
|[[Файл:Db one.png|100px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding: 10px&amp;quot; | Много&lt;br /&gt;
|[[Файл:Db many.png|100px]]&lt;br /&gt;
|-&lt;br /&gt;
|Обязательный&lt;br /&gt;
|[[Файл:Db mandatory.png|100px]]&lt;br /&gt;
|-&lt;br /&gt;
|style=&amp;quot;padding:20px&amp;quot;| Необязательный&lt;br /&gt;
|[[Файл:Db optional.png|100px]]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Можно выбрать значение по умолчанию, которое будет обозначаться сплошной линией без символов.&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;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Связь&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Значение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |По умолчанию&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:Many to many.png|200px]]&lt;br /&gt;
|Многие ко многим&lt;br /&gt;
|style=&amp;quot;padding: 10px&amp;quot;|Единственность, необязательность&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:One to many.png|200px]]&lt;br /&gt;
|Один ко многим&lt;br /&gt;
|Единственность, обязательность&lt;br /&gt;
|-&lt;br /&gt;
|[[Файл:One to one.png|200px]]&lt;br /&gt;
|Один к одному&lt;br /&gt;
|Единственность, обязательность&lt;br /&gt;
|-&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ассоциации ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Ассоциацией''' (англ. ''association'') называется многосторонняя связь, нагруженная произвольными не ключевыми атрибутами.}}&lt;br /&gt;
&lt;br /&gt;
[[Файл:Association contract.png|400px|thumb|right|Графическое обозначение ассоциации]]&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Ассоциация обозначается прямоугольником с закругленными краями&lt;br /&gt;
* Может содержать не ключевые атрибуты&lt;br /&gt;
* Имеет произвольное количество концов с произвольными ролями и типами&lt;br /&gt;
&lt;br /&gt;
[[Файл:Db erm contract.png|400px|thumb|left|Пример с ассоциацией]]&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;
[[Файл:Association неопределнность нотации.png|thumb|right|350px|Пример неоднозначности интерпретации связей]]&lt;br /&gt;
Многостороннюю ассоциацию можно интерпретировать по-разному. Так, например, на рисунке может быть обозначено следующее:&lt;br /&gt;
* У каждого контракта есть один поручитель&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; (англ. ''Chen-like'', ''Look-across'')&lt;br /&gt;
|[[Файл:Chen-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Зафиксировав остальные сущности, получаем&amp;lt;br/&amp;gt; ограничение на рассматриваемую. &amp;lt;br/&amp;gt; У каждого контракта есть поручитель.&lt;br /&gt;
|-&lt;br /&gt;
|'''Ограничение по Мерис''' &amp;lt;br /&amp;gt; (англ. ''Merise-like'', ''Look-here'')&lt;br /&gt;
|[[Файл:Merise-like.png|350px]]&lt;br /&gt;
|style=&amp;quot;padding: 10px;&amp;quot;|Ограничение непосредственно на сущность. &amp;lt;br/&amp;gt; Можно быть поручителем у одного контракта.&lt;br /&gt;
|}&lt;br /&gt;
Также существуют '''обобщенные ограничения''' (англ. ''generic''), позволяющие зафиксировать произвольное подмножество.&lt;br /&gt;
[[Файл:Все ограничения.png|600px]]&lt;br /&gt;
&lt;br /&gt;
== Слабые сущности ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Слабой сущностью''' называется сущность, у которой недостаточно атрибутов для идентификации.}}&lt;br /&gt;
Слабая сущность обозначается прямоугольником с двойной границей.&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Идентифицирующей связью''' называется связь, позволяющая слабой сущности получить атрибуты, необходимые для ее идентификации.}}&lt;br /&gt;
[[Файл:Weak entity.png|400px|thumb|right|Пример слабой сущности]]&lt;br /&gt;
Идентифицирующая связь обозначается двойной сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Например, название учебной группы уникально в рамках одного университета. Если же мы будем рассматривать несколько университетов, для идентификации группы будет недостаточно лишь ее названия. В таком случае можно считать группу слабой сущностью, для идентификации которой необходим университет.&lt;br /&gt;
&lt;br /&gt;
== Альтернативные нотации ==&lt;br /&gt;
Выше рассматривалась нотация '''Crow's foot''', предложенная Гордоном Эверестом.&lt;br /&gt;
===Нотация Питера Чена===&lt;br /&gt;
Модель Сущность-связь была предложена Питером Ченом в 1976 году, им же была предложена следующая графическая нотация:&lt;br /&gt;
&lt;br /&gt;
[[Файл:Нотация Питера Чена.png|600px]]&lt;br /&gt;
&lt;br /&gt;
===UML-нотация===&lt;br /&gt;
Для каждой таблицы явно подписывается, что она обозначает (ассоциацию, сущность и т.д.). Ограничения прописываются в виде $i..k$ (например, $1..n$), это позволяет наложить ограничение $2..n$, что было невозможно в Crow's foot.&lt;br /&gt;
&lt;br /&gt;
[[Файл:UML-нотация.png|400px]]&lt;br /&gt;
&lt;br /&gt;
===Object Definition Language===&lt;br /&gt;
&lt;br /&gt;
  '''class''' Student {&lt;br /&gt;
    int Id;&lt;br /&gt;
    string Name;&lt;br /&gt;
    Group group inverse Group::Students;&lt;br /&gt;
  }&lt;br /&gt;
  &lt;br /&gt;
  '''class''' Group {&lt;br /&gt;
    int id;&lt;br /&gt;
    Set&amp;lt;Student&amp;gt; students inverse Student::group;&lt;br /&gt;
  }&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79752</id>
		<title>Физическая модель базы данных</title>
		<link rel="alternate" type="text/html" href="http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B8%D0%B7%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%B0%D1%8F_%D0%BC%D0%BE%D0%B4%D0%B5%D0%BB%D1%8C_%D0%B1%D0%B0%D0%B7%D1%8B_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85&amp;diff=79752"/>
				<updated>2021-01-21T18:07:19Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Графическая нотация */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Определение&lt;br /&gt;
|definition =&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;
== Таблицы ==&lt;br /&gt;
Каждая таблица состоит из строк и столбцов и предназначена для хранения информации об однотипных объектах. &lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Запись''' (строка таблицы) — набор полей, содержащий информацию о конкретном объекте.}}&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Поле''' (столбец таблицы) — набор значений определенного типа, отвечающий за конкретную характеристику объекта. &lt;br /&gt;
}}&lt;br /&gt;
Пример таблицы, содержащей информацию о студентах:&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center; padding:1000px&amp;quot;&lt;br /&gt;
!'''StudentId: int'''&lt;br /&gt;
!'''Name: varchar(60)'''&lt;br /&gt;
!'''Birth: Date'''&lt;br /&gt;
|-&lt;br /&gt;
|1&lt;br /&gt;
|Иван Иванов&lt;br /&gt;
|01.01.1998&lt;br /&gt;
|-&lt;br /&gt;
|2&lt;br /&gt;
|Петр Петров&lt;br /&gt;
|02.02.1999&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Ключи ==&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Ключом''' называется набор полей, уникально идентифицирующий запись.}}&lt;br /&gt;
Выделяют следующие виды ключей:&lt;br /&gt;
* По структуре ключа:&lt;br /&gt;
** '''Простые''' (англ. ''simple'') {{---}} состоящие из одного поля,&lt;br /&gt;
** '''Составные''' (англ. ''composite'') {{---}} состоящие из нескольких полей.&lt;br /&gt;
* По «естественности»:&lt;br /&gt;
** '''Естественные''' (англ. ''natural'') {{---}} приходят из реальных данных, &lt;br /&gt;
** '''Суррогатные''' (англ. ''surrogate'') {{---}} генерируются СУБД или придумываются специально для идентификации записи. Использование суррогатного ключа может быть обусловлено тем, что естественный ключ является длинным, составным или вовсе отсутствует. &lt;br /&gt;
* По «приоритету»:&lt;br /&gt;
** '''Основной''' (англ. ''primary'') {{---}} ключ, используемый для того, чтобы ссылаться на таблицу. Использование различных ключей для ссылок считается плохой практикой.&lt;br /&gt;
** '''Дополнительные''' (англ. ''secondary'') {{---}} ключи, позволяющие поддерживать уникальность поля или набора полей. Их не следует использовать для ссылок на таблицу.&lt;br /&gt;
&lt;br /&gt;
Так, например, идентификатор студента будет простым суррогатным ключом, а серия и номер паспорта {{---}} составным естественным ключом.&lt;br /&gt;
&lt;br /&gt;
== Ссылки ==&lt;br /&gt;
&lt;br /&gt;
{{Определение&lt;br /&gt;
|definition =&lt;br /&gt;
'''Внешним ключом''' (или '''ссылкой''', англ. ''foreign key'') называют набор столбцов, соответствующий (как правило, основному) ключу другой или той же самой таблицы.}}&lt;br /&gt;
[[Файл:БД_ссылка_Students_Groups.png|400px|thumb|right|Пример ссылки на другую таблицу]]&lt;br /&gt;
Типы ссылок:&lt;br /&gt;
* '''Простые''' (англ. ''simple'') {{---}} ссылки, состоящие из одного поля,&lt;br /&gt;
* '''Составные''' (англ. ''composite'') {{---}} ссылки, состоящие из нескольких полей.&lt;br /&gt;
&lt;br /&gt;
== Графическая нотация ==&lt;br /&gt;
[[Файл:ФМ_графическая_нотация.png|400px|thumb|right|Пример графической нотации для таблицы $Students$]]&lt;br /&gt;
[[Файл:FK Student Group.png|400px|thumb|right|Пример внешней ссылки]]&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;
{| class=&amp;quot;wikitable&amp;quot; style=&amp;quot;background-color:#FFF; text-align:center&amp;quot;&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Обозначение&lt;br /&gt;
! style=&amp;quot;background-color:#F0F8FF;&amp;quot; |Свойство поля&lt;br /&gt;
|-&lt;br /&gt;
|'''M'''&lt;br /&gt;
|Обязательное (англ. ''mandatory'')&lt;br /&gt;
|-&lt;br /&gt;
|'''O'''&lt;br /&gt;
|Необязательное (англ. ''optional'')&lt;br /&gt;
|-&lt;br /&gt;
|'''PK'''&lt;br /&gt;
|Основной ключ (англ. ''primary key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''Kn'''&lt;br /&gt;
|Дополнительный ключ $n$ (англ. ''key'')&lt;br /&gt;
|-&lt;br /&gt;
|'''FKn'''&lt;br /&gt;
|Внешний ключ $n$ (англ. ''foreign key'')&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
'''Замечания:'''&lt;br /&gt;
* Так как любое поле обладает либо свойством обязательности, либо свойством необязательности, будем считать поля необязательными по умолчанию, не указывая это свойство явно.&lt;br /&gt;
* Основной ключ можно выделить, подчеркнув атрибуты, входящие в него, сплошной линией.&lt;br /&gt;
&lt;br /&gt;
Внешний ключ обозначается стрелкой, над которой указывается уникальный идентификатор ключа $FKn$. Этим идентификатором также отмечаются поля, выступающие в роли ссылки.&lt;br /&gt;
&lt;br /&gt;
==Литература==&lt;br /&gt;
* Дейт К. Введение в системы баз данных (глава 14)&lt;br /&gt;
* Уидом Д., Ульман Д. Основы реляционных баз данных (глава 2)&lt;/div&gt;</summary>
		<author><name>Npostnikova</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=78946</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=78946"/>
				<updated>2021-01-19T18:23:51Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Предисловие&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$. Пример перепада яркости при простой вставке]]&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\}$ {{---}} область, заданная маской $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;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&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|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$'''&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;
Для решения задачи минимизации авторы статьи&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;
{|&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>Npostnikova</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=78912</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=78912"/>
				<updated>2021-01-19T17:32:43Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Сделала пример поменьше (200px)&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\}$ {{---}} область, заданная маской $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;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&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|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$'''&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;
Для решения задачи минимизации авторы статьи&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;
{|&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>Npostnikova</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=78911</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=78911"/>
				<updated>2021-01-19T17:23:42Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Первый этап */&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\}$ {{---}} область, заданная маской $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;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&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;
Для решения задачи минимизации авторы статьи&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;
{|&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>Npostnikova</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=78907</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=78907"/>
				<updated>2021-01-19T17:22:29Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: L-BFGS ref&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\}$ {{---}} область, заданная маской $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;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&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;
Для решения задачи минимизации авторы статьи&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;
{|&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>Npostnikova</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=78905</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=78905"/>
				<updated>2021-01-19T17:10:49Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Дискретный случай */&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\}$ {{---}} область, заданная маской $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;
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например, сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей&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>Npostnikova</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=78904</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=78904"/>
				<updated>2021-01-19T17:04:14Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Запятую забыла&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>Npostnikova</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=78903</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=78903"/>
				<updated>2021-01-19T17:03:44Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Оформление списка предварительной обработки&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>Npostnikova</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=77571</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=77571"/>
				<updated>2021-01-11T19:06:48Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &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>Npostnikova</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=77568</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=77568"/>
				<updated>2021-01-11T19:00:16Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Глубокий блендинг */&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;
&lt;br /&gt;
[https://en.wikipedia.org/wiki/Gramian_matrix Матрица Грама (англ.)]&lt;br /&gt;
&lt;br /&gt;
==Примечания==&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Lenna.png&amp;diff=77564</id>
		<title>Файл:Lenna.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:Lenna.png&amp;diff=77564"/>
				<updated>2021-01-11T18:54:16Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:Lenna_Laplacian_Neg.png&amp;diff=77563</id>
		<title>Файл:Lenna Laplacian Neg.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:Lenna_Laplacian_Neg.png&amp;diff=77563"/>
				<updated>2021-01-11T18:53:41Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</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=77552</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=77552"/>
				<updated>2021-01-11T18:38:46Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Выравниваем заборчик&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;
|-&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;
На первом этапе изображение $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;
! После обоих этапов&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}$ используются слои $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>Npostnikova</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=77546</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=77546"/>
				<updated>2021-01-11T18:23:39Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Удаляем картиночки&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;
На первом этапе изображение $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;
! После обоих этапов&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}$ используются слои $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>Npostnikova</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=77545</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=77545"/>
				<updated>2021-01-11T18:23:09Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Картиночки&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;
! После обоих этапов&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}$ используются слои $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>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:1_first_pass.png&amp;diff=77543</id>
		<title>Файл:1 first pass.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:1_first_pass.png&amp;diff=77543"/>
				<updated>2021-01-11T18:15:41Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:1_second_pass.png&amp;diff=77542</id>
		<title>Файл:1 second pass.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:1_second_pass.png&amp;diff=77542"/>
				<updated>2021-01-11T18:15:28Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:3_first_pass.png&amp;diff=77541</id>
		<title>Файл:3 first pass.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:3_first_pass.png&amp;diff=77541"/>
				<updated>2021-01-11T18:15:15Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:3_second_pass.png&amp;diff=77540</id>
		<title>Файл:3 second pass.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:3_second_pass.png&amp;diff=77540"/>
				<updated>2021-01-11T18:14:59Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_first_pass.png&amp;diff=77539</id>
		<title>Файл:5 first pass.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_first_pass.png&amp;diff=77539"/>
				<updated>2021-01-11T18:13:47Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</name></author>	</entry>

	<entry>
		<id>http://neerc.ifmo.ru/wiki/index.php?title=%D0%A4%D0%B0%D0%B9%D0%BB:5_second_pass.png&amp;diff=77538</id>
		<title>Файл:5 second pass.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_second_pass.png&amp;diff=77538"/>
				<updated>2021-01-11T18:13:33Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Npostnikova</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=77522</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=77522"/>
				<updated>2021-01-11T17:04:54Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Глубокий блендинг */&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}(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;[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>Npostnikova</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=77515</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=77515"/>
				<updated>2021-01-11T16:20:46Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Дискретный случай */&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}(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;[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;
|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>Npostnikova</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=77514</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=77514"/>
				<updated>2021-01-11T15:55:16Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: /* Блендинг Пуассона */&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_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;[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}(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;[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;
|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>Npostnikova</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=77509</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=77509"/>
				<updated>2021-01-11T15:15:07Z</updated>
		
		<summary type="html">&lt;p&gt;Npostnikova: Определение блендинга&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;
Блендинг Пуассона на самом деле является гармонизацией, так как требует маску заменяемых пикселей. Почему-то в статьях его называют блендингом (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;[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;
|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>Npostnikova</name></author>	</entry>

	</feed>