04-10-2014 02:38 AM - 編集済み 04-10-2014 02:39 AM
初めまして,LabView8.5でVIを作成しております砂と申します.
早速質問なのですが,現在私は一枚の画像(4096×4096)の各画素近傍における分散値を求めるVIを作成しています.
このVIでは画像の(0,0)座標の位置の画素から処理を開始し,各画素ごとに部分配列関数を用いて近傍画素(3×3)を抽出し,そこから各画素に対する分散を求め出力します.
この部分配列関数を用いた処理に多大な時間がかかってしまい,全体の処理が終わるのに1時間以上かかってしまいます.ですので,この配列関数を他の関数や形式に置き換えることで高速化が図れると思うのですが,知識不足で解決方法が分かりません.
そこで,解決方法に関して助言をいただきたいです.
問題のVIを添付します.
解決済! 解決策の投稿を見る。
04-10-2014 03:13 AM
こんにちは。
添付VIを拝見させていただきました。
2D配列である「Image Pixels (U8)」をループの外側から配線したらいかがでしょうか。
適当な画像で試した所10秒ほどで処理出来ました。
更に高速に処理できる方法もあるかもしれませんので、ご参考までにどうぞ。
04-10-2014 09:22 AM
LabVIEWは、配列は配列のまま演算した方が効率的に処理してくれますので、
平均・分散を求めている部分を、3x3の部分2D配列のまま処理してしまうと速くなります。
一番効いたのは(=時間がかかっていたのは)、「3x3を、9要素の1Dに成形しなおしている」ところでした。
1Dに成形しなおさなくても、3x3のまま演算できるので、そのままやってみました。
当方、haljion様のダイアグラムで4096x4096の配列を処理すると、当初15.1±0.1秒(5回)かかったものが、
下のように部分2D配列のまま処理することで、6.7±0.1秒(5回)と、半分以下になりました。
なお、他にもいくつかアイテムはありますが、上記も含めて列挙すると
・「数値3」の表示を、1つ外のループに移して、外側のループのindex表示に切り替える。できれば数値3への出力自体しない。
(表示器への表示は時間がかかるがリフレッシュレート以上の速度で更新してもあまり意味がない)
・1個目の「範囲に強制(1~4094のレンジ内か)」の比較は、Forの外に出す。(中のForで毎回同じ比較をしてしまっている)
・そもそも1~4094の範囲内でcaseにするのをやめて、Loop回数は2減じれば良いことは初めから分かるので、
Loop回数を「"数値"-2」「"数値2"-2」にし、部分配列のindexの「-1」を取る。(ただし最後の配列は、縁部分が無くなります)
・3x3配列を1D配列にしていたのを、1D配列に成形するのをやめる。(これが一番効いた)
・平均と分散を求めるところでForループがあるが、配列のまま演算した方が効率良いので、Forは取ってしまって良い。
(これが二番目に効いた)
・細かいところでは、平均と分散で割り算している整数9が、2回、割り算で型キャストされていましたので(赤ドット)、
同じ数値が2回以上キャストされているならば、事前に自明にキャストして配線した方が、処理回数が減ります。
今回は、9は、初めからDBLで記述しました。これはごくごく僅かな時間短縮ですが。
などなどがあるかと思います。
04-10-2014 09:34 AM
もう1点・・・
中で平均を求めているところがありますが、もともとの2D配列が [U8] だったと思いますので、
平均を求めるために Σ で加算する前に、I16 か I32 又は DBL などに、キャストしておく必要があります。
U8の配列で加算・和を求めると、すぐにU8の範囲を超えてしまい、9ビット目以降が失われて
0~255の正しくない値しか返りませんので、先に大きなビット数の箱に入れておく必要があります。
この処理により若干時間ロスになり、当方の環境では、I32へのキャストがなければ 6.7±0.1秒(5回)
だったものが、7.8±0.1秒(5回) に、ちょっと伸びました・・・ まぁそれでも当初の半分くらい、ということで・・・
04-10-2014 11:00 PM
haljion様,M.Shiraishi様
素早い回答ありがとうございます.
M.Shiraishi様の回答を元に修正したところ,期待通りの結果が確認できました.
haljion様もありがとうございました.