实现图片沿水平和竖直方向翻转(旋转180度)

相机旋转180度,为了不改变原有的算法,最好的方法是将图片旋转180,这样就和之前拍摄的图片一致了。最先想到的方法是在basler相机中设置,但只找到了ReverseX,不满足要求。

查阅左飞的图像处理书,他介绍了基于GDI+ 中DrawImage实现翻转的方法,分辨率为2592*1944的图片,耗时260ms,太慢了,这种方法不可取。实现代码如下

        private Bitmap ReverseByDrawImage(Bitmap bitmap)
        {
            System.DateTime begin = System.DateTime.Now;

            Bitmap image = new Bitmap(bitmap.Width, bitmap.Height);
            using (Graphics graphics = Graphics.FromImage(image)) //假如直接使用FromImage(bitmap),会报错“无法从带有索引像素格式的图像创建Graphics对象。”
            {
                Rectangle Rect = new Rectangle(0, 0, bitmap.Width, bitmap.Height);
                graphics.DrawImage(bitmap, Rect, Rect, GraphicsUnit.Pixel);
                graphics.Dispose();
            }

            Graphics graphicsRev = Graphics.FromImage(image);

            Point[] VerPoints = { new Point(bitmap.Width, 0), new Point(0, 0), new Point(bitmap.Width, bitmap.Height) };
            graphicsRev.DrawImage(image, VerPoints);

            Point[] HorPoints = { new Point(0, bitmap.Height), new Point(bitmap.Width, bitmap.Height), new Point(0, 0) };
            graphicsRev.DrawImage(image, HorPoints);

            System.DateTime end = System.DateTime.Now;
            TimeSpan duration = end - begin;
            MessageBox.Show("DrawImage Duration time is :" + duration.Milliseconds + " ms");
            return image;
        }


第二种方法是在内存中实现翻转,原理是在内存中将图片像素首尾替换,该方法耗时26ms,代码如下 

        private unsafe Bitmap ReverseBmpByPtr(Bitmap bitmap)
        {
            System.DateTime begin = System.DateTime.Now;

            Bitmap bitmapClone = (Bitmap)bitmap.Clone();

            int width = bitmap.Width;
            int height = bitmap.Height;

            int length = height * width;
            byte[] Pixels = new byte[length];
            byte[] PixelsClone = new byte[length];

            BitmapData data = bitmap.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadOnly, PixelFormat.Format8bppIndexed);
            BitmapData dataClone = bitmapClone.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.WriteOnly, PixelFormat.Format8bppIndexed);


            System.IntPtr Scan0 = data.Scan0;
            System.IntPtr Scan0Clone = dataClone.Scan0;

            System.Runtime.InteropServices.Marshal.Copy(Scan0, Pixels, 0, length);
            System.Runtime.InteropServices.Marshal.Copy(Scan0Clone, PixelsClone, 0,length);

            for (int i = 0; i < Pixels.Length; i += 1)
            {
                PixelsClone[i] = Pixels[length-i-1];
            }

            System.Runtime.InteropServices.Marshal.Copy(Pixels, 0, Scan0, length);
            System.Runtime.InteropServices.Marshal.Copy(PixelsClone, 0, Scan0Clone, length);

            bitmap.UnlockBits(data);
            bitmapClone.UnlockBits(dataClone);

            System.DateTime end = System.DateTime.Now;
            TimeSpan duration = end - begin;
            MessageBox.Show("Ptr Duration time is :" + duration.Milliseconds + " ms");
            

            return bitmapClone;
        }


后来发现Bitmap类有一个方法RotateFlip支持对图像和旋转和翻转操作,速度更快,耗时15ms

        private Bitmap ReverseBmpByRotateFlip(Bitmap bitmap)
        {
            System.DateTime begin = System.DateTime.Now;

            bitmap.RotateFlip(RotateFlipType.Rotate180FlipNone);
            System.DateTime end = System.DateTime.Now;
            TimeSpan duration = end - begin;
            MessageBox.Show("RotateFlip Duration time is :" + duration.Milliseconds + " ms");
            return bitmap;
        }

测试了Halcon中mirror_image算子,耗时约为13ms。

基于像素的图像处理,一定要放在内存中进行,否则太慢了,避免使用类似GetPixel和SetPixel的方法。







你可能感兴趣的:(【C#】,【视觉】)