LabVIEWでプログラムを書くときの強みの一つは、ユーザーインタフェースであるフロントパネルをドラッグアンドドロップの操作だけで簡単に構築することができることだと思います。
本ブログのまずこれのシリーズでは主にプログラムのアルゴリズムの部分の書き方について解説してきましたが、アルゴリズムを知っているだけではプログラムは書けず、どのような選択肢があるかということも知っておく必要があります。
使い方集は、まずこれのシリーズでステートマシンまでの知識はある程度知っている前提で、アルゴリズム以外に関わるプログラムの書き方について紹介するシリーズです。
本記事ではLabVIEWの標準関数(特別なアドオンをインストールしていなくてもLabVIEW単体で使用できる関数)で画像を扱う2Dピクチャについて紹介しています。
画像はピクセル値の集まり
LabVIEWで画像を操作する基本は、画像を2次元配列化してこの配列に対し必要な処理を行うことになります。
そもそもどんな画像も、細かく見れば色の集まりとなっていてそれら一つ一つをピクセルと呼んでおり、そういったピクセル値の集まりが縦と横にびっしり広がっているだけなので、画像の実態は(2次元)配列そのものと言えます。
例えば、後で紹介する画像を2次元配列に変換する関数を使用した結果として得られる2次元配列は、その要素の一つ一つは単色しかもたず、これらが縦横にびっしり並んでいることで全体的な画像を構成していることがわかります。

LabVIEWで色について表現するには、カラーボックスという数値制御器(あるいは表示器)があります。
これが数値制御器になっているのは、色をR(赤)、G(緑)、B(青)の3色それぞれを0~255の256段階で表しているからであって、扱うデータタイプもこれら3色をぜんぶひっくるめて表すためにU32のデータタイプとなっています。
なお、一つの色は256段階ですが、これは16進数にて00~FFで記述します。

実際に色を指定する際には、専用の関数を使用してU32のデータタイプに変換するのがわかりやすかったりします。
R、G、Bそれぞれの値を決めるだけでU32のデータとして出力してくれます。

これらの組み合わせにより、RGBフルカラーを表現することができます。
例えば、以下の図のようなカラーバーを2Dピクチャの上に表示させることもできます。

さらっと出しましたが、配列を画像に変換させた上記の例では、画像をピクチャ表示器に表すために以下の関数を使用しています。

こちらで画像をピクチャに表すことができますが、これはあくまでLabVIEW上に表示しているにすぎません。実際は、ピクチャに表した画像を、画像ファイルに出力させることもできます。
例えば、以下のようなプログラムを組むことで、指定したパスにmytestimage.pngという画像ファイルとして出力させることができます。

なお、ピクチャは「重ねる」ことができます。
ピクチャに関する操作を行う関数の多くは、ピクチャ制御器あるいはピクチャ定数を入力することができ、その関数の処理の結果をその入力されたピクチャに重ねて表します。(入力がない場合には空のピクチャが入力されているものとみなされ処理されます)
言い換えれば、場合によっては入力ピクチャの情報が隠れてしまうことになります。

特定の場所に上書きしたいという場合には、そもそもの画像の描画開始位置をずらすこともできます。
以下の図の赤枠の指定は、描画領域の左上のX、Y座標の指定を行っていて、デフォルトだと(0,0)になっている値ですが、これを変更することで位置をずらせます。

扱える画像ファイルの種類
配列として画像に対する処理を加えるのはいいとして、では画像をどのように配列にするか、ですが、専用の関数があります。
ただ、この専用の関数を使用するさらに前の段階として、まずはLabVIEWに画像を取り込む必要があります。
標準関数として、LabVIEWでは3種類の画像ファイル、jpeg、png、bmpを読み込むことができます。
これらの操作を行う関数は、先ほど画像ファイルに出力した関数と対になっています。

これらで読み込んだら、次に配列に変換していきます。
配列に変換する際には、その画像の「深度」によってどの出力が得られるかが決まります。
深度としては24ビット、8ビット、4ビット、1ビットの4通りがあります。ここでは、比較的よく使うであろう24ビットと8ビットを例に出します。
まず、24ビットは、カラー画像を使用するのに使います。RGBそれぞれで8ビットずつ(0~255)であることは既に紹介したとおりです。

次に8ビットですが、これはグレースケール画像を扱う際に使用することができるのですが、グレースケール以外の画像も扱える、という点に少し注意が必要です。
画像を読み込む際に「色」の指定を行うことができ、ここで0~255の256階層それぞれの色を指定することができます。
つまり、8ビットピックスマップの場合には、配列の要素としてはU8であり0~255になっていますが、その256個の要素それぞれがどの色を表すかを指定できるというわけです。
なので、8ビットピックスマップとしては同じ配列を与えたとしても、「色」の指定を変えれば異なる結果を得られます。

単純にグレースケール画像として表したい場合に、ちゃんと色を指定する必要があります。

また、画像読み込み時にはマスクの指定も行うことができます。
このマスクの指定は少しややこしく、U8の配列で指定するのですが、「配列の最初の要素のU8では8ビット分のマスクの有無を決めて、次の要素のU8ではその次の8ビット分のマスクの有無を決める」ということを繰り返します。
分かりにくいと思うので、具体的な例で説明するために、以下のようなプログラムを考えます。
こちらのプログラムでは、元々のピクチャに重ね書きして全体が赤のピクチャを置いています。
なので「マスク後」のピクチャは真っ赤になっています。

