如何以亚像素精度转换图像?

时间:2011-09-14 13:44:02

标签: graphics image-processing rendering subpixel

我的系统需要在屏幕上移动图像。我目前正在使用png并将其放置在所需的屏幕坐标处。

由于屏幕分辨率和所需帧速率的组合,一些帧是相同的,因为图像尚未移动整个像素。不幸的是,屏幕的分辨率是不可协商的。

我对子像素渲染如何平滑边缘有一个大致的了解,但是我无法找到资源(如果存在)我如何使用着色来将图像转换少于一个像素

理想情况下,这可用于任何图像,但如果只能使用简单的形状(如圆形或环形),那么这也是可以接受的。

2 个答案:

答案 0 :(得分:10)

子像素插值相对简单。通常,您应用相当于具有恒定相移的全通滤波器,其中相移对应于所需的子像素图像偏移。根据所需的图像质量,您可以使用例如5点Lanczos或其他窗口sinc函数,然后根据您是想要X换档还是Y换档或两者,将其应用于一个或两个轴。

E.g。对于0.5像素移位,系数可能是[ 0.22954, 0.65507, 0.95725, 0.95725, 0.65507 ]。要生成水平移位,您可以将这些系数与x - 2x + 2的像素进行卷积,例如

const float kCoeffs[5] = { 0.22954f, 0.65507f, 0.95725f, 0.95725f, 0.65507f };

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
    }

答案 1 :(得分:1)

从概念上讲,该操作非常简单。首先,您按比例缩放图像(使用任意一种插值方法),然后转换结果,最后将子采样降低为原始图像尺寸。

比例因子取决于您要执行的亚像素转换的精度。如果要平移0.5度,则需要将原始图像放大2倍,然后将生成的图像平移1个像素。如果要平移0.25度,则需要放大4倍,依此类推。

请注意,此实现方式效率不高,因为放大后最终会计算出您实际上不会使用的像素值,因为当您对原始图像大小进行子采样时,像素值会被丢弃。 Paul的答案的实施效率更高。