Optimization “a”的快速公式;“高对比度”;曲线

Optimization “a”的快速公式;“高对比度”;曲线,optimization,math,formula,Optimization,Math,Formula,我的内部循环包含一个分析显示有问题的计算 我们的想法是采用灰度像素x(0很简单,您可以简单地设置阈值,但我认为这太愚蠢了: return i < 0.5 ? 0.0 : 1.0; 返回i7; //这个转变真的是:*2/256 i=255-i; 返回255-((i*i)>>7); 考虑以下S形函数(正确转换为所需范围): 我使用MATLAB生成了上图。如果有兴趣,下面是代码: x = -3:.01:3; plot( x, 2*(x>=0)-1, ...

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


我们的想法是采用灰度像素x(0很简单,您可以简单地设置阈值,但我认为这太愚蠢了:

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

您的“多重对比度”看起来相当快。一种优化方法是使用整数数学。再说一次,您的输入值实际上可以在[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);
intmulcontrastize(inti){
如果(i<128)返回(i*i)>>7;
//这个转变真的是:*2/256
i=255-i;
返回255-((i*i)>>7);

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


我使用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'})

分段插值可以快速灵活。它只需要几次决策,然后进行乘法和加法运算,并且可以近似任何曲线。它还避免了查找表所带来的过程性(或者在两次查找之后再进行一次插值以平滑此过程的额外成本),尽管lut可能对您的案例非常有效

只需几段,你就可以得到一个非常好的匹配。在这里,颜色渐变中会有粗糙度,这比绝对颜色中的粗糙度更难检测


正如Eamon Nerbonne在评论中指出的那样,分割可以通过“基于二阶导数选择分割点以最大化细节”来优化也就是说,在斜率变化最明显的地方,在我的例子中,在五个区段中间有三个区段并没有增加更多的细节。

在我的例子中,一个阈值太过平滑,不太有用。它们是亮度值,是的,它们不是离散的值——它们实际上是浮动的,有两个原因。在OpenGL中,浮点纹理是最快的。其次,我决定使用0.0-1.0浮点使我的数学变得简单和快速。但我从来没有想过与查找表进行对比,我会研究一下,看看它是否超过了OpenGL纹理的关注。你发布的实现确实不错,但没有查找表那么好。我的Mulcontastize确实“相当快”,但不是在这样一个紧密的内部循环中:)顺便说一句,你不应该被255除两次,仅仅一次。所以你应该被7除。哦,你是对的,这将标准化一步太远。这将修复这个例子。++对于查找表的建议。是的,我最终使用了一个查找表。它本身没有任何改进。但是它允许我做其他一些优化-谢谢!OP的主要问题是速度。这些是如何加快速度的?谢谢,至少我知道它们现在被称为‘sigmoid’;)我用tanh做了一个简单的实现,它和cos一样快。剩下的要花更多的时间考虑,我认为它们会变慢,但我们会看到的。++Nice。我个人倾向于logit(实际上它是逆logit函数),因为你只需要调用ExpEd()一次,而且除法。你可以通过缩放X.@ ToM10来使它更清晰,OP可以看到所用的公式,最好考虑哪种套件。如果你能告诉我们你使用的是什么语言,我可以帮助你更好的(我假设java)。什么是编译器/运行时。C?s带有MS编译器和运行时,但如果我发现……我需要用CAMELCASE方法名称,那么我愿意重写C++中的临界ALGO:(许多这样的函数在以0为中心时更快/更简单。我不确定你的程序的其余部分,但是如果这种代码是关键的,你可以考虑重新定位你的数据表示,从1…1,而不是0……1,如果你真的很时髦,你可以选择像S一样的分割点。二阶导数可以最大化细节(在区分中心段时没有意义,相当直的段)。@Eamon:感谢二阶导数的想法。我知道我对中心点很懒惰,但我真的很喜欢二阶导数的推广。
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'})