5

我的内部循环包含一个分析显示有问题的计算。

这个想法是采用灰度像素 x (0 <= x <= 1),并“增加其对比度”。我的要求相当宽松,如下:

  • 对于 x < .5, 0 <= f(x) < x
  • 对于 x > .5,x < f(x) <= 1
  • f(0) = 0
  • f(x) = 1 - f(1 - x),即它应该是“对称的”
  • 优选地,该函数应该是平滑的。

所以图表必须看起来像这样:

图形.

我有两个实现(它们的结果不同但都是一致的):

float cosContrastize(float i) {
    return .5 - cos(x * pi) / 2;
}

float mulContrastize(float i) {
    if (i < .5) return i * i * 2;
    i = 1 - i;
    return 1 - i * i * 2;
}

因此,我要求对这些实现之一进行微优化,或者您自己的原始、更快的公式。

也许你们中的一个人甚至可以旋转这些位;)

4

3 回答 3

13

考虑以下sigmoid形函数(正确转换为所需范围):

截屏


我使用 MATLAB 生成了上图。如果有兴趣这里的代码:

x = -3:.01:3;
plot(   x, 2*(x>=0)-1, ...
        x, erf(x), ...
        x, tanh(x), ...
        x, 2*normcdf(x)-1, ...
        x, 2*(1 ./ (1 + exp(-x)))-1, ...
        x, 2*((x-min(x))./range(x))-1  )
legend({'hard' 'erf' 'tanh' 'normcdf' 'logit' 'linear'})
于 2009-09-26T00:27:26.257 回答
5

微不足道,您可以简单地设置阈值,但我认为这太愚蠢了:

return i < 0.5 ? 0.0 : 1.0;

由于您提到“增加对比度”,我假设输入值是亮度值。如果是这样,并且它们是离散的(可能是 8 位值),您可以使用查找表快速完成此操作。

您的“mulContrastize”看起来相当快。一种优化是使用整数数学。再说一次,您的输入值实际上可以作为 [0..255] 中的 8 位无符号值传递。(再次,可能是一个很好的假设?)你可以做一些大致像......

int mulContrastize(int i) {
  if (i < 128) return (i * i) >> 7; 
  // The shift is really: * 2 / 256
  i = 255 - i;
  return 255 - ((i * i) >> 7);
于 2009-09-25T23:53:56.433 回答
4

分段插值可以快速灵活。它只需要几个决定,然后是乘法和加法,并且可以逼近任何曲线。它还避免了查找表可能引入的过程(或两次查找中的额外成本,然后进行插值以消除这种情况),尽管 lut 可能非常适合您的情况。

替代文字

只需几个片段,您就可以获得非常好的匹配。在这里,颜色渐变中会有路线,这将比绝对颜色中的路线更难检测。

正如 Eamon Nerbonne 在评论中指出的那样,可以通过“根据诸如二阶导数之类的东西来选择分割点以最大化细节”来优化分割,即斜率变化最大的地方。显然,在我发布的示例中,在五段案例的中间设置三个段并不会增加更多细节。

于 2009-09-27T15:30:43.930 回答