相机旋转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;
}
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;
}
基于像素的图像处理,一定要放在内存中进行,否则太慢了,避免使用类似GetPixel和SetPixel的方法。