ImageWarping变形算法研究---反距离加权插值(IDW)

admin 2018-06-27 阅读


参考论文:Image Warping with Scattered Data Interpolation

Inverse distance weighted interpolation算法(IDW)实际上就是根据给定的控制点对和控制点对的位移矢量(方向和距离),计算控制点对周围像素的反距离加权权重影响,从而实现图像每一个像素点的位移。

 

代码实现如下:


  1.  
    //IDW:Inverse distgance weighted interpolation method
  2.  
    //Reference:Image Warping with Scattered Data Interpolation
  3.  
    int f_IDW(unsigned char* srcData, int width, int height, int stride, int inputPoints[], int outputPoints[], int pointNum)
  4.  
    {
  5.  
    int ret = 0;
  6.  
    unsigned char* pSrc = srcData;
  7.  
    int aa, bb, cc, dd, pos, pos1, xx, yy;
  8.  
    double r1, r2, r3;
  9.  
    unsigned char *pSrcL1;
  10.  
    unsigned char *pSrcL2;
  11.  
    unsigned char* tempData = (unsigned char*)malloc(sizeof(unsigned char)* height * stride);
  12.  
    memcpy(tempData, srcData, sizeof(unsigned char) * height * stride);
  13.  
    unsigned char* p = tempData;
  14.  
    double w = 0, x_in, y_in, sumw, v;
  15.  
    int u = 3;
  16.  
    for(int j = 0; j < height; j++)
  17.  
    {
  18.  
    for(int i = 0; i < width; i++)
  19.  
    {
  20.  
    x_in = 0, y_in = 0;
  21.  
    //F function compute
  22.  
    sumw = 0;
  23.  
    for(int k = 0; k < pointNum; k++)
  24.  
    {
  25.  
    int t = (k << 1);
  26.  
    v = 1.0 / (pow((double)((i - inputPoints[t]) * (i - inputPoints[t]) + (j - inputPoints[t + 1]) * (j - inputPoints[t + 1])),u));
  27.  
    sumw += v;
  28.  
    if(i == inputPoints[t] && j == inputPoints[t + 1])
  29.  
    w = 1.0;
  30.  
    else
  31.  
    w = v;
  32.  
    x_in += w * (outputPoints[t] + i - inputPoints[t]);
  33.  
    y_in += w * (outputPoints[t + 1] + j - inputPoints[t + 1]);
  34.  
    }
  35.  
    w = 1.0 / sumw;
  36.  
    x_in = x_in * w;
  37.  
    y_in = y_in * w;
  38.  
    //interpolation
  39.  
    x_in = CLIP3(x_in, 0, width - 1);
  40.  
    y_in = CLIP3(y_in, 0, height - 1);
  41.  
    xx = (int)x_in;
  42.  
    yy = (int)y_in;
  43.  
    pSrcL1 = p + yy * stride;
  44.  
    pSrcL2 = p + CLIP3((yy + 1), 0, height - 1) * stride;
  45.  
    pos = (xx << 2);
  46.  
    aa = pSrcL1[pos];
  47.  
    bb = pSrcL1[pos + 4];
  48.  
    cc = pSrcL2[pos];
  49.  
    dd = pSrcL2[pos + 4];
  50.  
    r1 = aa + (bb - aa) * (x_in - xx);
  51.  
    r2 = cc + (dd - cc) * (x_in - xx);
  52.  
    r3 = r1 + (r2 - r1) * (y_in - yy);
  53.  
    pSrc[0]=(unsigned char)(CLIP3(r3, 0, 255));//B
  54.  
    aa = pSrcL1[pos + 1];
  55.  
    bb = pSrcL1[pos + 4 +1];
  56.  
    cc = pSrcL2[pos + 1];
  57.  
    dd = pSrcL2[pos + 4 + 1];
  58.  
    r1 = aa + (bb - aa) * (x_in - xx);
  59.  
    r2 = cc + (dd - cc) * (x_in - xx);
  60.  
    r3 = r1 + (r2 - r1) * (y_in - yy);
  61.  
    pSrc[1]=(unsigned char)(CLIP3(r3, 0, 255));//G
  62.  
    aa = pSrcL1[pos + 2];
  63.  
    bb = pSrcL1[pos + 4 + 2];
  64.  
    cc = pSrcL2[pos + 2];
  65.  
    dd = pSrcL2[pos + 4 + 2];
  66.  
    r1 = aa + (bb - aa) * (x_in - xx);
  67.  
    r2 = cc + (dd - cc) * (x_in - xx);
  68.  
    r3 = r1 + (r2 - r1) * (y_in - yy);
  69.  
    pSrc[2]=(unsigned char)(CLIP3(r3, 0, 255));//R
  70.  
    aa = pSrcL1[pos + 3];
  71.  
    bb = pSrcL1[pos + 4 + 3];
  72.  
    cc = pSrcL2[pos + 3];
  73.  
    dd = pSrcL2[pos + 4 + 3];
  74.  
    r1=aa + (bb - aa) * (x_in - xx);
  75.  
    r2=cc + (dd - cc) * (x_in - xx);
  76.  
    r3=r1 + (r2 - r1) * (y_in - yy);
  77.  
    pSrc[3]=(unsigned char)(CLIP3(r3, 0, 255));//A
  78.  
    pSrc += 4;
  79.  
    }
  80.  
    }
  81.  
    free(tempData);
  82.  
    return ret;
  83.  
    };

这里本人以瘦脸效果为例:

这张图中蓝色的点是原始点对,红色点是控制点,这里只对人脸脸庞的两个蓝色点进行了偏移,得到了红色控制点,经过IDW算法处理之后的效果如下所示:

大家可以看到,人脸变瘦了,而其他的地方变化比较小(距离人脸越远,变化越小)。

以上就是IDW算法的全过程,IDW算法不单单可以做瘦脸,还可以做一些五官变形特效,具体不再展示。

关于图片,来自网络,若有侵权敬请告知。

声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。