Блендинг изображений
Определение: |
Блендинг изображений (англ. image blending) — метод, позволяющий вставить часть одного изображения в другое таким образом, чтобы композиция изображений выглядела естественно, без швов на границах вставки и соответсвующими цветами и текстурами. |
Содержание
[убрать]Блендинг Пуассона
Простая вставка одного изображения поверх другого нередко влечет заметный перепад яркости на границе вставки (рис. 1.1). Метод Пуассона заключается в сглаживании этого перепада (рис. 1.2) с целью сделать дефект менее заметным, используя градиент вставляемого изображения и значения пикселей фонового изображения на границе вставки.
Замечание: Для RGB изображений задача минимизации решается для каждого цветового канала отдельно.
Давайте обозначим за S изображение, которое служит фоном, а за I — изображение, вставляемое поверх S. Область вставки будем задавать двоичной маской M, содержащей единицы в области наложения. Например:
Фоновое изображение S |
Накладываемое изображение I |
Маска M |
---|---|---|
![]() |
![]() |
![]() |
Идея подхода
Пусть замкнутое множество P⊂R2 — область, на которой определено изображение S, а замкнутое множество Ω⊂P с границей ∂Ω и внутренностью int(Ω) — область вставки изображения I.
Пусть fS — скалярная функция, определенная на P∖int(Ω), задает фоновое изображение S; f — неизвестная скалярная функция, определенная на int(Ω), задает, каким образом должно выглядеть результат блендинга в области вставки.
vI — векторное поле, определенное на Ω. В качестве vI возьмем градиент вставляемого изображения I: vI=∇fI
Нашей задачей является поиск такой функции f, чтобы блендинговое изображение выглядело реалистично. Для этого минимизируем разность градиента функции f и векторного поля vI, считая, что f=fS на границе Ω. minf∬Ω|∇f−vI|2,где f|∂Ω=fS|∂Ω
Дискретный случай
Пусть p — координаты (x,y) пикселя двухмерного изображения. За Imgp обозначим значение пикселя с координатами p изображения Img. Пусть Ω={p|Mp=1}. Тогда ∂Ω — координаты границы вставляемой области, а int(Ω) — внутренность области.
Пусть Np — множество соседей p (максимум четыре пикселя, имеющих общую границу с p, т.е. пиксели со следующими координатами: (x+1,y),(x−1,y),(x,y+1),(x,y−1)). Для всех пар (p,q) таких, что q∈Np, введем vpq=Ip−Iq
Введем переменные Op,p∈Ω. Так как мы хотим сделать результат бесшовным, пиксели Op,p∈∂Ω, сделаем равными Sp. Для p,q∈int(Ω),q∈Np постараемся найти такое O, чтобы разность Op и Oq была близка к vpq. Для этого решим задачу минимизации:
minOp,p∈Ω∑p,q∈Ω(Op−Oq−vpq)2,где Op=Sp,p∈∂Ω
Заметим, что функция, которую мы хотим минимизировать, квадратична относительно переменных Op,p∈int(Ω). Для решения задачи минимизации вычислим частные производные по этим переменным и найдем значения переменных, при которых частные производные будут равны нулю. ∂∑p,q∈Ω(Op−Oq−vpq)2∂Op=∑q∈Np2(Op−Oq−vpq)−∑q∈Np2(Oq−Op−vqp)=2∑q∈Np2(Op−Oq−vpq)
Приравнивая к нулю, получаем: |Np|Op−∑q∈NpOq=∑q∈Npvpq.
Добавим условие Op=Sp,p∈∂Ω: |Np|Op−∑q∈Np∩int(Ω)Oq=∑q∈Np∩∂ΩSq+∑q∈Npvpq.
Для решения систем уравнений такого вида могут быть использованы итеративные алгоритмы Gauss-Seidel и V-cycle multigrid[1].
Получаем значения пикселей Op, p∈int(Ω). Тогда результат B блендинга Пуассона будет следующим: Bp={Op,если p∈int(Ω)Sp,иначе
Mетод Пуассона сдвигает цвета накладываемого изображения, сохраняя свойства градиента (т.е. если пиксель Ip1 был меньше Ip2, то после преобразования Ip1 не станет больше Ip2), однако само значение градиета может получиться другим.[2]
Трансфер стиля
Прежде чем переходить к гармонизации картин, рассмотрим задачу трансфера стиля с изображения S на изображение I. Для этого используются выходы скрытых слоёв свёрточной нейронной сети VGG-19[3].
Основная идея генерации изображения — решение оптимизационной задачи L(I,S,O)→Omin, где O — итоговое изображение, L(I,S,O) — функция потерь. Такую задачу можно решать градиентным спуском в пространстве изображений используя метод обратного распространения ошибки.
Определение: |
Пусть Fl[I]∈RNl×Ml — выход l-го слоя сети на изображении I. Представим его как матрицу Nl×Ml, где Nl — количество фильтров в l-ом слое, Ml — количество признаков (высота, умноженная на ширину). Тогда Flij[I] — j-ый признак i-го фильтра в l-ом слое. Fl[I] отражает содержание изображения. |
Определение: |
Матрица Грама (англ. Gram matrix) — матрица попарных скалярных произведений. В нашем случае матрица отражает статистику выходов фильтров независимо от их расположения, что, в свою очередь, отражает стиль изображения.
Gl[I]∈RNl×Nl
Gl[I]=Fl[I]Fl[I]T |
Алгоритм Гатиса[4]
Определение: |
Lαcontent(I,O)=∑lαl2NlMl∑i,j(Flij[I]−Flij[O])2 — функция потерь содержания, где αl — вклад l-го слоя в функцию потерь[5]. |
Определение: |
Lβstyle(I,O)=∑lβl2N2l∑i,j(Glij[I]−Glij[O])2 — функция потерь стиля, где βl — вклад l-го слоя в функцию потерь[5]. |
Итоговой функцией потерь будет LGatys=Lαcontent(I,O)+wstyleLβstyle(I,O)[5]. Вес wstyle, векторы α и β являются, в некотором смысле, гиперпараметрами алгоритма, которые нужно подбирать.
Авторы статьи показывают, что в качестве начальной инициализации можно брать изображение I, изображение S или белый шум — алгоритм даёт похожие результаты в этих случаях.
Histogram Loss
Авторы другой статьи[6] показывают, что результаты, полученные с помощью LGatys нестабильны и предложили другую функцию потерь, основанную на сопоставлении гистограмм.
Определение: |
Сопоставление гистограмм (англ. Histogram matching) — метод обработки изображения, после которого гистограмма изображения совпадает с целевой гистограммой[7]. |
Определение: |
Пусть R=histmatch(S,O) — отображение пикселей такое, что гистограмма S совпадает с гистограммой R(O). |
Определение: |
Lγhist(S,O)=∑lγl∑i,j(Flij[O]−R(Flij[O]))2 — функция потерь гистограмм, где γl — вклад l-го слоя в функцию потерь |
Замечание: Если в случае остальных функций потерь нетрудно посчитать производную, то здесь могут возникнуть проблемы. Но поскольку ∂Lhist∂Flij[O] является нулём почти везде, авторы предлагают при подсчёте производной считать R(Flij[O]) константой, которая не зависит от O.
Total variation loss
Также добавим ещё одну функцию потерь, которая удаляет шумы, при этом сохраняя важные детали изображения[8][9].
Определение: |
Ltv(O)=∑i,j(Oli,j−Oli−1,j)2+(Oli,j−Oli,j−1)2 — общая вариационная потеря (англ. Total variation loss). |
Глубокая гармонизация картин[10]
Для того чтобы вставить изображение в картину или рисунок нужно не только сделать бесшовный переход и изменить цвета, но ещё и изменить текстуру вставляемого изображения, например сымитировать мазки кистью. Используем для этого комбинацию подходов из других статей[4][9][6].
Алгоритм будет состоять из двух проходов. Первый проход будет делать грубую гармонизацию, а второй — более тщательную. Отличаться они будут стилевым маппингом и функциями потерь.
Определение: |
Стилевым маппингом мы будем называть отображение P:RNl×Ml→RNl×Ml, которое некоторым образом переставляет столбцы матрицы (не обязательно обратимо, то есть столбцы могут теряться и копироваться). Более формально, пусть p(j) — новая позиция столбца j, тогда P(Q)i,p(j)=Qij. |
Один проход будет состоять из 3 частей:
- Входное I и стилевое S изображения подаются на вход нейронной сети VGG-19, так мы получаем Flij[I] и Flij[S].
- Для каждого слоя l некоторым алгоритмом π cтроится стилевой маппинг Pl, который сопоставляет столбцам из Fl[I] столбцы из Fl[S].
- Изображение O восстанавливается градиентным спуском по пространству изображений, используя некоторую функцию потерь L.
fun SinglePassHarmonization( I,// Входное изображение M,// Маска S,// Стилевое изображение π,// Алгоритм построения стилевого маппинга L// Функция потерь ): // Строим матрицы F[I] и F[S] с помощью свёрточной сети VGG-19 F[I]←ComputeNeuralActivations(I) F[S]←ComputeNeuralActivations(S) // Строим стилевой маппинг P←π(F[I],M,F[S]) // Градиентным спуском ищем изображение O, которое минимизирует L O←Reconstruct(I,M,S,P,L) return O
Первый проход
Определение: |
Вектор активации (англ. activation vector) — это вектор значений функции активации для каждого фильтра свёрточного слоя. Заметим, что столбцы Fl являются векторами активации. |
Определение: |
Патчем (англ. patch) для столбца j будем называть тензор 3×3×Nl, который состоит из соседних векторов активации в тензоре свёрточного слоя, с центром в столбце j |
Первый проход делает грубую гармонизацию, но при этом он хорошо работает с любыми стилями. Здесь используется алгоритм IndependentMapping
для построения стилевого маппинга. Этот алгоритм для каждого столбца j в Fl[I] ищет столбец p(j) в Fl[S], такой что евклидово расстояние между патчем Fl[I] с центром j и патчем Fl[S] с центром p(j) минимально (метод ближайшего соседа).
fun IndependentMapping( F[I],// Выходы слоёв после входного изображения Mask,// Маска F[S]// Выходы слоёв после стилевого изображения ): // Для всех слоёв от 1 до L for l∈[1:L]: // Для всех столбцов от 1 до Ml for j∈[1:Ml]: // Рассматриваем патчи только внутри маски, которую нужно масштабировать в соответсвии с размером слоя l if j∈Resize(Mask,l): // Берём самый похожий стилевой патч и записываем его в маппинг. Pl(j)←NearestNeighborIndex(F[I],j,F[S]) return P
В первом проходе используется модифицированная функция потерь LGatys, с тем лишь отличием, что к Fl[S] применяется стилевой маппинг Pl.
L1(I,S,O,P)=Lαcontent(I,O)+wstyleLβstyle(S,O,P), где wstyle — вес стилевой функции потерь
Замечание: при посчёте градиента Lαcontent используются только пиксели внутри маски[12].
Второй проход
Второй проход делает более качественную гармонизацию после первого прохода. Здесь мы будем использовать более сложный алгоритм ConsistentMapping построения стилевого маппинга и более сложную функцию потерь. Суть этого алгоритма в том, чтобы найти стилевой мапинг на некотором слое lref и перенести этот маппинг на остальные слои. Также, мы будем предпочитать маппинги, в которых смежные патчи в Fl[S] остаются смежными после мапинга, чтобы обеспечить пространсвенную согласованность (видимо таким образом мы хотим переносить сложные текстуры более качественно, например мазки кистью).
fun ConsistentMapping( F[I],// Выходы слоёв после входного изображения Mask,// Маска F[S]// Выходы слоёв после стилевого изображения ): // Сначала посчитаем маппинг как в IndependentMapping только для слоя lref for j∈[1:Mlref]: if j∈Resize(Mask,lref): P0(j)←NearestNeighborIndex(F[I],j,F[S]) // Далее обеспечиваем пространсвенную согласованность for j∈[1:Mlref]: if j∈Resize(Mask,lref): q←P0(j) // Инициализируем множество кандидатов на новый маппинг CSet←{q} // Перебираем все смежные патчи for o∈N,NE,E,SE,S,SW,W,NW: // Добавляем в кандидаты патч, сосед которого является маппингом для нашего соседа в соответсвующем направлении CSet←CSet∪{P0(j+o)−o} // Среди всех кандидатов выбираем тот, который ближе всего к маппингам наших соседей Plref(j)←argminc∈CSet∑o‖(Flref[S]c−Flref[S]P0(j+o)‖2 // Теперь нужно перенести маппинг для lref на остальные слои for l∈[1:L]∖{lref}: for j∈[1:Ml]: if j∈Resize(Mask,l): // Вычисляем позицию j′ на слое lref соответствующую позиции j на слое l j′←ChangeResolution(l,lref,j) // Берём маппинг для позиции j′ q←Plref(j′) // Переносим позицию q обратно на слой l Pl(j)←ChangeResolution(lref,l,q) return P
При вычислении стилевого маппинга появляется очень много дублирующихся векторов, что даёт не очень хорошие результаты. Поэтому при вычислении матрицы Грама выкинем повторяющиеся векторы. Назовём эту функцию потерь Ls1.
L2(I,S,O,P)=Lαcontent(I,O)+wstyleLβs1(S,O,P)+whistLγhist(S,O)+wtvLtv(O), где wstyle,whist,wtv — веса соответсвующих функций потерь
Итоговый алгоритм
Теперь осталось запустить две стадии
fun Harmonization( I,// Входное изображение Mask,// Маска S// Стилевое изображение ): // Грубый проход алгоритма. Каждый слой рассматривается отдельно при построении стилевого маппинга. I′←SinglePassHarmonization(I,Mask,S,IndependentMapping,L1) // Улучшение результата. Стилевой маппинг строится консистентно для всех слоёв. O←SinglePassHarmonization(I′,Mask,S,ConsistentMapping,L2) return O
Постобработка
Описанный алгоритм даёт хорошие результаты в целом, но при ближайшем рассмотрении могут быть артефакты. Поэтому сделаем двухступенчатую постобработку (подробное описание есть в оригинальной статье[10]):
- Переведём изображение в CIELAB и применим Guided filter для a и b каналов.
- С помощью алгоритма PatchMatch[13] и того же Guided filter делаем так чтобы все патчи выходного изображения присутсвовали в стилевом (чтобы не было новых объектов или структур)
Подбор гиперпараметров
Возьмём lref = conv4_1. Выберем следующие веса для слоёв:
Параметр | conv1_1 | conv2_1 | conv3_1 | conv4_1 | conv5_1 |
---|---|---|---|---|---|
α | 0 | 0 | 0 | 1 | 0 |
β | 0 | 0 | 1/3 | 1/3 | 1/3 |
Параметр | conv1_1 | conv2_1 | conv3_1 | conv4_1 | conv5_1 |
---|---|---|---|---|---|
α | 0 | 0 | 0 | 1 | 0 |
β | 1/4 | 1/4 | 1/4 | 1/4 | 0 |
γ | 1/2 | 0 | 0 | 1/2 | 0 |
Введём гиперпараметр τ и возьмём wstyle=whist=τ, wtv=τ101+exp(104∗noise(S)−25), где noise(S)=medi,j{(Oli,j−Oli−1,j)2+(Oli,j−Oli,j−1)2}[14]
Для того чтобы подбирать τ авторы статьи использовали классификатор стилей изображений. Они взяли VGG-19, обучили её классифицировать 18 различных стилей. Эти стили были разделены на 3 категории с разными τ. Используя Softmax можно интерполировать необходимый τ по следующей таблице:
Категория стиля | Примеры стилей | τ |
---|---|---|
Слабый | Барокко, Высокое Возрождение | 1 |
Средний | Абстрактное Искусство, Постимпрессионизм | 5 |
Сильный | Кубизм, Экспрессионизм | 10 |
Примеры
Исходное изображение | Простая вставка | Результат | Постобработка |
---|---|---|---|
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
Глубокий блендинг
Алгоритм глубокого блендинга состоит из двух этапов. На первом этапе на стилевое изображения S бесшовно накладывается входное изображение I, получается подготовительное блендинг-изображение B. На втором этапе B модифицируется таким образом, чтобы результат по стилю был похож на S.
Будем считать, что на вход подаются изображения, прошедшие предварительную обработку:
- Используемая для вставки часть I вырезана с помощью маски
- M и I выровнены относительно S
- Размеры матриц, задающих M,S,I совпадают
Примеры входных данных:
Стилевое изображение S |
![]() |
![]() |
![]() |
---|---|---|---|
Накладываемое изображение I |
![]() |
![]() |
![]() |
На обоих этапах алгоритм минимизирует взвешенную сумму следующих функций потерь:
- Функция потерь содержания Lcont для сохранения содержания накладываемого изображения I
- Функция потерь стиля Lstyle для переноса стиля изображения S на I
- Гистограмная функция потерь Lhist для стабилизации переноса стиля
- Функция потерь полного отклонения Ltv для удаления шумов
- Градиентная функция потерь Lgrad для бесшовности наложения
Для подсчета Lstyle и Lcontent авторами статьи[15] использовалась сеть VGG-19[3], обученная на ImageNet[16].
Определение: |
Простой вставкой (англ. copy and paste) CAP(M,S,I) будем назвать изображение, полученное наложением части изображения I, заданной маской M, на изображение S. CAP(M,S,I)=I⊙M+S⊙(1−M), где ⊙ — покомпонентное умножение. |
Определение: |
Дискретный оператор Лапласа (фильтр Лапласа) D2 — аналог непрерывного оператора Лапласа ∇2, который позволяет выделять контуры изображения.
D2=[0101−41010] |
- TODO картиночка**
Чтобы комбинировать решение задачи бесшовного наложения методом Пуассона с остальными ограничениями, авторы статьи[15] предлагают использовать функцию потерь Lgrad. Для сохранения контуров изображений S и I в области вставки используется дискретный оператор Лапласа.
Определение: |
Lgrad(S,I,M,O)=12HWH∑m=1W∑n=1[D2B−(D2S+D2I)]2mn — градиентная функция потерь (англ. Possion gradient loss). H,W — высота и ширина изображений. B=CAP(M,S,O) — блендинговое изображение, оптимизируемое относительно O. |
Рассмотрим область ¯Ω={p|Mp=0}. Заметим, что градиент I в ¯Ω равен нулю. Тогда градиенты S и B совпадают, и задача минимизации Lgrad решается только в области вставки.
Первый этап
На первом этапе изображение I накладывается на фоновое изображение S таким образом, чтобы были незаметны швы. Построение начинается с белого шума Z, который оптимизируется в области вставки путем минимизации суммарной функции потерь Ltotal, представленной взвешенной суммой всех функций потерь, описанных выше: Ltotal(Z)=wgradLgrad(I,S,B)+wcontLcont(I,M,Z)+wstyleLstyle(S,B)+wtvLtv(B)+whistLhist(S,B)
Отличительной чертой этого этапа является использование функции потерь Lgrad, приближающей градиент результата к градиенту I в области наложения, за счет чего достигается бесшовность. Для вычисления производных второго порядка используется фильтр Лапласа.
В результате получается подготовительное блендинг-изображение B: Bp={Zp,если Mp=1Sp,иначе
fun SeamlessBlending( I, // Входное изображение M, // Маска S // Стилевое изображение ): // Инициализируем первое приближение белым шумом Z←RandomNoise() B←CAP(M,S,Z) // Определим суммарную функцию потерь с весами слагаемых w Ltotal(Z)←wgradLgrad(I,S,B)+wcontLcont(I,M,Z)+wstyleLstyle(S,B)+wtvLtv(B)+whistLhist(S,B) // С помощью алгоритма L-BFGS ищем изображение Z, которое минимизирует Ltotal Z←Reconstruct(Ltotal,Z) return CAP(M,S,Z)
Второй этап
Второй этап алгоритма представляет собой модификацию полученного на первом этапе блендинг-изображения B таким образом, чтобы стиль изображения был наиболее близок к стилю S.
В отличие от предыдущего этапа, функция потерь не включает в себя Lgrad: Ltotal(O)=wcontLcont(B,O)+wstyleLstyle(S,O)+wtvLtv(O)+whistLhist(S,O)
Минимизация происходит относительно результата алгоритма O, которой инициализируется изображением B.
fun StyleRefinement( B, // Подготовительное блендинг-изображение, результат первого этапа M, // Маска S // Стилевое изображение ): O←B // Определим суммарную функцию потерь с весами слагаемых w Ltotal(O)←wcontLcont(B,O)+wstyleLstyle(S,O)+wtvLtv(O)+whistLhist(S,O) // С помощью алгоритма L-BFGS ищем изображение O, которое минимизирует Ltotal O←Reconstruct(Ltotal,O) return O
Детали реализации
Этап | wgrad | wcont | wstyle | whist | wtv |
---|---|---|---|---|---|
1 | 105 | 1 | 105 | 1 | 10−6 |
2 | 0 | 1 | 107 | 1 | 10−6 |
Для подсчета Lstyle используются слои conv12,conv22,conv33,conv43 VGG, для Lcont — conv22.
На обоих этапах максимальное количество итераций алгоритма L-BFGS — 1000.
Примеры
Ссылки
Примечания
- Перейти ↑ Poisson Image Editing Patrick Perez, Michel Gangnet, Andrew Blake (2003)
- Перейти ↑ https://erkaman.github.io/posts/poisson_blending.html Poisson blending для самых маленьких
- ↑ Перейти к: 3,0 3,1 Very Deep Convolutional Networks for Large-Scale Image Recognition Karen Simonyan, Andrew Zisserman (2014)
- ↑ Перейти к: 4,0 4,1 Image Style Transfer Using Convolutional Neural Networks Leon A. Gatys, Alexander S. Ecker, Matthias Bethge (2016)
- ↑ Перейти к: 5,0 5,1 5,2 Здесь используется определение функции потерь, которое отличается от статьи Гатиса, но используется в таком виде в статье про гармонизацию.
- ↑ Перейти к: 6,0 6,1 Stable and Controllable Neural Texture Synthesis and Style Transfer Using Histogram Losses Eric Risser, Pierre Wilmot, Connelly Barnes (2017)
- Перейти ↑ https://en.wikipedia.org/wiki/Histogram_matching
- Перейти ↑ Understanding Deep Image Representations by Inverting Them Aravindh Mahendran, Andrea Vedaldi (2015)
- ↑ Перейти к: 9,0 9,1 Perceptual Losses for Real-Time Style Transfer and Super-Resolution Justin Johnson, Alexandre Alahi, Li Fei-Fei (2016)
- ↑ Перейти к: 10,0 10,1 10,2 https://arxiv.org/pdf/1804.03189.pdf Fujun Luan, Sylvain Paris, Eli Shechtman, Kavita Bala (2018)
- Перейти ↑ Visual Attribute Transfer through Deep Image Analogy Jing Liao, Yuan Yao, Lu Yuan, Gang Hua, Sing Bing Kang (2017)
- Перейти ↑ https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_gram.lua#L349
- Перейти ↑ 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)
- Перейти ↑ [https://github.com/luanfujun/deep-painterly-harmonization/blob/a33a9a70366b6baff1cc0291f857b5895b271fc1/neural_paint.lua#L470 код функции noise
- ↑ Перейти к: 15,0 15,1 Deep Image Blending Lingzhi Zhang, Tarmily Wen, Jianbo Shi (2020)
- Перейти ↑ 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