【圖像處理】利用雙線性插值算法進行圖像的縮放


本文地址:http://www.cnblogs.com/zzw-in/p/Bilinear_interpolation.html 

首先我們來看一下雙線性插值的定義:

百度百科上的定義:雙線性插值,又稱為雙線性內插。在數學上,雙線性插值是有兩個變量插值函數的線性插值擴展,其核心思想是在兩個方向分別進行一次線性插值

根據定義,雙線性插值就是分別在兩個不同方向進行線性插值,這里的"兩個方向"一般對應着xy軸。

如下圖所示:

image

 

圖中已知4個點:clip_image001[19]

對應的值為:clip_image001[21]

那么如果先對y方向進行插值再對x軸方向進行插值的話,計算思路如下:

clip_image001[23]

同理,如果先對y方向進行插值再對x軸方向進行插值的話,計算思路如下:

clip_image001[25]

上面就是雙線性插值的計算思路。

好的,現在已經對雙線性插值的概念有了比較清楚的認識,那么接下來就看看雙線新插值在圖像縮放里面的應用吧。

在圖像縮放中,如果源圖像是的圖像,而縮放后的圖像為,那么原圖與縮放后的圖在xy方向上的縮放比為clip_image001[31]

clip_image001[33]

image

由於在原圖當中並不存在點P的像素值,為了求得這個對應於縮放后的圖像在(i,j)位置的像素值,我們就需要根據該位置周圍的4個像素點的像素值進行雙線性插值得到該點的像素值,這樣我們就可以求得縮放后的圖像在位置(i,j)上的像素值了。對縮放后的圖像的每個像素點遍歷一遍,就可以得到整幅縮放后的圖像了。整個思路就是:

image

根據上面的雙線性插值的公式:

clip_image001[35]

式子當中的clip_image001[37]

所以,經整理可得:

clip_image001[39]

在這里,u、v為浮點坐標的小數部分,是取值[0,1)區間的浮點數。

理論上面已經講得差不多了,下面來看一下C#的實現代碼:

            double xRatio = (double)rect.Width / newRect.Width;//橫向比
            double yRatio = (double)rect.Height / newRect.Height;//縱向比

            unsafe
            {
                //源圖像的掃描起點
                byte* ptr1 = (byte*)(bmpData1.Scan0);
                //新圖像的掃描起點
                byte* ptr2 = (byte*)(bmpData2.Scan0);
                //對新圖像的像素點進行遍歷
                for (int i = 0; i < bmpData2.Height; i++)
                {
                    double srcY = i * yRatio;//源圖像“虛”坐標的y值
                    int IntY = (int)srcY;//向下取整
                    double v = srcY - IntY;//獲取小數部分
                    double v1 = 1.0 - v;
                    for (int j = 0; j < bmpData2.Width; j++)
                    {
                        double srcX = j * xRatio;//源圖像“虛”坐標的x值
                        int IntX = (int)srcX;//向下取整
                        double u = srcX - IntX;//獲取小數部分
                        double u1 = 1.0 - u;

                        int Index00 = IntY * stride1 + IntX * 3;//得到原圖左上角的像素位置
                        int Index10;                            //原圖左下角的像素位置
                        if (IntY < bmpData1.Height - 1)
                        {
                            Index10 = Index00 + stride1;
                        }
                        else
                        {
                            Index10 = Index00;
                        }
                        int Index01;                            //原圖右上角的像素位置
                        int Index11;                            //原圖右下角的像素位置
                        if (IntX < bmpData1.Width - 1)
                        {
                            Index01 = Index00 + 3;
                            Index11 = Index10 + 3;
                        }
                        else
                        {
                            Index01 = Index00;
                            Index11 = Index10;
                        }
                        double temp0 = (v1 * (u * ptr1[Index01] + u1 * ptr1[Index00]) +
                                        v * (u * ptr1[Index11] + u1 * ptr1[Index10]));

                        double temp1 = (v1 * (u * ptr1[Index01 + 1] + u1 * ptr1[Index00 + 1]) +
                                        v * (u * ptr1[Index11 + 1] + u1 * ptr1[Index10 + 1]));

                        double temp2 = (v1 * (u * ptr1[Index01 + 2] + u1 * ptr1[Index00 + 2]) +
                                        v * (u * ptr1[Index11 + 2] + u1 * ptr1[Index10 + 2]));

                        ptr2[0] = (byte)temp0;
                        ptr2[1] = (byte)temp1;
                        ptr2[2] = (byte)temp2;
                        ptr2 += 3;
                    }
                    ptr2 += offset2;
                }
            }
 

image

image

參考文章:

http://blog.sina.com.cn/s/blog_afe2af380101cadz.html

http://blog.csdn.net/qiqi5521/article/details/2207562

http://www.cnblogs.com/Imageshop/archive/2011/11/12/2246808.html#2922372


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM