如何翻译具有亚像素精度的图像?



我有一个需要在屏幕上移动图像的系统。我目前正在使用png,只是把它放在所需的屏幕坐标。

由于屏幕分辨率和所需帧速率的组合,有些帧是相同的,因为图像尚未移动一个完整的像素。遗憾的是,屏幕的分辨率没有商量的余地。

我对亚像素渲染如何平滑边缘有一个大致的了解,但我一直无法找到一个资源(如果它存在),关于我如何使用阴影来翻译图像少于一个像素。

理想情况下,这将适用于任何图像,但如果只有一个简单的形状,如圆或环,这也是可以接受的。

亚像素插值比较简单。通常,您应用的是具有恒定相移的全通滤波器,其中相移对应于所需的亚像素图像移位。根据所需的图像质量,您可能会使用例如5点Lanczos或其他窗口函数,然后根据您是否需要X移位或Y移位或两者同时在一个或两个轴上应用此函数。

。对于0.5像素的位移,系数可能是[ 0.06645, 0.18965, 0.27713, 0.27713, 0.18965 ]。(注意系数是归一化的,即它们的和等于1.0。)

要生成水平移位,您将这些系数与从x - 2x + 2的像素进行卷积,例如

const float kCoeffs[5] = { 0.06645f, 0.18965f, 0.27713f, 0.27713f, 0.18965f };
for (y = 0; y < height; ++y)         // for each row
    for (x = 2; x < width - 2; ++x)  // for each col (apart from 2 pixel border)
    {
        float p = 0.0f;              // convolve pixel with Lanczos coeffs
        for (dx = -2; dx <= 2; ++dx)
            p += in[y][x + dx] * kCoeffs[dx + 2];
        out[y][x] = p;               // store interpolated pixel
    }

从概念上讲,操作非常简单。首先按比例放大图像(使用任何插值方法,根据您的喜好),然后翻译结果,最后将子样本缩小到原始图像大小。

比例因子取决于你想要做的亚像素转换的精度。如果你想平移0.5度,你需要将原始图像放大2倍,然后将结果图像平移1个像素;如果你想要平移0.25度,你需要放大4倍,以此类推。

请注意,这个实现是不高效的,因为当你扩大你最终计算像素值,你不会实际使用,因为他们只是丢弃当你的子样本回到原始图像的大小。Paul回答中的实现更高效。

最新更新