技术开发 频道

C#和C++哪个更高效?五方式图像计算实验

  【IT168 技术】阅读《各种图像处理类库的比较及选择(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 。

public class ArgbImage8 : ImageChannelSet8
    {
        
public ImageChannel8 A { get { return this.Channels[0]; } }
        
public ImageChannel8 R { get { return this.Channels[0]; } }
        
public ImageChannel8 G { get { return this.Channels[0]; } }
        
public ImageChannel8 B { get { return this.Channels[0]; } }

        
public ArgbImage8(int width, int height)
            : base(
4, width, height)
        {
        }

        
public GrayscaleImage8 ToGrayscaleImage()
        {
            return ToGrayscaleImage(
0.299, 0.587, 0.114);
        }

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

            
for (int i = 0; i < r.Length; i++)
            {
                dst[i]
= (Byte)(r[i] * rCoeff + g[i] * gCoeff + b[i] * bCoeff);
            }

            return img;
        }

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

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

            
for (int row = 0; row < img.Height; row++)
            {
                
for (int col = 0; col < img.Width; col++)
                {
                    
int index = row * img.Width + col;
                    Color c
= map.GetPixel(col, row);
                    a[index]
= c.A;
                    r[index]
= c.R;
                    r[index]
= c.R;
                    r[index]
= c.R;
                }
            }

            return img;
        }
    }

5)C# 指针/unsafe 实现(ArgbImage32 ),核心代码如下:

    
public class UnmanagedMemory<T> : IDisposable
        where T : struct
    {
        
public Int32 ByteCount { get; private set; }
        
public Int32 Length { get; private set; }
        
public IntPtr Start { get; private set; }
        
public Int32 SizeOfType { get; private set; }

        
public UnmanagedMemory(Int32 length)
        {
            Length
= length;
            SizeOfType
= SizeOfT();
            ByteCount
= SizeOfType * length;
            Start
= Marshal.AllocHGlobal(ByteCount);
        }

        
public void Dispose()
        {
            Dispose(
true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            
if (false == disposed)
            {
                 disposed
= true;
                 Marshal.FreeHGlobal(Start);
            }
        }

        
private bool disposed;

        ~UnmanagedMemory()
        {
            Dispose(
false);
        }

        
private Int32 SizeOfT()
        {
            return Marshal.SizeOf(typeof(T));
        }
    }

    
public struct Argb32
    {
        
public Byte Alpha;
        
public Byte Red;
        
public Byte Green;
        
public Byte Blue;
    }

    
public class Argb32Image : UnmanagedMemory<Argb32>
    {
        
private unsafe Argb32* m_pointer;

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

        
public unsafe Argb32Image(int length)
            : base(length)
        {
            m_pointer
= (Argb32*)this.Start;
        }

        
public unsafe Argb32 this[int index]
        {
            
get { return *(m_pointer + index); }
            
set { *(m_pointer + index) = value; }
        }

        
public Grayscale8Image ToGrayscaleImage()
        {
            return ToGrayscaleImage(
0.299, 0.587, 0.114);
        }

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

            
while (p != end)
            {
                
*to = (Byte)(p->Red * rCoeff + p->Green * gCoeff + p->Blue * bCoeff);
                p
++;
                
to++;
            }
            return img;
        }

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

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

            Argb32
* p = img.Pointer;

            
for (int row = 0; row < map.Height; row++)
            {
                
for (int col = 0; col < map.Width; col++)
                {
                    Color c
= map.GetPixel(col, row);
                    p
->Alpha = c.A;
                    p
->Red = c.R;
                    p
->Green = c.G;
                    p
->Blue = c.B;
                    p
++;
                }
            }

            return img;
        }
    }
0
相关文章