
前回に引き続き、Turbo Delphi で Rinkaku Application をつくる、の5回目。
今回は、一次微分と二次微分によるエッジ検出フィルタを組み合わせ、
このアプリの中心となる Rinkaku() フィルタをつくる。
Rinkaku() フィルタは、一次微分と二次微分によるエッジ検出結果の
相乗平均によってつくる。これまでに、一次微分として
Contour3()
Contour4()
SobelInvert()
二次微分として
Edge3()
Edge4()
をつくった。したがって、組み合わせの数は6通りある。いろいろ試して、
微妙な違いから、今回は SobelInvert() と Edge4() の組み合わせを採用
することにした。
前回つくった RinkakuUtils.pas に以下の関数を追加する。
function Rinkaku(var bmp: TBitmap; factor: double): Boolean; var tmp:TBitmap; w, h, x, y,i: integer; src, dst: TBmpData8; ct, ed, v: double; ff: array[0..255] of double; begin result := false; if bmp.PixelFormat <> pf24bit then exit; w := bmp.Width; h := bmp.Height; for i := 0 to 255 do ff[i] := factor * Sin(i * PI / 160.0); tmp := BmpClone(bmp); //Edge3(tmp, true); Edge4(tmp, true); HistoStretch(tmp); //Contour3(bmp, true); //Contour4(bmp, true); SobelInvert(bmp, true); src := TBmpData8.Create(tmp); dst := TBmpData8.Create(bmp); for y := 0 to h-1 do for x := 0 to w-1 do begin ed := 255 - src[x, y]^; ct := 255 - dst[x, y]^; v := Sqrt(ed * ct); v := v - ff[Trunc(v)]; dst[x, y]^ := AdjustByte(255 - v); end; dst.Free; src.Free; tmp.Free; result := true; end;
ここで、二番目の引数 factor は、Sine 関数をつかった S 字型のノイズ除去
フィルタの強度であり、0から40までの値を設定できる。実際に、この factor を
変えてみた結果を以下にしめす。なお、以下の結果は同じだけコントラストを調整
したものだ。
factor = 0 (S字型ノイズ除去なし)

factor = 10

factor = 20

factor = 30

S字型ノイズ除去は強力である。しかし、髪のディテールなど、失う情報もある。
元画像の質に依存して、factor を試行錯誤で決めなくてはならない。
テストコードを以下にしめす。
uses VCLImageUtils, RinkakuUtils, Clipbrd; procedure TForm1.Button1Click(Sender: TObject); var bmp: TBitmap; begin bmp := LoadPng('C:\Home\ImgWork\RaceQueen.png'); if not Assigned(bmp) then exit; bmp.PixelFormat := pf24bit; //Median(bmp); if Rinkaku(bmp, 30) then begin Canvas.Draw(5, 35, bmp); Clipboard.Assign(bmp); end; bmp.Free; end;
かなり、それらしくなってきた。しかし、まだノイズの除去は十分ではない。
これ以降は、ノイズとの戦いである。次回では、まず最初にコントラスト調整
を行うフィルタを作成する。