大津の手法による閾値自動決定アルゴリズムを用いた二値化をGPUを用いて実装しました

Boltzmanです. 前回の記事から1か月以上が経過しました. 極めて難航しましたが, 進捗が上がりましたので記事にします. (遅すぎ)

前回, 大津の手法による自動閾値決定2値化アルゴリズムをCPUで実装してあまりにも重くなったため, GPUを用いて, 具体的にはComputeShaderを用いて実装しました.
実行環境は私のノートPC(Intel Core i5-5200U/RAM 4.00GB/Intel HD Graphics 5500)です. 決して良いとは言えないスペック.
実行結果は
CPUのみで実装   (v0.1.0):MonoBehaviourが平均330msくらい
GPUを取り入れて実装(v0.2.3):Gfx.WaitForPresentが平均16~20msくらい?(ガタつきが多い)

プロファイル比較

改めてこうしてみるとCPUのみで実装したほうが理不尽に重いので, どこかでコーディングミスをしている可能性が大いにあります.

また大津の手法による自動閾値決定により2値化画像がどのように変化するかが以下です.

大津の手法結果

上を見るとわかる通り, マーカーは濃淡の変化が顕著になるように作られているためか, あまり見栄えは変わりません.
しかしその他の背景画像は大津の手法を実装したときのほうが見やすくなっています.

以下にComputeShaderのコードを記載します

前回からの変更点としては,
・大津の手法の計算と最大値算出にScanを使用した
(参考URL:http://http.developer.nvidia.com/GPUGems3/gpugems3_ch39.html)
・ヒストグラムの生成時にSharedMemoryを利用してアクセスの集中を軽減した
(参考URL:https://devblogs.nvidia.com/parallelforall/gpu-pro-tip-fast-histograms-using-shared-atomics-maxwell/)
といった感じです.
参考元はNvidiaなのでCUDAで書いてありますが, 実装はHLSLで行いました.

いずれもまだまだ最適には程遠いかと思います.
もう少し実行速度が安定するまでコードを練るか, それともGPUを用いたラベリングの実装に移るか少し迷っています.

あと魚眼レンズはまだまだ遠いので一度置いておこうと思います.
そもそも魚眼レンズから取得したゆがんだ画像からマーカーを検出できるのかという問題を一切考えていないのでできる保証はないです.
次回はどちらになるでしょうか…
それではまた.

Posted on