このとき、マスクとしている全体が赤のピクチャに対しmask配列を指定することで、どの部分をマスクとしてどの部分をマスクしないかを決められます。
ここでいう、「マスクしない」とは、赤の領域ではなくなり透明となることで背景が表れる状態のことです。
mask配列の要素0はピクチャの左上から左方向に8ピクセル分に対して、どのピクセルをマスクしどの部分をマスクしないかを決め、要素1では次の8ピクセル分に対して決めます。

実際にmask配列を指定した場合の例をいくつか以下で紹介します。

mask配列を増やすほど、次の8ピクセル分、次の8ピクセル分、とマスクを指定できる領域が増えていきます。

ピクチャ関数の組み合わせ方
画像の取り込み方もわかれば、あとは配列を操作して自由に画像処理ができる・・・とはいえ、配列操作をがちゃがちゃやっていくのは結構大変です。
実際配列操作を行う必要がある場面も多々あると思いますが、配列操作をせずともできる処理があるので、それらについて紹介していきます。
まずは、画像をマスクの処理です。
「え、さっきマスクの処理扱ったよね?」と思われそうですが、こちらについては色を指定してその色の部分を透明にすることができるので、操作感が違います。
例によって、下絵と、そこにわざと別のピクチャを重ねている状態を基にして示してみます。

マスク作成の関数はピクチャ関数のパレットにあります。
注意点として、この関数はピクチャの入力ではなく、画像データ(クラスタ)を配線する必要があり、「透明にしたい」色を入力します。

透明にしたい色を切り替えることで、任意の部分を隠したり表したりできるようになります。
また、下の図では一色ずつしか透明にしていませんが、複数の色を透明にするように指定することもできます。

次に、描画のための関数です。ピクチャに対して、丸や四角などといった基本図形を描画していく処理になります。

これらの関数には、描画位置の座標情報を指定することになります。
絶対位置での指定以外に相対位置での座標指定を行うことができる場合もありますが、これらの関数を駆使して自由に描画するのは結構大変です。

その気になれば、星を描画することもできます。

もっと気軽に図形の描画ができないの?という方には、LabVIEWのサンプルファインダのサンプルが役に立つと思います。
実際、私のブログで紹介しているプログラム例でも、この「ペン属性と画像サブセット」のサンプルをベースにしているパターンが結構あります。
ペイントのアプリケーションのようにマウス操作をした場所に点や線を描画するにはこのサンプルが一番手っ取り早いです。

プロパティノードを使用した便利な実装
ピクチャ上に画像を表現する際の便利なテクニックを紹介します。
画像のサイズを変更
まずは画像サイズを変更してピクチャに表示する方法です。
これには、ピクチャのプロパティノードにズーム倍率というプロパティがあるのでこちらを使用します。

ピクチャの幅を画像に合わせる
次に、ピクチャの表示器を画像のサイズに合わせる方法です。
ピクチャ表示器は、そのままでは画像のサイズと無関係に表示されます。
そのため、場合によっては画像を全て表示しきれていなかったり、あるいは画像を表示している以外の部分で余白が出てしまうことがありえます。
こちらもプロパティノードを使用して画像サイズを合わせることができます。

もしズームもさせつつピクチャ表示器の枠も合わせたければ、上記二つを組み合わせることになります。

ピクチャ以外で画像を扱う
本記事で紹介する主眼はピクチャの扱い方ですが、LabVIEWで画像を扱う際により高度な処理を行いたい場合には、画像を扱うための専用のアドオンソフトであるVision Development Moduleを使用します。
似たアドオンにVision Acquisition Softwareというものがあり、どちらもVisionというだけあって画像を扱うのに使用するアドオンとなっています。
違いとしては、Vision Development Moduleはいわゆるマシンビジョンと呼ばれる画像処理に特化した処理を実装できるのに対してVision Acquisition Softwareは画像を取得する側、つまりカメラの操作を行うためのものとなっています。
もし興味があるよという方は以下の記事も参考になると思います(ただしVision Development ModuleもVision Acquisition Softwareも有償ソフトなので注意)
「じゃあVision Development Moduleがないと画像解析はできないの?」と思われるかもしれませんが、いえいえ、効率(実装の手間やプログラムの処理時間など)を考えなければ、いくつかの処理は実装できます。
冒頭でも書いたように、所詮は画像なんて色の情報が集まった2次元配列なので、配列操作の関数を中心にプログラムを書いていけばある程度のことは実装できます。
配列操作に関して具体例を挙げている記事もあるので参考にしてみてください。
本記事では、LabVIEWにおける標準関数だけで画像を扱うためのピクチャ関数について紹介しました。
ユーザーが線や点を描画するのはもちろん画像ファイルの中身を取り込むこともできるので、ピクチャ関数の使い方を覚えておくと、LabVIEWで作れるアプリケーションの幅がぐっと広がると思います。この記事で紹介した内容が少しでも参考になればうれしいです。
ここまで読んでいただきありがとうございました。
コメント