2018/12/24

UnsharpHQのソースを見ていたのですが

僕はシャープフィルタにUnsharpHQを使っているのですが、ソースを眺めていてバグにしか見えないコードが・・・
あと、せっかく読んだの忘れないようにメモ



float giro = thres; float atanMIN = atan(0-giro/curva); //なんとなく後から/curvaを付け加えた香りがする・・・ float atanMAX = atan(256-giro/curva); float A= (MAX-MIN) / (atanMAX-atanMIN) ; float S= MIN - A*atanMIN ; giro= giro - tan(-S/A)*curva; atanMIN = atan(0-giro/curva); atanMAX = atan(256-giro/curva); A= (MAX-MIN) / (atanMAX-atanMIN) ; S= MIN - A*atanMIN ; __int16 funcion[256]; for (int i=0;i<256;i++){ funcion[i]= (__int16) A*atan( ((float)i -giro) / curva ) + S; //int16がSまでかかってないけど良いの? }

コメントは全て僕のものですが、もともコメントがあまりなくて、意図がさっぱりつかめない・・・。
というかオープンソースのソースって結構そういうものが多いですね。
僕はコメントに設計情報を入れていかないとわからなくなるのですが。そういう文化なんでしょうか?

もともとUnsharpHQはreadmeにも引数の説明があまりなく、何をしているかわからないという謎フィルタだったのですが、ソースを読んだ感じでは下記のことをしているみたいです。

■8近傍点からフィルタをかける
- - i - -
- j - k -
l - X - m
- n - o -
- - p - -

dst=org + funcion[diff] *(org-avr)/ocho;
(より正確にはdst=( org*(ocho + funcion[diff]) - avr*funcion[diff]) )/ocho;)
 orcho:重み 内部で4が使われている(以前のバージョンでは16だったらしい)
 diff=sum(|X-y|) y=i,j,k,..p
 avr=sum(y)/8 y=i,j,k,..p

■funcion[]という差分→係数の変換テーブルを持っている
これが上述した部分でfuncion[i]=A*atan((i-giro)/curv)+S;  i=0..255
 giro=thresh(フィルタオプションの)
 curv=30(内部係数→100/curvでπ付近にしたかったのかな?)
 A,S:(atanMIN,atanMAX) →(MIN,MAX)の線形写像の係数
 MIN= -SMOOTH-1;
 MAX= SHARPSTR+1;

となっています。
このfuncionが曲者で、差分が大きいほど強めにフィルタをかけるために正接関数を用いたものになっているのですが、いろいろバグがありそうです。
この強さ(というかMINとMAX)をSHARPSTRとSMOOTHのオプションで与えるようになっています。ちなみに、SMOOTHという名前は、funcionが負になるとノーマライズになるからだと思います。


ってか変数名はブラジル語? らしく、いまいちつかみづらいです。functionではないのか、とかgiroとcurvaとか。
ソースを読んでいてなるほど、と思ったのはabs(a-b)をmax(a,b)-min(a,b)で実施していること。

とかいろいろやっていて、多分元々意図してたのはこれじゃね?と思う今日この頃

giro = thres; atanMIN = atan((0-giro)/curva);            //0なので括弧でくくっても同じだけど atanMAX = atan((255-giro)/curva);        //funcionが(i-giro)/curvであることを考えると、ここも(i-giro)が正しい fncionもgiro/curvにするなら正しいが・・・ あと、255までじゃね? A= (MAX-MIN) / (atanMAX-atanMIN) ;        //(atanMIN,atanMAX)→(MIN,MAX)の傾き S= MIN - A*atanMIN ;                    //(atanMIN,atanMAX)→(MIN,MAX)のオフセット for (int ii=0;ii<8;ii++){                //i=giroでfuncionが0になるように繰り返し演算     giro= thres - tan(-S/A)*curva;        atanMIN = atan((0-giro)/curva);     atanMAX = atan((255-giro)/curva);     A= (MAX-MIN) / (atanMAX-atanMIN) ;     S= MIN - A*atanMIN ; } for (int i=0;i<256;i++){     funcion[i]  = (__int16)round( A*atan( (i -giro) / curva  ) + S );    //こっちが正しいと思う }

あと、なぜかVC2017でコンパイルしただけで1割ほど早くなった。
・・・なんで?

0 件のコメント:

コメントを投稿