位图数据与图像<,>.访问像素值时的数据 - 性能
本文关键字:数据 性能 像素 图像 位图 访问 | 更新日期: 2023-09-27 18:37:01
我正在开发一种图像处理工具(C#,使用EmguCV)我需要在像素上的单个操作上获得最佳性能。
我已经阅读了很多关于LockBit()
并将值从指针复制到字节数组作为最佳方法(当性能优先时)以获取/设置像素值的线程。
我发现了一些这样的实现:http://www.codeproject.com/Tips/240428/Work-with-bitmap-faster-with-Csharp
我将其与更简单的方法进行了比较:
Image<Bgr, byte> image = new Image<Bgr, byte>(Bitmap);
byte[,,] data = image.Data;
//And then get r channel like:
byte rChannel = data[y,x,0];
//And set r channel like:
data[y,x,0] = color.R;
因此,我使用了上面链接中的实现,但我剪掉了一个像 Color.FromArgb(r, g, b);
这样的创建Color
,并假设图像深度 = 24,只是为了优化性能(我返回一个字节的 1D 数组作为颜色)
我的结果(图像 2048x2048 - 4194304 将像素颜色与Color.White
进行比较的操作 - 完成 3 次):
Via `LockBit()` and pointer method:
00:00:00.7971876
00:00:00.7569262
00:00:00.7693977
Via `Image<,>.Data` method:
00:00:00.7957318
00:00:00.8136698
00:00:00.8010817
我认为不安全的LockBits()
和指针方法与非常清晰和简单的Image<,>.Data
方法之间没有任何显着的性能差异。
有人可以解释为什么LockBits()/Pointer
方法被称为超快吗?也许我错过了一些东西(正如我所说 - 我使用了上面链接的实现)。
你是问为什么使用LockBits()
"被称为超快"吗?我并不完全清楚这里的"第一个"指的是什么。
也就是说,重要的问题是您的代码是否需要过渡到图形驱动程序(处理位图操作)。转换非常昂贵,每次调用 GetPixel()
或 SetPixel()
等方法时都会发生。
因此,API 类似于 LockBits()
方法。在此类方法中,您将单个转换中的所有数据复制到图形驱动程序中,并复制到程序可以直接访问的内存中。然后你直接对该内存进行操作。然后,在另一个过渡中将其复制回位图(如有必要)。
与使用 GetPixel()
和 SetPixel()
相比,像 LockBits()
这样的东西非常快。但LockBits()
并不是实现这种性能的唯一方法。任何避免与图形驱动程序之间转换的 API 将是"超快"的。由于EmguCV类似于使用LockBits()
,因为它不涉及代码和图形驱动程序之间的大量转换,因此速度也同样快。
这样看:使用GetPixel()
和SetPixel()
有点像骑自行车,而使用LockBits()
和EmguCV更像是驾驶赛车。后两者并不相同;一辆赛车和/或其驾驶员将比另一辆略慢或更快。但两者都比人力运输快得多。