编写高效的C#图像处理程序

前些天阅读《各种图像处理类库的比较及选择(The Comparison of Image Processing Libraries)》,对后面的比较结果感觉怪异。对计算密集型运算,C#和C/C++的性能应该差别不大才是。为了探讨问题,做了以下实验。

本实验比较了五种方式进行图像灰度化计算:

(1)EmguCV实现,见 《各种图像处理类库的比较及选择(The Comparison of Image Processing Libraries)》 文中代码

(2)OpenCV/PInvoke实现,见 《各种图像处理类库的比较及选择(The Comparison of Image Processing Libraries)》 文中代码

(3)BitmapData实现,见 《各种图像处理类库的比较及选择(The Comparison of Image Processing Libraries)》 文中代码

(4)Array实现(ArgbImage8),核心代码如下:

(每一个)ImageChannel8 内含1个Byte数组Data。GrayscaleImage8  继承自 ImageChannel8 。
  1.     public class ArgbImage8 : ImageChannelSet8
  2.     {
  3.         public ImageChannel8 A { get { return this.Channels[0]; } }
  4.         public ImageChannel8 R { get { return this.Channels[0]; } }
  5.         public ImageChannel8 G { get { return this.Channels[0]; } }
  6.         public ImageChannel8 B { get { return this.Channels[0]; } }

  7.         public ArgbImage8(int width, int height)
  8.             : base(4, width, height)
  9.         {
  10.         }

  11.         public GrayscaleImage8 ToGrayscaleImage()
  12.         {
  13.             return ToGrayscaleImage(0.299, 0.587, 0.114);
  14.         }

  15.         public GrayscaleImage8 ToGrayscaleImage(double rCoeff, double gCoeff, double bCoeff)
  16.         {
  17.             GrayscaleImage8 img = new GrayscaleImage8(this.Width, this.Height);
  18.             Byte[] r = R.Data;
  19.             Byte[] g = G.Data;
  20.             Byte[] b = B.Data;
  21.             Byte[] dst = img.Data;

  22.             for (int i = 0; i < r.Length; i++)
  23.             {
  24.                 dst = (Byte)(r * rCoeff + g * gCoeff + b * bCoeff);
  25.             }

  26.             return img;
  27.         }

  28.         //性能低下,先这样写了
  29.         public static ArgbImage8 CreateFromBitmap(Bitmap map)
  30.         {
  31.             if (map == null) throw new ArgumentNullException("map");

  32.             ArgbImage8 img = new ArgbImage8(map.Width, map.Height);
  33.             Byte[] a = img.A.Data;
  34.             Byte[] r = img.R.Data;
  35.             Byte[] g = img.G.Data;
  36.             Byte[] b = img.B.Data;

  37.             for (int row = 0; row < img.Height; row++)
  38.             {
  39.                 for (int col = 0; col < img.Width; col++)
  40.                 {
  41.                     int index = row * img.Width + col;
  42.                     Color c = map.GetPixel(col, row);
  43.                     a[index] = c.A;
  44.                     r[index] = c.R;
  45.                     r[index] = c.R;
  46.                     r[index] = c.R;
  47.                 }
  48.             }

  49.             return img;
  50.         }
  51.     }
复制代码
(5)C# 指针/unsafe 实现(ArgbImage32 ),核心代码如下:
  1.     public class UnmanagedMemory<T> : IDisposable
  2.         where T : struct
  3.     {
  4.         public Int32 ByteCount { get; private set; }
  5.         public Int32 Length { get; private set; }
  6.         public IntPtr Start { get; private set; }
  7.         public Int32 SizeOfType { get; private set; }

  8.         public UnmanagedMemory(Int32 length)
  9.         {
  10.             Length = length;
  11.             SizeOfType = SizeOfT();
  12.             ByteCount = SizeOfType * length;
  13.             Start = Marshal.AllocHGlobal(ByteCount);
  14.         }

  15.         public void Dispose()
  16.         {
  17.             Dispose(true);
  18.             GC.SuppressFinalize(this);
  19.         }

  20.         protected virtual void Dispose(bool disposing)
  21.         {
  22.             if (false == disposed)
  23.             {
  24.                 disposed = true;
  25.                 Marshal.FreeHGlobal(Start);
  26.             }
  27.         }

  28.         private bool disposed;

  29.         ~UnmanagedMemory()
  30.         {
  31.             Dispose(false);
  32.         }

  33.         private Int32 SizeOfT()
  34.         {
  35.             return Marshal.SizeOf(typeof(T));
  36.         }
  37.     }


  38.     public struct Argb32
  39.     {
  40.         public Byte Alpha;
  41.         public Byte Red;
  42.         public Byte Green;
  43.         public Byte Blue;
  44.     }

  45.     public class Argb32Image : UnmanagedMemory<Argb32>
  46.     {
  47.         private unsafe Argb32* m_pointer;

  48.         public unsafe Argb32* Pointer { get { return m_pointer; } }

  49.         public unsafe Argb32Image(int length)
  50.             : base(length)
  51.         {
  52.             m_pointer = (Argb32*)this.Start;
  53.         }

  54.         public unsafe Argb32 this[int index]
  55.         {
  56.             get { return *(m_pointer + index); }
  57.             set { *(m_pointer + index) = value; }
  58.         }

  59.         public Grayscale8Image ToGrayscaleImage()
  60.         {
  61.             return ToGrayscaleImage(0.299, 0.587, 0.114);
  62.         }

  63.         public unsafe Grayscale8Image ToGrayscaleImage(double rCoeff, double gCoeff, double bCoeff)
  64.         {
  65.             Grayscale8Image img = new Grayscale8Image(this.Length);
  66.             Argb32* p = Pointer;
  67.             Byte* to = img.Pointer;
  68.             Argb32* end = p + Length;

  69.             while (p != end)
  70.             {
  71.                 *to = (Byte)(p->Red * rCoeff + p->Green * gCoeff + p->Blue * bCoeff);
  72.                 p++;
  73.                 to++;
  74.             }
  75.             return img;
  76.         }

  77.         public unsafe static Argb32Image CreateFromBitmap(Bitmap map)
  78.         {
  79.             if (map == null) throw new ArgumentNullException("map");

  80.             Argb32Image img = new Argb32Image(map.Width*map.Height);

  81.             Argb32* p = img.Pointer;

  82.             for (int row = 0; row < map.Height; row++)
  83.             {
  84.                 for (int col = 0; col < map.Width; col++)
  85.                 {
  86.                     Color c = map.GetPixel(col, row);
  87.                     p->Alpha = c.A;
  88.                     p->Red = c.R;
  89.                     p->Green = c.G;
  90.                     p->Blue = c.B;
  91.                     p++;
  92.                 }
  93.             }

  94.             return img;
  95.         }
  96.     }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值