位图数据与图像<,>.访问像素值时的数据 - 性能

本文关键字:数据 性能 像素 图像 位图 访问 | 更新日期: 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更像是驾驶赛车。后两者并不相同;一辆赛车和/或其驾驶员将比另一辆略慢或更快。但两者都比人力运输快得多