图像Resize中0.5像素中心对齐的问题

0.5像素对齐的问题

1. 问题提出

在进行图像缩放时,偶尔会看到一些比较奇怪的代码,其中有一个就是0.5像素中心对齐的问题,例如在OpenCV线性插值的代码中有类似如下操作(非源码,只是举例):

// 实际代码
int x=(i+0.5)*m/a-0.5;
int y=(j+0.5)*n/b-0.5;

// 公式计算
int x=i*m/a
int y=j*n/b

2. 原因分析

为什么要先加0.5又减去0.5呢?之前一直认为只是简单的取整操作,后来多次遇到,于是深入分析了一下,才发现原因:
在进行双线性插值的时候,通常情况下图像的原点都选在了左上角,即左上角像素的左上角,但实际访问的时候,\((0,0)\)却代表了第一个像素的值。那么对像素访问的可以按照如下方式来理解。当访问像素\((i,j)\)的时候,实际上获取的是以\((i,j)\)为左上角坐标原点的一个像素的值,即实际取值点与对应坐标点有一定偏差。平常使用的时候没问题,但是当进行图像缩放的时候,便会出现一些差异,例如:

把一个\(5\times 5\)图像缩放到\(3\times3\)大小,那么我们看像素对应关系,只看第一行:
\(I_(x,y)\)

\[I_{3\times3}(0,0) = I_{5\times5} (0,0)\\I_{3\times3}(1,0) = I_{5\times5} (\frac{5}{3},0) \\I_{3\times3}(2,0) = I_{5\times5} (\frac{10}{3},0) \]

由于\(I_{3\times3} ,I_{5\times5}\)的一个像素的大小是相同的,坐标表示的像素左上角的起始位置,那么可以得到如下示意图:

可以看到,按照这种情况,两张图并不是中心对齐的,实际会片左上角。那么如何解决这个问题呢:

\[x'= (x+0.5)*s-0.5\\y' =(y+0.5)*s-0.5 \]

即在计算缩放坐标前先加上\((0.5,0.5)\)取中心点坐标,再乘以变换系数,然后再变换回左上角坐标,即减去\((0.5,0.5)\).

\[I_{3\times3}(0,0) = I_{5\times5} (\frac{1}{3},0)\\I_{3\times3}(1,0) = I_{5\times5} (2,0)\\I_{3\times3}(2,0) = I_{5\times5} (\frac{11}{3},0) \]

其基本原理就是先获取像素中心的坐标,再对该坐标进行缩放,之后再获取变换后像素左上角位置坐标。

3. Ref

posted @ 2019-10-11 15:35  椒盐蘑菇  阅读(2547)  评论(1编辑  收藏  举报