xBRZ 插值详解

ud2_

2020-04-30 21:32:24

Algo. & Theory

xBRZ 是一种针对图像整数倍放大的插值算法,由于在 Animal Crossing: New Horizons 中被使用而变得广为人知。

算法

首先在图像上进行边缘检测,然后沿着边缘插值。

注:下文可以配合代码食用。边缘检测部分对应原实现中的 preProcessCorners 函数;插值部分对应 blendPixel 函数。

边缘检测

对于每个像素 \mathrm E 和周围的像素:

注:因为上面的图形关于 \mathrm x\mathrm y 轴对称,所以接下来只考虑右下角。

如果 \mathrm E\mathrm F\mathrm E\mathrm H 颜色相同,那么 \mathrm{HF} 上一定不存在边缘。否则,分别计算 \mathrm{\color{red}HF}\mathrm{\color{blue}EI} 方向上的色差(把颜色看作 YCbCr 色彩空间中的向量):

\begin{aligned}d_\mathrm{\color{red}HF}&=|\mathrm G-\mathrm E|+|\mathrm E-\mathrm C|+|\mathrm{H5}-\mathrm I|+|\mathrm I-\mathrm{F4}|+4|\mathrm H-\mathrm F|\\d_\mathrm{\color{blue}EI}&=|\mathrm D-\mathrm H|+|\mathrm H-\mathrm{I5}|+|\mathrm B-\mathrm F|+|\mathrm F-\mathrm{I4}|+4|\mathrm E-\mathrm I|\end{aligned}

如果 d_\mathrm{\color{red}HF}<d_\mathrm{\color{blue}EI},那么 \mathrm{HF} 上存在边缘。把 4d_\mathrm{\color{red}HF}<d_\mathrm{\color{blue}EI} 的边缘称为主边缘

插值

因为只是沿着边缘插值,距离边缘较远的像素可以保留原来的颜色,所以先进行最近邻插值。

为了使放大后的图片看起来不模糊 (点名批评双线性插值),xBRZ 采取模式识别的方式。像素的每个角可以是线形圆形,线形又分为对角线缓坡线陡坡线或后两者的叠加。

如果 \mathrm{HF} 上存在边缘,那么右下角一般是线形。但当这个边缘不是主边缘时,就要考虑特殊情况,据此判断右下角是否为圆形:

对于线形角:

\begin{aligned}d_\mathrm{FG}&=|\mathrm F-\mathrm G|\\d_\mathrm{HC}&=|\mathrm H-\mathrm C|\end{aligned}

确定角的形状后,就可以用 \mathrm H\mathrm F 中与 \mathrm E 相差较小的颜色填充。

实例

最近邻 双线性 xBRZ

部分图片来自 xBR algorithm tutorial 和 Super Mario World。