標準関数だけで画像分割、保存 | マーブルルール

標準関数だけで画像分割、保存

Tips

スポンサーリンク

この記事で扱っていること

  • 標準関数だけで画像分割、保存を行う方法

を紹介しています。

LabVIEWの標準関数で画像を取り扱う場合にはピクチャ形式のデータを使用します。

ピクチャは2D配列に変換できるので、画像を分割するとはつまり2D配列の操作を行うことになります。

ただし単に分割をするだけではなく、分割後のイメージを表示させるようにピクチャ上に分割線を表示する等の仕組みを作るとなると少し話は複雑になります。

本記事ではそんなピクチャの操作含めた画像分割および分割した画像の保存プログラムの例を紹介しています。

スポンサーリンク

どんな結果になるか

フロントパネルには、画像分割に必要なパラメータである、分割領域のサイズ、位置、分割モードの選択および保存先パスの情報を入力できる制御器とピクチャ表示器を付けています。

プログラムを実行して画像を選択すると、その画像のサイズに合うようにピクチャ表示器の大きさが変化します。

そして、有限の大きさの枠サイズを指定すると指定した色で枠を表示させることができ、この縦、横位置を操作できます。

分割指定の列挙体で既定の分割数を選ぶあるいは任意の分割数で指定することで枠を縦横に分割することができ、保存先パスをファイル名含めて指定して保存ボタンを押すと、分割した画像を保存できます。

例えば以下の図では横方向に4つ縦方向に2つという分割を指定して画像に赤い枠で分割時の各枠を示しており、この状態で保存することで分割した画像を4×2の8枚の画像として出力することができます。

プログラムの構造

ユーザーのボタン操作に反応して逐次決まった処理をする、ということで、イベント駆動のステートマシンで組むのが簡単です。

各イベントで使用するデータクラスタは以下の図のWhileループ左側のクラスタ定数を参考にしてください。

それでは各ステートの中身を紹介していきます。

まずinitステートでは、フロントパネルの制御器とクラスタのデータを初期化しています。

初期化時の定数は以下の図の通りでなくてもいいですが、制御器の初期化(ローカル変数で行っている部分)とクラスタデータの初期化には同じ値を配線するようにします。

initステートの後はeventステートに移ります。

次にeventステートです。

イベントストラクチャを配置して、ユーザーからの入力に対して応答するようにしています。

ほとんどのイベントでは、次に進むステートを決めるだけです。

ピクチャ倍率はこのイベント内でササっと変えるので、次にまたeventステートに戻るようにしています。

少し厄介なのは、読み込む画像(ブールボタン)の値変更イベントです。

以下の図で示したこのイベントに対する内容は、別の専用ステートを作ってその中に盛り込むようにしてもかまいません。

次はshow pictureステートです。

2Dピクチャの表示器に「分割後」の画像を表示させます。

他のいくつかのステートからこのステートを実行することになります。

change frame conditionステートでは、画像上に枠組みを表示するための様々な操作を詰め込んでいます。

見た目は一つのサブVIを配置しているだけのシンプルなものです。

サブVIであるframe position.viの中身は以下の図のようなものです。

まずは分割情報を更新しています。

列挙体で指定した分割数に合わせて、分割数指定縦と分割数指定横の値を更新しています。

次に、指定した枠組みの縦と横の大きさを分割したい数で割って、「割り切れる数」にサイズを強制しています。

例えば枠組みの縦サイズが150の場合、分割数指定横(縦ではないことに注意)が5であれば割り切れるのでサイズは150のままですが、指定数が7の場合には割り切れないので、割り切れる中で150を超えない大きさである147に強制されます。

サブVIの後半では、実際に各パラメータを使用して枠組みの分割線を作っています。

細かい説明は省きますが、やっていることは単純で、縦と横それぞれに分割指定のパラメータに沿ってラインを描いていきます。

縦、横の扱いがややこしいので、以下の図を参考にそのまま書いてもらうのがいいかなと思います。

メインのVIに戻って、次はsaveステートです。

単純に画像を保存すればいいだけ、ではなく、画像を分割する処理を入れる必要があるので、これも全ての処理をサブVIに詰め込んでいます。

サブVIであるsave divided image.viの中身は以下の通りです。

画像に分割線を書くプログラムと近しいことをしていますが、画像を2D配列としてこれを操作していくことになるので2重構造のForループを使用して部分配列で切り出していきます。

最後にfinishステートです。

ステートマシンのWhileループを止めます。

ズーム係数に合わせて枠の大きさも変える場合

上のプログラムでは、ズーム倍率を変更して大きいピクチャもウィンドウの枠に収まるようにしていましたが、ピクチャ表示器自体の大きさは変えていませんでした。

そのため、ズーム倍率を変えると確かに表示されている画像の大きさは変化しますが、例えば縮小表示した場合には余白が表れることになります。

これに対応しようとして、ピクチャの描画領域を読み取って、これにズーム倍率を掛けて描画領域プロパティにその結果を渡す場合、問題が起きます。

それは、ズーム倍率を変更するたびに、前の描画領域の大きさを参照するため、例えばズーム倍率を0.8、0.7、0.6などと順に切り替えると、表示される画像がどんどん小さくなります。

これを回避するためには、ズーム倍率が1のときの描画領域の値をクラスタに入れて保存しておくという方法があります。

クラスタをタイプ定義している場合にはタイプ定義の中身を編集し、以下のようにすることでうまく処理できるようになります。

本記事では、標準関数だけで画像分割、保存を行う方法を紹介しました。

画像を配列として扱う操作と、ピクチャ上に分割の様子を表示させる仕組みは慣れが必要でそもそもメンドクサイので、近いニーズがあったときにこのプログラム通りに組んで面倒なことはさっさと終わらせられるような役に立てばうれしいです。

ここまで読んでいただきありがとうございました。

コメント

タイトルとURLをコピーしました