C#双线性插值

根据维基百科的定义:
双线性插值,又称为双线性内插。在数学上,双线性插值是对线性插值在二维直角网格上的扩展,用于对双变量函数(例如 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代表但前的二进制图像
  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
双线性插值图像缩放是一种常用的图像缩放方法,可以在保持图像清晰度的同时缩放图像大小。下面是使用C#实现双线性插值图像缩放的示例代码: ```csharp public static Bitmap BilinearInterpolation(Bitmap source, float scaleX, float scaleY) { int newWidth = (int)(source.Width * scaleX); int newHeight = (int)(source.Height * scaleY); Bitmap result = new Bitmap(newWidth, newHeight); float x, y, u, v; int x1, y1, x2, y2; Color color1, color2, color3, color4; for (int i = 0; i < newHeight; i++) { for (int j = 0; j < newWidth; j++) { x = j / scaleX; y = i / scaleY; x1 = (int)Math.Floor(x); y1 = (int)Math.Floor(y); x2 = (int)Math.Ceiling(x); y2 = (int)Math.Ceiling(y); u = x - x1; v = y - y1; if (x2 >= source.Width) { x2 = source.Width - 1; } if (y2 >= source.Height) { y2 = source.Height - 1; } color1 = source.GetPixel(x1, y1); color2 = source.GetPixel(x2, y1); color3 = source.GetPixel(x1, y2); color4 = source.GetPixel(x2, y2); int red = (int)(color1.R * (1 - u) * (1 - v) + color2.R * u * (1 - v) + color3.R * (1 - u) * v + color4.R * u * v); int green = (int)(color1.G * (1 - u) * (1 - v) + color2.G * u * (1 - v) + color3.G * (1 - u) * v + color4.G * u * v); int blue = (int)(color1.B * (1 - u) * (1 - v) + color2.B * u * (1 - v) + color3.B * (1 - u) * v + color4.B * u * v); result.SetPixel(j, i, Color.FromArgb(red, green, blue)); } } return result; } ``` 该函数接受三个参数:原始图像、缩放比例X和缩放比例Y。它首先计算新图像的大小,然后在新图像上循环遍历每个像素。对于每个像素,它计算出其在原始图像上的四个相邻像素,并使用双线性插值计算出新像素的颜色值。最后,它将新像素的颜色值设置为新图像中对应像素的颜色值,并返回新图像。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

稻田里展望者

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值