この記事で扱っていること
標準関数だけでクランプ処理を行う方法
を紹介しています。
注意:すべてのエラーを確認しているわけではないので、記事の内容を実装する際には自己責任でお願いします。また、エラー配線は適当な部分があるので適宜修正してください。
LabVIEWで画像処理を行うために、有償アドオンであるVision Development Moduleを使用しなくても、画像をピクチャ表示器に表し、このピクチャに対する操作と配列関数を組み合わせることで、いくつかの画像解析処理を実現することができます。
今回の記事では、クランプ処理を扱っています。
このクランプ処理とは、ユーザーが指定した「対象領域」(関心領域)内の左右あるいは上下方向で最も広い間隔がどれくらいになるかを測定する処理となります。
どんな結果になるか
フロントパネルには2Dピクチャ表示器と、画像ファイルを指定するファイルパス制御器、対象を指定するための四角を表示する際の色、エッジを識別するためのピクセル値のしきい値設定用の数値制御器、そして測定された距離の表示器があります。

プログラム実行後、画像ファイルを選択し、画像上で対象としたい領域を囲むことで、その領域の左右で最も広い間隔を検出してその間の間隔を測ります。
’(フロントパネルで指定するペンカラーは、領域を指定する時の色です。また、下の図で書かれている青い矢印は実際には表示されません)

プログラムの構造
ピクチャに対して四角を描画するための処理はマウスダウンやマウス移動、マウスアップ等を組み合わせるため最初から組むのは少し面倒です。
そこで、既に欲しい機能がある程度揃っている、サンプルファインダの「ペン属性と画像サブセット」サンプルをコピペし、必要な機能を追加、不必要な機能を削除することでより手軽に実装できるようになります。

プログラムの構造としては、イベントが7つあるものの、大部分はサンプルのままかあるいはサンプルの機能で特に使わないものを一部削除することで書けます。

それぞれのイベントの中身は以下の通りです。
まず、ピクチャのマウスダウンイベントです。
サンプルでは動作に応じていくつかの機能がありますが、今回はマウスを動かして行うことといえば領域を指定するくらいのことしかしないので、Move Pen.viを実行するのみとしています。

次にピクチャのマウス移動イベントです。
サンプルでいうところの「長方形を描画」するためのケース「3」を実行するだけとなります。
この長方形が、領域指定の枠組みとなります。

次にピクチャのマウスアップイベントです。
ここだけサンプルと大きく異なり、新たにサブVIを二つ設けています。
片方はエッジを探すためのfind_edge.viで、もう片方はその情報を基に線(端を示す赤い線)を引くための処理を行うdraw_lines.viです。

find_edge.viでは、ユーザーが長方形として指定した対象領域の中で、水平方向に対して左から右へ、および右から左へ、「エッジ」を探していきます。
ここでいう「エッジ」とは、画像全体から色情報をとって(下の図ではRGBのうちRの成分を選択)これを部分配列で対象領域だけの配列とし、Forループで対象領域(ピクセル値の2次元配列)の各行に対して、一定のしきい値(edge factor)を初めて下回ったときの列の値(Forループの反復端子値)を指します。
あとは例えば左から右へ調べる場合に各行ごとにこれを調べて全行を調べたら、その中で一番小さい値(一番左側の列の値)を配列最大最小の関数で見つけて、これを関心領域の左側の値に足せば、画像全体に対してどこに線を引けばいいかという情報をleft edgeとして得られます。
右から左へ調べるときにも同じ要領(ただしこの場合には関心領域の右側の値から引く)で処理します。

ただ、この方法だと「左から右へ」エッジを調べる場合反復端子の値-1とすることで、後で線を描画する際にエッジを境界部分に表示することができます。
以下の図に載せていますが、真ん中の結果が左も右もエッジ部分に赤線を引けているのでこれを採用しています。

もう一つのサブVIであるdraw_lines.viでは上で得られたエッジ情報を基に線を引いています。

メインVIの続きに入ります。
といってもほとんどはサンプルを少し修正するだけです。
次のイベントはピクチャのマウス境界外イベントです。
マウスカーソルの形を通常の状態に戻します。

ピクチャのマウス境界内イベントではマウスの形を22と指定しています。
これは、長方形を描画できることを表す表示として指定しています(が、別に他の表示にしても全く問題ありません)。

停止の値変更イベントではイベントストラクチャを終了します。

最後、サンプルに追加して、ファイルパスの値変更イベントです。
ファイルパスから拡張子の情報を抜き出し、グラフィック&サウンドの関数パレットのグラフィック形式パレットにある、各画像ファイルを読み取る関数を使用して、画像データを抜き出し、これを使ってピックスマップ(ピクチャ)に表示できる形式としています。

上下に対して間隔を求める場合
上で紹介したプログラムでは、左右方向に対する処理を行っていましたが、上下方向に調べたい場合にはサブVIの処理の一部を変更する必要があります。

変更する部分としては、ピクチャのマウスアップイベントで使用するサブVI、find_edge.viとなります。
このサブVIには、holizontal ?というブール制御器をつけることで、水平方向の処理なのか垂直方向の処理なのかを指定できるようにしています。

find_edge.viを修正した、find_edge adv.viの中身は以下のようにしています。
水平、垂直の切り替えは、ピクチャを2次元配列にしてしまえば、その配列を転置するかどうかで行えるので、この判断をholizontal ?で行わせています。

draw_lines.viも内容を修正します。
修正した、draw_lines adv.viの中身は以下のようにしており、前段のfind_edge adv.viの結果を受けて正しく線を引けるようにしてやります。

本記事では、標準関数だけでクランプ処理を行う方法を紹介しました。
都合上、距離は何ピクセル分で表すことになるため必ず整数値になりますし、現実世界の距離の単位ではないのですが、比較的簡単に距離を測るための方法としては参考にしてもらえるかなと思います。
ここまで読んでいただきありがとうございました。

コメント