【问题标题】:Average color of bitmap位图的平均颜色
【发布时间】:2017-03-19 23:34:09
【问题描述】:

我正在寻找一种极其有效和准确的方法来确定位图的平均 RGB 值。我目前有一种使用位锁的方法,它逐个像素地运行,并且在 30Hz 时占用了我大约 25% 的 CPU。

通过查看每三个像素,我已设法将其降低到约 15%,但我相信有更好的方法。我也尝试将计算转移到 GPU (Nvidia CUDA),但由于我在 GPU 编程方面缺乏经验,因此只需要更长时间。

我考虑过应用模糊之类的事情,但这不会减少像素数量,因此不会影响计算。

我想听听您对这个有趣话题的看法。

【问题讨论】:

  • 你的问题太笼统了,而且含糊其辞。您说您尝试查看每 3 个像素,但这并没有平均像素值。构建一个使用该计算产生与真实平均值截然不同的平均值的图像是微不足道的。最终,您必须将每个值相加,然后除以总数。这就是平均值。使用 CUDA 可能会或可能不会改善事情;将字节移动到视频卡可能需要与扫描和添加 RAM 一样多的时间。
  • 还请注意,CPU %age 不会告诉您任何有关效率的信息……它只是告诉您在算法运行时您正在使用的可用 CPU 的比例。使用 25% CPU 并耗时 10 秒的算法比使用 25% CPU 且仅耗时 5 秒的算法效率低。重要的是总计算时间。多线程代码可以通过使用更多 CPU 时间来提高吞吐量,但不一定被认为本身更高效。
  • 如果每 3 个像素检查一次是可以接受的,是否也可以将其缩小到 5-10%?

标签: c# colors bitmap processing-efficiency


【解决方案1】:

您可以开发一个 c++ dll,使用内部函数使用 SIMD 优化/矢量化代码执行相同的计算。然后,即使在相同的使用百分比下,cpu 的使用效率也会更高。处理未对齐的标题部分,然后使用更快的内在函数处理剩余的对齐部分。

如果这还不够,请尝试仅将一半甚至四分之一的图像移动到 GPU,因为 pci-e 是瓶颈。

流水线还有助于隐藏复制到 gpu 的一些延迟,但会使用更多 CPU,但完成速度更快,因此使用的总周期更少。

如果位图已经在 cpu 缓存中,它应该能够在 GPU 处理“映射”内存块(另一个位图或同一位图的一部分)时同时处理它,而不会出现 RAM 瓶颈。如果要流式传输数据,请不要复制到 GPU。让 GPU 使用适当的访问函数或标志将其映射到自己的控制器上。

“映射”的起点可以是位图字节数组的第一个 4096 寻址元素的倍数。

如果您有集成 GPU,请尝试使用 opencl,因为它更接近 RAM。


对于纯 C# 解决方案,尝试多个累加器以更好地使用 cpu 管道。在不安全的环境中使用它们。按 int 或 long 读取,而不是字节。然后使用 bithacks 处理它,除非 C# 已经在进行矢量化。


扫描平均值不使用乘法单位。所以你可以用一些交错的代码或做异步来增加东西。也许你可以同时混合一些其他的位图?


c[i]=a[i]+b[i]

与简单的 C# one-liner 相比,使用完全优化的 gpgpu 方法快 18 倍。我正在使用 Visual Studio 2015 社区版(项目处于发布模式和 64 位目标)。使用 Intel HD-400 iGPU(600MHz) 和 C3060(1.6GHz)(单通道 RAM),这是一款低端笔记本电脑,CPU 使用率为 %50ish 而不是纯 C# 的 %70ish。

【讨论】:

    猜你喜欢
    • 2012-07-28
    • 2010-11-07
    • 1970-01-01
    • 1970-01-01
    • 2013-06-04
    • 1970-01-01
    • 2011-03-28
    • 2012-09-06
    • 1970-01-01
    相关资源
    最近更新 更多