图像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)
\]
其基本原理就是先获取像素中心的坐标,再对该坐标进行缩放,之后再获取变换后像素左上角位置坐标。