更快的C#图像处理 [英] Faster c# image processing

查看:160
本文介绍了更快的C#图像处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个相当广泛的c ++图像处理库,并且我一直在从事c#项目的工作,但是我似乎无法使c#的运行速度与c ++差不多.我的c ++花费149ms来处理将整个图像设置为白色,而c#花费了1071ms来完成相同的操作.

这是我的c ++代码

  for(int i = 0; i< 100; i ++){for(int y = 0; y< image-> height; y ++){unsigned char * srcPixel =(unsigned char *)image-> mImageData +(y * image-> width);对于(int x = 0; x< image-> width; x ++){srcPixel [0] = 255;srcPixel [1] = 255;srcPixel [2] = 255;srcPixel [3] = 255;srcPixel + = 4;}}} 

mImageData是无符号字符的结构

  struct mImageData{无符号字符alpha;未签名的字符红色;未签名的字符绿色;未签名的字符蓝色;} 

这是我正在使用的C#代码.这是我能够获得的最快的速度.

  frame =新的位图(3840,2160);BitmapData bitmapData12 = frame.LockBits(new Rectangle(0,0,frame.Width,frame.Height),ImageLockMode.ReadWrite,PixelFormat.Format32bppArgb);var stopwatch = Stopwatch.StartNew();不安全的{int pixelBytes = 4;int paddingBytes = bitmapData12.Stride%pixelBytes;字节* location1 =(字节*)bitmapData12.Scan0;对于(int i = 0; i< 100; i ++){location1 =(字节*)bitmapData12.Scan0;对于(int y = 0; y  

解决方案

我以ResW = 3000和ResH = 3000运行了您的代码,以获取900ms的处理时间.我在释放模式下运行了它,并断开了调试器.

观察到此图像包含900万像素,每个像素4个字节长.这是36 MB的空间.我们将其填充100次,因此总共需要设置36亿字节.我的CPU运行在4.5 GHz上,因此它设法在40亿个时钟周期内设置了36亿字节.

我想说这对于任何一种语言来说都不算太过简陋.如果我关闭我的开发机上的所有VM,后台进程和服务器(目前消耗5%到20%的CPU)以进行更清晰的测量,则每个时钟周期几乎可以设置一个字节.当然,CPU可以做得更好-如果,您要求它们执行正确的操作.一次设置一个字节肯定会使它变慢.

因此C#实际上确实在不修改算法的情况下尽可能快地执行了此操作.只是C#拒绝优化经过代码的文字转换,而C ++可以并且会做到这一点.在我自己的测试中,只需按照AdamF的建议(使用 uint )进行操作即可将时间缩短到300ms.

我认为您没有指定ResW/ResH是什么(或者我是盲目的),因此仍然有可能没有以最快的方式运行代码,并且会干扰测量./p>

I have a pretty extensive c++ image processing library and I have been working on a c# project but I cannot seem to be able to get the c# to be anywhere near as fast as the c++. My c++ takes 149ms to process setting the entire image white while the c# takes 1071ms to do the same.

Here is my c++ code

for (int i = 0; i < 100; i++)
{
    for (int y = 0; y < image->height; y++)
    {
        unsigned char * srcPixel = (unsigned char*)image->mImageData + (y * image->width);

        for (int x = 0; x < image->width; x++)
        {
            srcPixel[0] = 255;
            srcPixel[1] = 255;
            srcPixel[2] = 255;
            srcPixel[3] = 255;
            srcPixel += 4;
        }
    }
}

mImageData is a struct of unsigned chars

struct mImageData
{
    unsigned char alpha;
    unsigned char red;
    unsigned char green;
    unsigned char blue;
}

And this is the c# code I am using. This is the fastest I have been able to get this one.

frame = new Bitmap(3840, 2160);
BitmapData bitmapData12 = frame.LockBits(new Rectangle(0, 0,
            frame.Width, frame.Height),
            ImageLockMode.ReadWrite,
            PixelFormat.Format32bppArgb);


var stopwatch = Stopwatch.StartNew();
unsafe
{
    int pixelBytes = 4;
    int paddingBytes = bitmapData12.Stride % pixelBytes;

    byte* location1 = (byte*)bitmapData12.Scan0;

    for (int i = 0; i < 100; i++)
    {
        location1 = (byte*)bitmapData12.Scan0;
        for (int y = 0; y < bitmapData12.Height; ++y)
        {
            for (int x = 0; x < bitmapData12.Width; ++x)
            {
                location1[0] = 255;
                location1[1] = 255;
                location1[2] = 255;
                location1[3] = 255;

                location1 += pixelBytes;
            }

            location1 += paddingBytes;
        }
    }
}

stopwatch.Stop();
var miliseconds = stopwatch.ElapsedMilliseconds;

frame.UnlockBits(bitmapData12);

解决方案

I ran your code with ResW = 3000 and ResH = 3000, to get 900ms processing time. I ran it in Release mode, with the debugger detached.

Observe that this image contains 9 million pixels, each one 4 bytes long. That's 36 MB to fill. We're filling this 100 times, so a total of 3.6 billion bytes to set. My CPU runs at 4.5 GHz, so it managed to set 3.6 billion bytes in 4 billion clock cycles.

I'd say that's not too shabby for any language. If I were to shut down all the VMs, background processes and servers on my dev machine (which are currently consuming between 5% and 20% CPU) to run a cleaner measurement, I'd get pretty much exactly one byte set per clock cycle. Of course CPUs can do vastly better - if you ask them to perform the right operation. Setting one byte at a time certainly makes it slower.

So C# is really doing this as fast as possible without modifying the algorithm. It's just that C# refuses to optimize past a literal translation of the code, whereas C++ can and will do that. Simply doing what AdamF suggests (use uint) already shrinks the time to 300ms in my own tests.

I don't think you've specified what your ResW/ResH are (or I'm blind), so it's still possible that you're not running the code the fastest way possible and something interferes with the measurement.

这篇关于更快的C#图像处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