【问题标题】:Fast image gamma correction快速图像伽玛校正
【发布时间】:2018-02-21 10:34:38
【问题描述】:

我正在对尺寸为 5000x3000x3 的图像进行伽马校正。

公式是

值 ^ (1 / gamma)

对于 0.0 到 1.0 的 RGB 值

我的输入 gamma 值范围从 0.0 到 10.0,而 gamma = 0.0 始终输出 0.0。

问题在于所涉及的 pow 计算太慢了。

在 float[, ,] 上执行此操作大约需要 1300 毫秒:

for (int y = 0; y < 3000; y++)
{
    for (int x = 0; x < 5000; x++)
    {
        for (int z = 0; z < 3; z++)
        {
            arr[x, y, z] = (float)Math.Pow(arr[x, y, z], 0.3);
        }
    }
}

在 FloatMatrix 上使用 NMathFunctions.Pow 大约需要 1100 毫秒:

a = NMathFunctions.Pow(a, 0.3f);

知道如何加快速度吗?

【问题讨论】:

  • 根据您的精度要求,您始终可以设置查找表并使用最近邻或线性插值(或高阶插值,但这很可能无法解决性能问题)。
  • 您是否考虑过添加并行化?在我看来,每个值都独立于其余值,因此并行算法没有理由不起作用
  • 确实,在我问之前我做了很多谷歌搜索,但我希望能立即在 C# 中使用更简单的东西。感谢您的链接,我会通过它。我不是数学家,但请帮助我了解 2^(p*log2(x)) 如何简化任何事情?还涉及到 pow 操作?编辑:你为什么删除你的评论?
  • @Glubus 值得一试是的。我只是假设像 NMath 这样的库会处理这个问题。
  • @tde,我已经删除了评论,因为我的数学技能已经无法证明这一点(而且我无法在 5 分钟后编辑评论)。这个想法是将昂贵的操作表示为由便宜的操作组成的表达式,现在轮到谷歌了;)

标签: c# gamma nmath


【解决方案1】:

编辑:实际上,如果功率小于 1,我不确定这是否有效。我知道当您想要替换 pow(x, 2.2) 时,它适用于伽马校正。功率更高时效果更好,但功率小于 1 时可能效果不佳


确实,pow 是一个非常慢的函数,甚至比 sqrt 还要慢(这是有道理的,因为 pow 可以使用分数作为指数来完成任何 sqrt 操作)

没有办法更有效地计算功率,但是有很好的方法来估计它。

一个条件是您的基值在 [0, 1] 范围内,这在您的情况下是正确的。然后你可以得到一个很好的估计(准确率在 99% 左右)。你可以这样做:

使用您自己计算的离散幂的组合,而不是使用 pow。例如 x 在 [0, 1] 范围内,

而不是

result = pow(x, 2.2)

result = 0.8*x*x + 0.2*x*x*x

请注意,当 x 为 0 和 x 为 1(结果分别为 0 和 1)时,它是完全准确的

我希望这对你有用

【讨论】:

  • OP 需要0.3 幂,你能解释一下2.2 如何与0.80.2 以及一些乘法运算吗?
猜你喜欢
  • 1970-01-01
  • 2018-12-04
  • 1970-01-01
  • 2021-08-12
  • 1970-01-01
  • 1970-01-01
  • 2013-05-07
  • 2022-12-10
  • 1970-01-01
相关资源
最近更新 更多