数字图像缩放算法--双线性插值

来源:互联网 发布:javascript api文档 编辑:程序博客网 时间:2024/05/04 07:33
    最近在Linux下做一个项目,里面需要实现对RGB图像进行缩放的功能,经过几个小时的研究,觉得双线性插值的方法还不错,简单易懂,而且图像不会出现很明显的失真。下面将双线性插值法进行简单的描述,并附上测试过的算法代码。
    双线性插值法:

       将缩放后的图像坐标通过反向变换得到的一个浮点坐标,将浮点坐标在原图像应位置周围的4(2×2)个像素根据某种权值进行加权运算得到的像素值就是缩放后目的像素的像素值。双线性插值缩放后图像质量高,极大地消除了锯齿现象,不会出现像素值不连续的的情况,但由于其具有低通滤波器的性质,使高频分量受损,所以可能会使图像轮廓在一定程度上变得模糊。

      设原图像为f(x,y),缩放后的图像为g(u,v),水平缩放系数为ZoomX,竖直缩放系数为ZoomY,则使用下面的方法计算使用双线性插值法缩放后的像素值。

      

x' = [u/ZoomX], y' = [v/ZoomY];

m = u/ZoomX - x', n = v/ZoomY - y';

      其中[]符号表示对括号包络的部分取整数部分。

      则有

g(u,v)= (1-m)×(1-n)× f(x',y')+ (1-m)×n× f(x',y'+1)

+m×(1-n)× f(x'+1,y') + m×n×f(x'+1,y'+1);


 

 

void ZoomBitMap(unsigned char *pSrcImg, unsigned char *pDstImg, int nWidth, int nHeight, float fRate)

{

    int i = 0;

    int j = 0;


    float fX, fY;

    int iStepSrcImg = nWidth;

    int iStepDstImg = nWidth * fRate;

    int iX, iY;


    unsigned char bUpLeft, bUpRight, bDownLeft, bDownRight;

    unsigned char gUpLeft, gUpRight, gDownLeft, gDownRight;

    unsigned char rUpLeft, rUpRight, rDownLeft, rDownRight;

    unsigned char b, g, r;


    for(i = 0; i < nHeight * fRate; i++)

    {

        for(j = 0; j < nWidth * fRate; j++)

        {

            fX = ((float)j) /fRate;

            fY = ((float)i) /fRate;

            iX = (int)fX;

            iY = (int)fY;

    bUpLeft = pSrcImg[iY * iStepSrcImg * 3 + iX * 3 + 0];

       bUpRight = pSrcImg[iY * iStepSrcImg * 3 + (iX + 1) * 3 + 0];

       bDownLeft = pSrcImg[(iY + 1) * iStepSrcImg * 3 + iX * 3 + 0];

       bDownRight = pSrcImg[(iY + 1) * iStepSrcImg * 3 + (iX + 1) * 3 + 0];


              gUpLeft = pSrcImg[iY * iStepSrcImg * 3 + iX * 3 + 1];

       gUpRight = pSrcImg[iY * iStepSrcImg * 3 + (iX + 1) * 3 + 1];

       gDownLeft = pSrcImg[(iY + 1) * iStepSrcImg * 3 + iX * 3 + 1];

       gDownRight = pSrcImg[(iY + 1) * iStepSrcImg * 3 + (iX + 1) * 3 + 1];

       rUpLeft = pSrcImg[iY * iStepSrcImg * 3 + iX * 3 + 2];

           rUpRight = pSrcImg[iY * iStepSrcImg * 3 + (iX + 1) * 3 + 2];

       rDownLeft = pSrcImg[(iY + 1) * iStepSrcImg * 3 + iX * 3 + 2];

       rDownRight = pSrcImg[(iY + 1) * iStepSrcImg * 3 + (iX + 1) * 3 + 2];


       b = bUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + bUpRight * (fX - iX) * (iY + 1 - fY)

             + bDownLeft * (iX + 1 - fX) * (fY - iY) + bDownRight * (fX - iX) * (fY - iY);

       g = gUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + gUpRight * (fX - iX) * (iY + 1 - fY)

             + gDownLeft * (iX + 1 - fX) * (fY - iY) + gDownRight * (fX - iX) * (fY - iY);

       r = rUpLeft * (iX + 1 - fX) * (iY + 1 - fY) + rUpRight * (fX - iX) * (iY + 1 - fY)

            + rDownLeft * (iX + 1 - fX) * (fY - iY) + rDownRight * (fX - iX) * (fY - iY);

            if(iY >= 0 && iY <= nHeight * 2 && iX >= 0 && iX <= nWidth * 2)

      {

               pDstImg[i * iStepDstImg * 3 + j * 3 + 0] = b;        //B

               pDstImg[i * iStepDstImg * 3 + j * 3 + 1] = g;        //G

               pDstImg[i * iStepDstImg * 3 + j * 3 + 2] = r;        //R

             }

        }

    }

}

原创粉丝点击