处理大量图像数据的策略

时间:2012-02-01 21:42:53

标签: c# .net memory-management image-processing parallel-processing

技术堆栈:C#/ .NET 4 / WinForms

背景:

我正在使用的项目是一系列图像堆栈的可视化应用程序。具体地,每个图像堆栈与网格对齐,在任何时间显示相同的图像,并且处理功能应用于当前在视图中的图像。图像堆栈本身为150-300 MB,每个映像为512KB-1MB。典型的数据集将包含~100个图像堆栈。

问题:

为了尝试使用这些数据,我使用了几种技术:

  • 内存映射文件:在启动应用程序时从磁盘加载图像堆栈
  • 允许使用不安全代码的x64下的编译:显然我需要64位地址空间用于这种大小的文件。我正在将当前显示的图像从内存映射文件移动到一个方法,该方法通过带有不安全指针的Marshal.Copy生成位图。
  • System.Threading.Tasks:我正在使用并行循环进行处理
  • System.Drawing.BufferedGraphicsContext:每个图像堆栈都有一个活动图像,在传递给PictureBox以显示给用户之前,该图像被合成到BufferedGraphicsContext上。
  • 高端系统要求:四核CPU或更高,SSD,12GB内存等

然而,即使使用上述所有内容,重复性仍然有很多不足之处。使用SysInternals Process Explorer,CPU利用率很低(<25%),而内存使用量在垃圾收集发生之前会上升到极限。

分析表明,大部分执行时间都花在从内存映射文件中获取数据上。我假设它等待操作系统将请求的内存页面重新打开到活动内存中?

我还能做些什么来改善表现?

注意:

  • 大多数(如果不是全部)图像堆栈将同时可见,因此剪切到当前视口可能不会产生太大的速度。
  • 调整显示大小是一个选项,但完整的原始数据必须始终可用于处理,因此这似乎只是一个额外的步骤。

更新1:

  • 对于内存,我的开发盒只有6 GB(我试图加载更少的文件),但部署系统将有24 GB。
  • 我正在考虑通过CUDA通过英特尔性能基元和GPU加速进行SSE优化。
  • 我试图将所有数据加载到内存中的原因是因为一个重要的可视化步骤是在15-60 Hz的图像堆栈中循环而且我害怕颠簸。

5 个答案:

答案 0 :(得分:5)

首先,我认为使用不安全的代码和内存映射文件并不是很有帮助。您需要从磁盘读取大约20GB的数据。如果您只是使用流,那么从磁盘读取它将比内存中的一个额外副本花费更长的时间 - 您已经在错误的位置进行了优化。

我认为你应该从不同的角度来看待它。您可以在显示器上显示少量10MB数据的图像堆栈 - 价值20GB。您不需要读取20GB的数据来显示所有图像堆栈,并在处理这些图像时提供响应式UI。您只需要从每个堆栈加载顶部图像 - 这将更快

至于实际处理,除非你能以某种方式使用GPU,否则我认为你不能比并行处理图像更快。我想这取决于你实际做的处理。

答案 1 :(得分:2)

当所有图像都可用时,您仍然可以为每个图像预先生成拇指图像,并仅在Grid上加载它们。在用户将效果/转换应用于图像的那一刻,您可以仅加载 该图像。即使在加载该图像时,您也可以将其分配到剪切加载扇区并以异步方式加载它们。如果您查看Google Street View,它是如何加载的,在缩放后,您会发现从不整个图像(即使它是您请求的)立即加载,但是它按扇区加载。

我认为另一种非常有趣的技术,Deep Zoom可能是,如果不是你问题的答案,但至少可以提供一个好的提示。

来自Scott Hanselman的

Another example on Deep Zoom

祝你好运。

答案 2 :(得分:0)

听起来很反常,你应该尝试触摸(即从每个文件的开头每4KB读取一个字节)应用程序启动时内存映射文件中的所有数据。由于你有足够的RAM,问题可能不是操作系统正在分页你的图像,而是它最初没有分页。内存映射文件是懒惰加载的,所以操作系统不会在你真正尝试访问内存映射文件中的数据。因此,在应用程序加载时触摸内存将导致磁盘读取发生,而不是用户正在查看映像堆栈时。

答案 3 :(得分:0)

减少并行处理的图像数量以增加内存局部性。 因此,您的4个核心应该同时处理一个图像。 这对处理器缓存很有用。

答案 4 :(得分:0)

根据显示器和图像的大小,您可以尝试下采样图像以适合堆栈所在的方块的分辨率。然后,如果您想要聚焦图像的某个点,则可以重新加载原始图片。

如果您使用的是WPF,可以尝试使用DecodePixelWidth和DecodePixelHeight。也许在winforms中有一个等价物