参考论文:Image Warping with Scattered Data Interpolation
Inverse distance weighted interpolation算法(IDW)实际上就是根据给定的控制点对和控制点对的位移矢量(方向和距离),计算控制点对周围像素的反距离加权权重影响,从而实现图像每一个像素点的位移。
代码实现如下:
//IDW:Inverse distgance weighted interpolation method
//Reference:Image Warping with Scattered Data Interpolation
int f_IDW(unsigned char* srcData, int width, int height, int stride, int inputPoints[], int outputPoints[], int pointNum)
{
int ret = 0;
unsigned char* pSrc = srcData;
int aa, bb, cc, dd, pos, pos1, xx, yy;
double r1, r2, r3;
unsigned char *pSrcL1;
unsigned char *pSrcL2;
unsigned char* tempData = (unsigned char*)malloc(sizeof(unsigned char)* height * stride);
memcpy(tempData, srcData, sizeof(unsigned char) * height * stride);
unsigned char* p = tempData;
double w = 0, x_in, y_in, sumw, v;
int u = 3;
for(int j = 0; j < height; j++)
{
for(int i = 0; i < width; i++)
{
x_in = 0, y_in = 0;
//F function compute
sumw = 0;
for(int k = 0; k < pointNum; k++)
{
int t = (k << 1);
v = 1.0 / (pow((double)((i - inputPoints[t]) * (i - inputPoints[t]) + (j - inputPoints[t + 1]) * (j - inputPoints[t + 1])),u));
sumw += v;
if(i == inputPoints[t] && j == inputPoints[t + 1])
w = 1.0;
else
w = v;
x_in += w * (outputPoints[t] + i - inputPoints[t]);
y_in += w * (outputPoints[t + 1] + j - inputPoints[t + 1]);
}
w = 1.0 / sumw;
x_in = x_in * w;
y_in = y_in * w;
//interpolation
x_in = CLIP3(x_in, 0, width - 1);
y_in = CLIP3(y_in, 0, height - 1);
xx = (int)x_in;
yy = (int)y_in;
pSrcL1 = p + yy * stride;
pSrcL2 = p + CLIP3((yy + 1), 0, height - 1) * stride;
pos = (xx << 2);
aa = pSrcL1[pos];
bb = pSrcL1[pos + 4];
cc = pSrcL2[pos];
dd = pSrcL2[pos + 4];
r1 = aa + (bb - aa) * (x_in - xx);
r2 = cc + (dd - cc) * (x_in - xx);
r3 = r1 + (r2 - r1) * (y_in - yy);
pSrc[0]=(unsigned char)(CLIP3(r3, 0, 255));//B
aa = pSrcL1[pos + 1];
bb = pSrcL1[pos + 4 +1];
cc = pSrcL2[pos + 1];
dd = pSrcL2[pos + 4 + 1];
r1 = aa + (bb - aa) * (x_in - xx);
r2 = cc + (dd - cc) * (x_in - xx);
r3 = r1 + (r2 - r1) * (y_in - yy);
pSrc[1]=(unsigned char)(CLIP3(r3, 0, 255));//G
aa = pSrcL1[pos + 2];
bb = pSrcL1[pos + 4 + 2];
cc = pSrcL2[pos + 2];
dd = pSrcL2[pos + 4 + 2];
r1 = aa + (bb - aa) * (x_in - xx);
r2 = cc + (dd - cc) * (x_in - xx);
r3 = r1 + (r2 - r1) * (y_in - yy);
pSrc[2]=(unsigned char)(CLIP3(r3, 0, 255));//R
aa = pSrcL1[pos + 3];
bb = pSrcL1[pos + 4 + 3];
cc = pSrcL2[pos + 3];
dd = pSrcL2[pos + 4 + 3];
r1=aa + (bb - aa) * (x_in - xx);
r2=cc + (dd - cc) * (x_in - xx);
r3=r1 + (r2 - r1) * (y_in - yy);
pSrc[3]=(unsigned char)(CLIP3(r3, 0, 255));//A
pSrc += 4;
}
}
free(tempData);
return ret;
};
这里本人以瘦脸效果为例:
这张图中蓝色的点是原始点对,红色点是控制点,这里只对人脸脸庞的两个蓝色点进行了偏移,得到了红色控制点,经过IDW算法处理之后的效果如下所示:
大家可以看到,人脸变瘦了,而其他的地方变化比较小(距离人脸越远,变化越小)。
以上就是IDW算法的全过程,IDW算法不单单可以做瘦脸,还可以做一些五官变形特效,具体不再展示。
关于图片,来自网络,若有侵权敬请告知。
本人QQ1358009172