「ハイコントラスト」カーブの高速フォーミュラ
-
18-09-2019 - |
質問
私の内部ループには、プロファイリングで問題があることが判明した計算が含まれています。
アイデアは、グレースケール ピクセル 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)、つまりそれは「対称」である必要があります
- 関数はスムーズであることが望ましいです。
したがって、グラフは次のようになります。
.
2 つの実装があります (結果は異なりますが、両方とも準拠しています)。
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;
}
したがって、これらの実装のいずれかに対するマイクロ最適化、または独自のより高速な独自の式のいずれかをリクエストします。
もしかしたら、あなたの中の 1 人がビットをいじることさえできるかも知れません ;)
解決
自明あなたは単にしきい値が、私は、これはあまりにも馬鹿で想像ます:
return i < 0.5 ? 0.0 : 1.0;
あなたが「増加コントラスト」を言及しているので、私は、入力値が輝度値であり、想定しています。もしそうなら、彼らは離散的である(おそらくそれは8ビットの値です)、あなたは非常に迅速にこれを行うには、ルックアップテーブルを使用することができます。
あなたの 'mulContrastizeは、' 合理的に迅速に見えます。最適化の1つは、整数演算を使用することです。さんがもう一度、あなたの入力値は、実際に[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);
他のヒント
次のことを考慮してください シグモイド- 型の関数 (目的の範囲に適切に変換):
上の図は 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はあなたのケースのために完全に正常に動作かもしれませんが、それはまた、ルックアップテーブル(またはこれを滑らかに補間に続いて2件の検索での追加費用)によって導入することができるcoursenessを回避できます。
わずか数のセグメントを使用すると、かなり良い一致を得ることができます。ここでは絶対的な色でcoursenessよりも検出することがはるかに困難になります色のグラデーションの、中coursenessがあるでしょう。
イーモンNerbonneはコメントで指摘するように、、セグメンテーションは傾きが最も変化している、つまり、「詳細を最大化するために、二次導関数のようなものに基づいてchoos [INGの]あなたのセグメンテーションポイント」によって最適化することができます。明らかに、私の投稿の例では、5つのセグメントの例真ん中に三つのセグメントを持つことは非常に詳細を追加しません。