Описание быстрого и стабильного Motion blur алгоритма

5ddf7d0745b438bc177f675bff48f130.png

Всем привет, эта статья является краткой выжимкой другой статьи: Guertin, Jean-Philippe & McGuire, M. & Nowrouzezahrai, D. (2014). A fast and stable feature-aware motion blur filter. High-Performance Graphics 2014, HPG 2014 — Proceedings. 51–60.

В ней описан алгоритм Motion blur эффекта, который был предложен авторами оригинальной статьи.

Итак, сам алгоритм:

  1. Изображение разбивается на r*r тайлов для максимального радиуса размытия пространства изображения r, что обеспечивает влияние на каждый пиксель не более чем его (1-ring) окрестности тайла.

Векторы скоростей пикселей. Зеленым показана доминирующая скорость в тайле

Векторы скоростей пикселей. Зеленым показана доминирующая скорость в тайле

  1. У каждого пикселя вычисляется своя скорость:

V[x,y]={v(p_{x,y})\over 2r} * {max(min)|v(p_{x,y})|*E,r),0.5)\over |v(p_{x,y})|+ε} +0.5

где ε = 10^{-5}, а E — время экспозиции в секундах.

  1. Каждому тайлу присваивается одна доминирующая скорость окрестности v_{max}

    Доминирующие векторы скоростей в тайле. Зеленым показан доминирующий вектор скорости среди соседних тайлов

    Доминирующие векторы скоростей в тайле. Зеленым показан доминирующий вектор скорости среди соседних тайлов

  2. Пиксельная (v(p)) и доминантная (v_{max}) скорости пикселя p обрабатываются следующим образом:   размещается ряд сэмплов вдоль центрального направления, интерполируя между нормированными направлениями v(p) и перпендикуляром к доминанте v_{max}^⊥ по мере уменьшения скорости пикселя до минимального порога пользователя :

    v_c(p)=lerp(norm(v(p)),v_{max}^⊥,(||v(p)||-0.5)/γСэмлирование направлений  (зеленый),  (желтый) и  (голубой)
    Сэмлирование направлений v_{max} (зеленый), v_{max}^⊥ (желтый) и v_c(p) (голубой)
  3. На каждом тайле вычисляется угловая разница между максимальными скоростями тайла и ее соседей:

u=1-{1\over|N|}\sum_{t∈N}abs[v_{max}(t)*v_{max}({\overline t})]

где N — множество (1-ring) соседних тайлов вокруг (и включая) тайлаt.

 Дисперсия (зеленый) для тайлов, соседствующих с пикселем  (красный)

 Дисперсия (зеленый) для тайлов, соседствующих с пикселем p (красный)
  1. Задается изначальный вес центра:

w_p=||v_c||^{-1}*N/k

где k — пользовательский параметр для изменения его важности.

  1. Вычисляется цвет центра:

C_{blur}=C[p]*w_p

где C — цвет пикселя.

  1. Для каждого нового сэмпла S выполняются следующие шаги:

    8.1 Задается значение d, которое равно v_c*u*N если номер сэмпла i нечетный или v_{max}*(1-u)*N если нечетный.

    8.2 Стохастически смещается поиск текстуры с максимальной скоростью соседства v_{max} для пикселей, расположенных у края плитки, используя простой линейный спад с управляемым наклоном t.

    Сэмплирование  изменяется с большей вероятностью ближе к границам плитки
    Сэмплирование v_{max} изменяется с большей вероятностью ближе к границам плитки

    8.3 Рассчитываются параметры точки S:

T=t*||v_{max}|| \\S=⎣t*d⎦+p\\colorSample=color[S]

8.4 Рассчитываются классификаторы для переднего и заднего плана:

f=zCompare(Z[p],Z[S])\\b=zCompare(Z[S],Z[p])

где Z — значение глубины пикселя, а zCompare имеет следующий вид:

zCompare[Z_a,Z_b]=min(max(0,1-{(Z_a-Z_b)\over min(Z_a,Z_b)}),1)

8.5 Вычисляется вес данного сэмпла:

weight = f*cone(T,1/||V[S]||)*norm(V[S])*d+ \\b*cone(T,1/||v_c||)*v_c*d+\\cylinder(T,min(||V[S]||,||v_c||)*max(norm(V[S])*d,v_c*d)*2

где функцияconeзадается следующим образом:

cone(a,b)=clamp(1-a/b,0,1)

, а функцияcylinderимеет следующий вид:

cylinder=1-smoothstep(0.95*b,1.05*b,a)

8.6 К изначальному весу центраw_pприбавляется вес сэмплаweight

8.7 Рассчитывается цвет сэмпла учитывающий его вес:

C_s=colorSample * weight

8.8 К цвету центраС_{blur}прибавляется цвет сэмплаC_s

  1. Рассчитывается результат:

result=C_{blur}/w_p

Вот и все, это весь алгоритм. Надеюсь, эта статья поможет разработчикам компьютерной графики или тем, кто только начинает свой путь в этом ремесле. Всем спасибо за внимание!

© Habrahabr.ru