C#双线性插值

647 阅读1分钟

根据维基百科的定义:
双线性插值,又称为双线性内插。在数学上,双线性插值是对线性插值在二维直角网格上的扩展,用于对双变量函数(例如 x 和 y)进行插值。其核心思想是在两个方向分别进行一次线性插值。

定义一个函数方法ReClass

 //使用双线性插值法进行重采样
        private Bitmap ReClass(Bitmap bitmap)
        {
            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bmpData = bitmap.LockBits(rect, ImageLockMode.ReadWrite, bitmap.PixelFormat);
            IntPtr ptr = bmpData.Scan0;
            //得到横坐标和纵坐标的缩放量
            double x =2;
            double y =2.5;
            //图像的几何中心
            int halfHeight = (int)(bitmap.Height / 2);
            int halfWidth = (int)(bitmap.Width / 2);
            int xz = 0;
            int yz = 0;
            int tempWidth = 0;
            int tempHeight = 0;
            int bytes = bitmap.Width * bitmap.Height;
            byte[] grayValues = new byte[bytes];
            byte[] tempArray = new byte[bytes];
            double tempX, tempY, p, q;
            for (int i = 0; i < bitmap.Height; i++)
            {
                for (int j = 0; j < bitmap.Width; j++)
                {
                    //以图像的几何中心为坐标进行坐标变换
                    //按逆向映射法得到输入图像的坐标
                    tempHeight = i - halfHeight;
                    tempWidth = j - halfWidth;
                    tempX = tempWidth / x;
                    tempY = tempHeight / y;
                    

                    //在不同象限内进行取整处理
                    if (tempWidth > 0)
                    {
                        xz = (int)tempX;

                    }
                    else
                    {
                        xz = (int)(tempX - 1);
                    }
                    if (tempHeight > 0)
                    {
                        yz = (int)tempY;
                    }
                    else
                    {
                        yz = (int)(tempY - 1);
                    }
                    //得到灰度插值法的公式中的变量p和q
                    p = tempX - xz;
                    q = tempY - yz;

                    //坐标逆变换
                    tempWidth = xz + halfWidth;
                    tempHeight = yz + halfHeight;

                    if (tempWidth < 0 || (tempWidth + 1) >= bitmap.Width || tempHeight < 0 || (tempHeight + 1) >= bitmap.Height)
                    {
                        //缩放后留下空白的空间用白色像素代替
                        tempArray[i * bitmap.Width + j] = 255;
                    }
                    else
                    {
                        tempArray[i * bitmap.Width + j] = (byte)((1.0 - q) * (1.0 - p) * grayValues[tempHeight * bitmap.Width + tempWidth] + p*grayValues[tempWidth*bitmap.Width+tempWidth+1]+q*(1.0-p)*grayValues[(tempHeight+1)*bitmap.Width+tempWidth]+p*grayValues[(tempHeight+1)*bitmap.Width+1+tempWidth]);
                    }        
                    
                }
            }
            grayValues = (byte[])tempArray.Clone();
            System.Runtime.InteropServices.Marshal.Copy(grayValues, 0, ptr, bytes);
            bitmap.UnlockBits(bmpData);
            return bitmap;
        }


然后在主函数中对这个方法进行应用

picturebox1.Image = ReClass(curBitmap);//curBitmap代表但前的二进制图像