C# 图像平移

图像平移:图像的平移是将一幅图像上的所有点都按照给定的偏移量在水平方向沿x轴、在垂直方向上沿y轴移动,平移后的图像与原图像大小相同。设(x0,y0) 为原图像上的一点,图像水平平移量为△x,垂直平移量为△y,则平移后点(x0,y0)坐标将变为(x1,y1),它们之间的数学关系式如下,坐标平移原理如下图所示:

本次实验图像用的时500w像素的图像(2592×1944),且深度为8。

C# 代码实现

上面代码种tempArray数组用Array.Fill方法初始化默认值,因为图像背景为黑色,为了方便区分,设置为白色,以就是:Array.Fill(tempArray, byte.MaxValue);

但是性能很差,耗时808、383ms,非常耗时,如下图:

接下来我们做算法优化,优化方向:减少重复计算和边界处理。如下:

耗时截图如下:

优化非常有效,性能嘎嘎猛!

但是作为simd资深玩家,怎么可能止步到此,接下来我们用simd优化,如下:

耗时如下: 

哇靠!性能再一次突破!太猛了~

附:OpeCV Sharp代码:

 为了兼容24、32深度图像,我们可以做如下修改(simd代码同样修改方法):

private unsafe Bitmap? Translation2()
        {
            if (string.IsNullOrEmpty(_imagePath)) return null;
            Bitmap bitmap = new Bitmap(_imagePath);

            Rectangle rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
            BitmapData bitmapData = bitmap.LockBits(rect, ImageLockMode.WriteOnly, bitmap.PixelFormat);
            byte* ptrSrc = (byte*)bitmapData.Scan0;
            int bytes = bitmapData.Stride * bitmapData.Height;

            byte[] tempArray = new byte[bytes];
            Array.Fill(tempArray, byte.MaxValue);
            int xOffset = (int)numericUpDown1.Value;
            int yOffset = (int)numericUpDown2.Value;

            int yoffset1, yoffset2;
            int tempy = yOffset * bitmapData.Stride;
            int startX;
            int startY;
            int nheight;
            int nwidth;
            if (xOffset >= 0)
            {
                startX = 0;
                nwidth = bitmapData.Stride - xOffset;
            }
            else
            {
                startX = -xOffset;
                nwidth = bitmapData.Stride;
            }
            if (yOffset >= 0)
            {
                startY = 0;
                nheight = bitmap.Height - yOffset;
            }
            else
            {
                startY = -yOffset;
                nheight = bitmap.Height;
            }
            int setp = 1;
            if (bitmap.PixelFormat == PixelFormat.Format24bppRgb)
                setp = 3;
            else if(bitmap.PixelFormat == PixelFormat.Format32bppRgb)
                setp = 4;
            else
                setp = 1;
            fixed (byte* ptr = tempArray)
            {
                int x = xOffset * setp;
                for (int i = startY; i < nheight; i++)
                {
                    yoffset1 = i * bitmapData.Stride;
                    yoffset2 = yoffset1 + tempy;
                    for (int j = startX; j < nwidth; j++)
                    {
                        //*(ptr + j + xOffset + yoffset2) = *(ptrSrc + j + yoffset1);

                        for (int k = 0; k < setp; k++)
                        {
                            *(ptr + j + x + k + yoffset2) = *(ptrSrc + j + k + yoffset1);
                        }
                    }
                }
            }

            Marshal.Copy(tempArray, 0, bitmapData.Scan0, bytes);
            bitmap.UnlockBits(bitmapData);
            return bitmap;
        }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值