画像情報処理テキスト
(最終改訂
2016/03/02)
実験の目的 画像データはコンピュータでビデオカードにより表示されるとき、1 画素ごとに R,G,B の光の三原色 のデータが指定され、例えば1680×1050 画素で各色 8 ビット(自然 2 進表現で 0~255)を割当てれ ば5.05MiB(1MiB=220 B)を必要とする。ファイルに保存する場合、実際の画像では空間周波数分析 とハフマン符号化により殆ど品位を損なわないで圧縮が可能であり、コンパクトデジタルカメラの画像 保存等に用いられるJPEG 画像は 1/4~1/20 程度に圧縮されている。 ここでは画像の圧縮については扱わず、カラー画像の各画素に対しての簡単な演算により結果がどの 様に変化するかをLabVIEW のプログラムを作成して確認し、画像の表現と処理に対する理解を深める ことを目的とする。日常目にするカラー画像も、X 線写真などのモノクローム画像を濃度に応じて異な る色に割付けたり(pseudo color)、赤外バンドに可視光を対応させるなど本来の波長とは別の波長の色 を割付けたり(false color)画像処理がなされていて実際の色調とは異なるものも珍しくない。デジタ ルカメラのJPEG 画像も、CCD/CMOS センサーの出力に輪郭強調、コントラスト調整、ホワイトバラ ンス(ミラーレス一眼ではレンズの周辺減光、歪曲収差、倍率色収差の補正も)などの演算を行った結 果であり、決してセンサーに入力された三原色の強度に応じた画素データそのものではない。 注意 本テキストでは実験を行う上で必要な項目について記述しており、画像処理の詳細については画像関 係の教科書に譲る。LabVIEW の概要については、情報学実験Ⅰ課題④「LabVIEW による論理回路」 (以下「課題Ⅰ④」という。)のテキスト(以下「Ⅰ④テキスト」といい、他の課題テキストについて も同様に略記する。)を参照のこと。課題Ⅰ④で見た通り、情報科学研究教育センターのPC では、Virtual Desktop と Local PC とで OS のフォント設定(ユーザには設定できない)が異なるため、LabVIEW の ソースプログラムVI(Virtual Instrument、拡張子.vi)を作成時の OS と実行時の OS とが異なる場合、 部品配置がずれる他、設定した枠から文字が溢れたり過剰な余白を生じたりする(LV_sample2.zip 中 の実行プログラムはそれぞれの表示に合せている)。何れの OS でログインしてもよいが、必ず同一の OS で作業を続け、作業中に OS を変更しないこと。本テキストの図および説明文はVirtual Desktop の環境に基づいている。 実験ノート以外に用意するもの USB メモリ(処理対象画像、キャプチャ画像、LabVIEW ソースプログラム等の保存に使用) 事前準備 必ず、本テキストに最後まで目を通して、全体の作業の流れを把握しておく。各自が撮影もしくは自 作のプログラムで生成した、または著作権の問題の無い画像を256×256 画素に整形した JPEG 画像フ ァイルを USB メモリに保存しておくこと。処理パラメータを変えたときリアルタイムに結果が反映さ れる実行速度を考慮してこのサイズとするので、事前にIrfanView などのソフトウェアを用いてクロッ プ、リサイズしておく。情報学実験のページからLV_sample2.zip をダウンロードして USB メモリに 保存しておくこと。本課題は課題Ⅰ④とは異なり、課題の全作業を事前に行うことが可能である。 使用機器 情報科学研究教育センターPC 【作業の途中でOS を変更しないこと】使用ソフトウェア LabVIEW(現在の版は 2013) 表紙交付基準 以下の事項について全てが完成したことを確認して表紙を交付する。レポート作成については、実験 手順中の記述の他、本テキスト末尾の備考p.15「レポート作成について」を参照のこと。 テキスト本文解説および備考pp. 15-21「その他の処理例」に掲げたコードを変数名、係数の変更等 を含め本質的に同一な形で使用したものには表紙を交付しない。 ● 行う画像処理の内容とアルゴリズム(「適当に式を書いたらこんな処理になっている」ではなく、「ど の様な処理を行う目的でアルゴリズムを組立てたか」を明確に記述すること)【実験ノートで確認する】 ● フォーミュラノード内のコード【実験ノートまたはテキストファイルを PC 画面で確認する】 ● 作成した LabVIEW VI の動作【所期の処理を行うことをPC で確認する】 画像データについて 加色混合に用いる光の三原色は、波長の長い方から赤、緑、青でR,G,B と略記する。図 1 に示す様に、 各色8 ビットの 24 ビットの画素データは全体を符号無整数と見たときの上位からこの順に並んでいる がアドレスでは逆順になる(註)。PC の演算対象に 24 ビットのデータ型は無いため、最上位 8 ビット が無駄になるがLabVIEW では 32 ビット符号無整数(uInt32 型)に 1 画素の情報を格納する。 図1 画素情報と LabVIEW で使用するデータタイプ 註:アドレス単位よりもデータ幅が長い場合、データ中には複数のアドレスが存在するが、当該データ を識別するアドレスは単一でデータ中のアドレスの内で最小のもの(図1 でa)である。データを符号 無整数(自然2 進)と見たとき、このアドレスがデータ中の最下位を示すもの(little endian)と最上 位を示すもの(big endian)とがあり、PC は前者に該当する。 画素に対して演算を施すには、例えばP を画素データとするとき図 2 上の様にシフト、マスクのビッ ト演算によりR,G,B 各色のデータを抽出し 8 ビット符号無整数(uInt8 型)として扱い、各色に対して 必要な処理をした上で、図2 下の様にシフト等で再構成すればよい(註)。 図2 画素データから各色の抽出(上)、各色から画素データの構成(下)
註:LabVIEW では、”<<”は真のビットシフト演算ではなく本来の結果が (7FFFFFFF)16 を超える場合 は 0 となるので、論理的には正しい B=(P<<24)>>24; で正しい結果を得られない。また、あふれを無 視する通常の整数乗算ではなく、あふれを生じた結果は (FFFFFFFF)16 となるので 2 の冪乗の乗除で シフトするB=(P*2**24)/2**24;も正しい結果を与えない。A を符号付整数とするとき、旧版では A が 負の場合にもA&0xFF で 256 を法とした合同演算を行えたが LabVIEW2013 では A が負の場合には 0 となる等、版による違いも多く注意を要する。
図3 左は R,G,B とそれぞれの補色 C (cyan) , M (magenta) , Y (yellow) に白と黒を加えた 8 色の矩形 を、どの色の矩形も他の7 色すべての矩形と隣接する様に配置した画像の例である。図 3 右は、これを 256×256 画素のビットマップイメージとして作成したファイルの先頭部分(ヘッダ 54 バイトおよび画 像左下の最初から96 画素分の 288 バイトの計 342 バイト)をバイナリエディタ TSXBIN(Ⅰ⑦テキス ト p.21 参照)で表示したものである。ファイル内の各画素データは、画像のラインが下から上へ(ヘ ッダで高さを負に設定した場合は上から下)、 ライン内では左から右の順に格納されている。 図3 ビットマップ画像(左)とバイナリエディタで表示した画素データ(右) 図3 右のシアン枠内の 96 バイトが、図 3 左下ライン中の青の区間 32 画素の色データを示すが、バイ ナリエディタで左側(アドレスが若い)はデータ中では下位バイトとなり、”FF 00 00” は (0000FF)16 を意味し赤ではなく、青であることに注意する。 圧縮の影響について 画像は圧縮することでファイルサイズを小さくすることができるが、非可逆圧縮(不可逆圧縮)では 画像の性質により画像の品位が著しく損なわれる場合がある。p.4 図 4 は、LV_sample2.zip 中の画素デ ータ表示プログラム(以下「Pixel_data」と言う。両ログイン OS に対応する実行プログラムはそれぞ れPixel_data_VDT.exe、Pixel_data_LPC.exe である)に同梱の test.bmp(図 3 左の画像)、test.jpg (test.bmp を IrfanView の既定パラメータで JPEG 圧縮したもの)を読込んで、赤の矩形が黒・マゼ ンタの矩形と隣接している箇所を約50 倍に拡大した例である。色差を間引く JPEG 圧縮は自然物の写 真では効果的な圧縮ができるが、幾何学模様等は苦手とする。特に赤は泣き所で(黒が背景の赤の格子 線は悲惨な結果になる)、これを確かめることができる。
図4 ビットマップ画像とこれを圧縮した JPEG 画像の対応する画素値の比較
PC の画面キャプチャの保存では、同じ非可逆圧縮でも JPEG ではなく PNG による圧縮を使用すべ きである(Pixel_data で同梱の test.png を読込んで図 4 と比較しなさい)。Pixel_data は、拡張子 が .bmp、.jpg、.png の何れかでサイズが 256×256 の画像ファイルを読込み、カーソル(画像に応じ てトグルSW で白黒を含む 8 色を選択する。図 4 の例では黒カーソル)で指定した画素の色データを表 示する。画像のサイズが256×256 とは異なる場合、画像の左上を合せるのでサイズが大きな場合は原 画像の左上256×256 画素が対象となり、また小さな場合は空いた右下に黒画素(値 0x00)が詰められ る。右側の拡大画面のカーソルはトグルSW で白または黒を選ぶ (図 4 では白を選択)。 ディスプレイの輝度について 課題Ⅱ⑥で学修した通り、PC の画面表示はガンマ補正されたもので、その物理的な輝度(SI 単位系 の単位は cd/m2)は画素データ中の色の数値に比例するものではない。本格的な計測装置が無くとも LV_sample2.zip 中の色設定プログラム(以下「RGB_setting」と言う。両ログイン OS に対応する実行 プログラムはそれぞれRGB_setting_VDT.exe、RGB_setting_LPC.exe である)で設定した画面をデジ タルカメラで覗き(シャッターボタン半押しで撮影する必要は無い)、画面設定を変えてカメラの絞り、 シャッター速度、ISO 感度の表示を読取ることで容易に確認できる。 RGB_setting は、課題Ⅱ⑥の「3-3 色設定された液晶ディスプレイの観察」での利用を想定している。 R, G, B 各色に対応する垂直スライド(これが既定の画素データ入力手段で、各色の値が 0 または 255 である実験項目①~⑥の設定に適している。分光器で画面をのぞきながらディスプレイの色を変更して リアルタイムの観察を行う場合にもこちらを使用する)または数値入力ボックス(各色を任意に設定す る⑦の設定に適している。入力手段の垂直スライドとの切替はボックスとスライドの間の垂直トグル SW で行う)で設定した色を枠内に表示する。 設定された色は、表示枠上のSAVE ボタン( )のクリックで1680×1050 画素(表示枠のサイズ ではなく、演習室PC のデスクトップサイズ)の画像ファイルとして保存できるので保存したファイル をペイントで開き、F11 を押下してタイトルバー、ウンイドウ枠の無い全画面表示にすれば、ディスプ レイの全画素を指定の色に設定できる。ファイル名は各色の 16 進数値を連結した rrggbb に拡張 子 .bmp または .png(SAVE ボタン左の水平トグル SW で選択する。既定は .png:p.5 註参照)が付 く(p.5 図 5 の例では 562870.png)。保存先を指定するプロンプトは無く、RGB_setting の実行ファイ ルが置かれたフォルダに保存される。このフォルダに既に同名のファイル(同色で拡張子も同じ)が存 在する場合はSAVE 操作を無視する(上書しない)。
図5 RGB_setting のフロントパネル 註:RGB_setting の出力画像や test.bmp の様に規則的で色数の限られた画像では、PNG 圧縮により失 われる情報は無い。したがってRGB_setting では敢えて非圧縮の .bmp(約 5.3MiB)で保存する利益 は無いが、任意の色に設定して保存したファイルをバイナリエディタで表示する興味のため、.bmp で の保存オプションを設けている。同梱の562870.png を Pixel_data で表示して画像の周辺も内部も正し い色で保存されていることを確認することができる(図6)。 図6 同一色から成る画像は PNG 圧縮で正しく保存されている スクロールバーを右に移動し、表示枠右上の水平トグルSW を RGB(既定)から xyY に切替えると、 p.6 図 7 に示す様に色のパラメータを RGB ではなく xyY で入力できる(sample フォルダ内の例を参照)。 xyY から求めた R,G,B の値が [0, 255] の範囲に無い場合に LED で表示し、その右の垂直トグル SW で頭打ちにする(既定)か黒にするかを切替える。xy 入力スライド傍らの画面は当該 (x, y, Y) に対す るX+Y+Z の色域(gamut)を示し、その下の水平トグル SW で 255 を超えた場合に 255 にする(既定) か黒にするかを切替える。RGB と xyY の変換計算は「色光のスペクトル分析」の課題であり、 RGB_setting では xyY の数値表示、数値入力の機能を省いている。
図7 xyY 入力による色指定の例 実験手順 本課題では、次の条件を満たす処理であれば画像処理の内容を自由に決めてよいが、処理結果がパラ メータの変更により顕著に変化するものであることが望ましい。 ● JPEG 画像をファイルから読み込む他に、1個以上の数値パラメータ(ブール値ではなく整数、浮動 小数点数)を入力して処理に反映させる。 ● すべての画素に対して何らかの演算を行う。pp.15-20 に掲げる処理例 1~4,7 の様に元の画素に算 術演算を施した結果を処理画素とするもの以外に、p.14 図 20 の例の様に元画素に対する比較演算の結 果により表示画素を決定するもの、pp.17-19 処理例 5,6 の様に画素の表示位置を幾何学的に変更する もの、p.21 処理例 8 の様な元画像に対する統計処理を含む。 課題Ⅰ④では、ブロックダイアグラムウィンドウでブール制御器とブール関数を配線して論理回路の 動作を模倣したが、本課題では処理内容をフォーミュラノード(Ⅰ④テキストp.5 図 4 参照)と呼ばれ る構造を用いて高水準言語と同様な形式で記述する。フォーミュラノードの文法はC に類似し、代入、 宣言、for ループの書き方などは C の文法に即しているが、ポインタや構造体は用意されておらず、ま た関数を定義して参照することはできないので再帰的なアルゴリズムも使えない。 1.処理内容を決め、そのアルゴリズムをフォーミュラノードの文法に即して記述する。 スタートメニューからLabVIEW2013(32 ビット)を開き(p.7 図 8 左)、新規 VI を作成し(図 8 中)、 ヘルプメニュー(フロントパネル、ブロックダイアグラム何れのウィンドウでもよい。図8 右は起動時 に手前に表示されるフロントパネルでの指定例)の詳細ヘルプを表示(H)をクリックする。
図8 LabVIEW2013 を開き(左)、新規 VI を作成し(中)、詳細ヘルプの表示を指定する(右) 最初にブロックダイアグラムウィンドウで右クリックして、「関数」→「プログラミング」→「スト ラクチャ」パレットから「フォーミュラノード」を選んで(図9 左)配置する。関数パネルの場合、詳 細ヘルプの表示を指定した状態ではマウスポインタを置いた関数の詳細ヘルプが表示されるので、フォ ーミュラノードを配置する前に機能を確認することができる(図 9 中上)。マウスポインタを、フォー ミュラノードを配置したい箇所の左上に移動して左クリックし、そのまま配置したい箇所の右下までド ラグしてマウスボタンを離す。一度配置した後でも辺の中心のクリック・ドラグで幅と高さの変更、四 隅のクリック・ドラグで同時変更が可能で、四隅と中点以外の箇所の左クリック・ドラグで位置を自由 に移動できる。これらの操作はⅠ④テキストp.17 の While ループ(本課題では p.13 第5節で使用する) と全く同じである。 図9 フォーミュラノードを選択、配置し、LabVIEW ヘルプ画面を開く フォーミュラノードの入出力、構文については、詳細ヘルプウィンドウのオンラインヘルプ(図9 中 上赤枠内)をクリックするか、またはフォーミュラノードの内側で右クリックし「ヘルプ」を指定して (図9 中下)LabVIEW ヘルプウィンドウを表示(図 9 右)し、フォーミュラノードを作成する、フォ ーミュラノードの構文(図 9 右赤枠内)をクリックする。個々の文(statement)の詳細についてはヘ ルプの目次を利用して必要な項目を表示すればよい。以下、ヘルプを参照しながらアルゴリズムを作成 し、テキストファイルに入力する。 処理対象の画像情報は256×256 要素の 2 次元配列として扱い(フォーミュラノードの外で JPEG フ ァイルをこの形式に変換する関数、2 次元配列を画像として表示する関数は p.9 第3節後述)個々の画 素を2 重の for ループで処理するのが一般的である。画素データは p. 2「画像データについて」に述べ た通り、R,G,B 各色 8 ビット符号無整数(値は 0~255)の 24 ビットで表現され、対応するデータ形式 に24 ビットのデータ型が無いため、32 ビット符号無整数(uInt32)を用いる。
yをフォーミュラノードから出力する処理結果の配列(フォーミュラノードの出力はデータ型の宣言 が必要)とすれば、uInt32 y[256][256]; の様に宣言する(p.14 図 20 参照)。これ以外にも、アルゴリ ズム中に現れる変数、配列はフォーミュラノードの入力として外側で型が定まっているものを除き、す べて宣言する。 xをフォーミュラノードへ入力する処理対象の配列(フォーミュラノードの入力はデータ型の宣言が 不要)として、各要素のR,G,B 各色の値を取り出すには(p. 2 図 1、2 参照)、例えば指標と色データを int i,j; uInt8 R,G,B; と宣言するとき、2 重の for ループの中でビットマスク、ビットシフトの演算を用 いてR = (x[i][j] & 0xFF0000)>>16; G = (x[i][j] & 0xFF00)>>8; B = x[i][j] & 0xFF; とすればよい。
逆に、R,G,B を(処理済みの)表示すべき 3 色のデータであるとして、これから画素データを構成す るには、y[i][j] = (R<<16)+(G<<8)+B; または、y[i][j] = (R*256+G)*256+B; とすればよい。 ここで処理結果の要素を y[i][j]の様に書くとき、表示画面で指標iは縦方向下向き、指標jは横方向 右向きの位置を示すことに注意する。指標値が増えるとき下向きであるのはコンピュータグラフィック スの初期の頃からの習慣である。 2.処理内容に必要な制御器をフロントパネルウィンドウでパレットから選んでドラグする。 フロントパネルウィンドウで右クリックして、実行時の画像表示窓として「制御器」→「モダン」→ 「グラフ」→「制御器」パレットから「2D ピクチャ」を選び(図 10 左)、これを 2 個(処理前と処理 後の画像を対比して表示させるため)配置する(詳細ヘルプの表示を指定した状態で、制御器パネルで は、マウスポインタを置いた制御器の詳細ヘルプが表示されるものとされないものとがある)。サイズ の変更はマウスポインタのドラグでも行えるが、右クリックのプロパティでラベルの変更と併せて行う のが簡単である。ここでは「プロパティ→外観」でラベルをそれぞれoriginal、processed、サイズで高 さと幅の値を、256×256 の画像に縁取りを含めた 262×262 としている(図 10 右)。 図10 制御器から「2D ピクチャ」を選び(左)、2 個配置後ラベルとサイズを変更する(右) 次に、画像処理の内容に応じてパラメータ入力、設定用に、右クリック、制御器」→「モダン」パレ ットから「数値」で数値入力(本課題では1 個以上必要)、「ブール」で論理値入力(本課題では任意) に(好みの形のものを)必要な個数選ぶ。ここでは、最も単純な画像処理として閾値指定(入力値は0 ~255)による 2 値化を例に取り、垂直ポインタスライド 1 個を用いている(p. 9 図 11 左端)。
この例では右クリック、プロパティでラベルを threshold、高さを画像表示窓に合せて 262(幅は任 意だが 30 としている)、入力値は 0~255 の整数であり、データタイプを U8(フォーミュラノード内 の型宣言ではuInt8 に相当)、スケールの上限を 255 としている。 図11 制御器から「垂直ポインタスライド」を選び、プロパティを変更する 図12 は、2 個の 2D ピクチャと垂直ポインタスライドのプロパティを変更し、位置を調整したフロン トパネルウィンドウの例である。 図12 2D ピクチャと垂直ポインタスライドのプロパティ変更後のフロントパネルウィンドウ 3.処理内容に必要な関数をブロックダイアグラムウィンドウでパレットから選んでドラグする。 実行開始後にJPEG 画像ファイルを指定して読取り、フォーミュラノードで処理する 2 次元配列に変 換するため、次の3 つの関数を配置する。この 3 つのみは、p.13 第5節で While ループを配置したと き、その外側に位置する(p. 14 図 20 参照)。 ① ブロックダイアグラムウィンドウで右クリックして「関数」→「プログラミング」→「ファイル I/O」
→「上級ファイル関数」パレットから「ファイルダイアログ」を選び(図13)、ドラグする。配置する ときに「ファイルダイアログを構成」のウィンドウが開くが、ただ OK をクリックすればよい(図 13 上)。詳細ヘルプの表示を指定していれば、マウスポインタを置いた状態で図13 右上の詳細ヘルプが表 示される。詳細ヘルプの赤枠内は、本課題でこの関数の配線に使用する入出力である(以下、図 14~ p.12 図 17 において同じ)。 図13 関数から「ファイルダイアログ」を選び、配置後 OK をクリックする ② ブロックダイアグラムウィンドウで右クリックして「関数」→「プログラミング」→「グラフィッ ク&サウンド」→「グラフィック形式」パレットから「JPEG ファイルを読み取る」を選び(図 14)ド ラグする(詳細ヘルプは図14 右上)。 図14 関数から「JPEG ファイルを読み取る」を選ぶ
③ 「JPEG ファイルを読み取る」の出力画像データは 1 次元配列であり、一方、画像処理の本体部分 のフォーミュラノードでは、2 次元配列として扱うため、変換が必要となる。ブロックダイアグラムウ ィンドウで右クリックして「関数」→「プログラミング」→「グラフィック&サウンド」→「グラフィ ック形式」パレットで「ピックスマップを非平坦化」を選び(図15:②と共通している「関数」→「プ ログラミング」→ の部分は図で省略している。図 16、p.12 図 17 も同様である)ドラグする。 図15 関数から「ピックスマップを非平坦化」を選ぶ 処理前と処理後の画像を表示するため、次の2 つの関数を配置する。この 2 つは p.13 第5節で While ループを配置したとき、その内側に位置する(p. 14 図 20 参照)。 ④ フォーミュラノードの処理結果yは 2 次元配列であり、処理された画像データを表示するためには 再び1次元配列に戻す必要がある。ブロックダイアグラムウィンドウで右クリックして「関数」→「プ ログラミング」→「グラフィック&サウンド」→「グラフィック形式」パレットから「ピックスマップ を平坦化」を選び(図16)ドラグする。 図16 関数から「ピックスマップを平坦化」を選ぶ ⑤ p. 10 ②の「JPEG ファイルを読み取る」の出力画像データ(処理前の 1 次元配列)および④の「ピ ックスマップを平坦化」でフォーミュラノードの処理結果を1 次元配列に戻した画像データを表示する ため、ブロックダイアグラムウィンドウで右クリックして「関数」→「プログラミング」→「グラフィ
ック&サウンド」→「ピクチャ関数」パレットから「平坦化ピックスマップ描画」を選び(図 17)ド ラグする。 図17 関数から「平坦化ピックスマップ描画」を選ぶ 4.フォーミュラノードに処理アルゴリズムを貼り付け、必要な「配線」(wiring)を行う。 p.6 第1節で作成したアルゴリズムをフォーミュラノードの中に貼り付ける。マウスの右クリックに よるペーストはできないので、編集メニューの「貼り付け(P)」を使うこと(デバッグで修正のためフォ ーミュラノード内をクリップボードにコピーする場合も同様に編集メニューの「コピー(C)」を用いる)。 初期状態ではフォーミュラノードの端子は入力も出力も空である。フォーミュラノードの枠(場所は どこでもよいが入力は左側、出力は右側とするのが一般的である)を右クリックして「入力を追加」、「出 力を追加」を選ぶと枠の上に外部とのデータ授受の小窓が作られるので、枠内が黒い状態( :他の場 所をクリックして白くなっている場合にはダブルクリック後に)で変数名を入力する(図18)。出力デ ータはフォーミュラノード内で型宣言されるので変数名を入力(他の場所をクリックして確定)した段 階で型に応じた色になる(図 18 右端の y)が、入力データは外部で型が決定されるので配線されるま で色が決まらない(図18 左から 3 番目、4 番目の x)。 図18 フォーミュラノードに入出力端子を追加して変数名を入力する p.10 図 13~p.12 図 17 の詳細ヘルプで赤枠内の入出力を対応付けて、ブロックダイアグラム上で次 の通り配線する。 ●ファイルダイアログの「選択されたパス」⇒JPEG ファイルを読み取るの「JPEG ファイルパス」
● JPEG ファイルを読み取るの「画像データ」⇒ピックスマップを非平坦化の「画像データ」 ⇒平坦化ピックスマップ描画の「画像データ」 ●ピックスマップを非平坦化の「24 ビットピックスマップ」⇒フォーミュラノードの入力 x ●フォーミュラノードの出力y⇒ピックスマップを平坦化の「24 ビットピックスマップ」 ●ピックスマップを平坦化の「画像データ」⇒平坦化ピックスマップ描画の「画像データ」 ●平坦化ピックスマップ描画の「新規ピクチャ」⇒制御器2D ピクチャ 例以外の制御器を入力に用いた場合、異なる型のデータ間で配線を行う場合には間に変換の関数を介 してデータの型を配線の入出力双方で一致させる必要があることに注意する(課題Ⅰ④と同様である)。 5.While ループを追加する。 前節の状態では処理内容についてのデバッグはできる(停止中にスライドを操作してパラメータを設 定して「実行」ボタン( )をクリックすると、実行開始後JPEG ファイルを読込んでフォーミュラノ ード内の処理を 1 回実行して停止する)が、実行中のパラメータ変更はできない(「連続実行」ボタン ( )をクリックするとフォーミュラノード内の処理を1 回実行してすぐにファイル読込みに戻るので スライドを操作できない)。ファイルの読込みを実行開始後の 1 回だけとして、スライドの入力を有効 にしてフォーミュラノード内の処理を繰返すには、3節の関数①~③を除いた処理と表示の部分を 「While ループ」(Ⅰ④テキスト p.17 参照)で囲めばよい。 ブロックダイアグラムウィンドウで右クリック、「関数」→「プログラミング」→「ストラクチャ」 パレット、または「関数」→「Express」→「実行制御」パレットで「While ループ」を選び(図 19 左)配置する。While ループ右下のループ条件( )にはブールの偽値(右クリック、「関数」→「プ ログラミング」→「ブール」パレットで「FALSE 定数」)を入力する(図 19 右)。While ループのサイ ズと位置の指定方法はフォーミュラノードと同様である。 図19 While ループ(左)とループ条件の FALSE 定数(右) p.14 図 20 は R,G,B の平均としてグレーレベルを求め、これがスライドから読み込んだ閾値 N を超 える画素を白、それ以外を黒で表示する2 値化表示のブロックダイアグラムウィンドウの例で、p.14 図 21 はその実行例である。
図20 閾値指定による 2 値化処理のブロックダイアグラムウィンドウ
備考 レポート作成について レポートには以下の内容を含めること。 ● 使用した画像に著作権上の問題が無いことの確認。 ● 処理アルゴリズムの説明:フォーミュラノード(複数ある場合にはそれぞれ)内に貼り付けたソース コードのテキストファイル(デバッグの結果、変更したときは、修正内容を反映した最終のもの)と、 ブロックダイアグラムウィンドウをPrtSc でキャプチャした画像。 ● 処理結果の説明と考察:実行中のフロントパネルウィンドウを PrtSc でキャプチャした画像(入力パ ラメータの変化による処理画像の変化が分る複数枚)。 その他の処理例 処理例1:階調制限 スライド入力の値S をパラメータ(bit/color)として階調を指定する。フォーミュラノード内では、 以下の様に、R,G,B 各色について 8-S ビット右シフトし(下位ビットは蒸発)同じだけ左シフトし(下 位ビットには0 が挿入される)、最後に 3 色を 24 ビットデータ(データ型としては uInt32 を使用) として構成する(実行例は図22)。
R = ((x[i][j] & 0xFF0000)>>(24-S))<<(8-S); G = ((x[i][j] & 0xFF00)>>(16-S))<<(8-S); B = ((x[i][j] & 0xFF)>>(8-S))<<(8-S); y[i][j] = (R*256+G)*256+B;
処理例2:色相変化
スライド入力の(RR, RG, RB)、(GR, GG, GB)、(BR, BG, BB)を処理後の各色に対する元画像 の色の重み、Sをそれらに共通の係数として数値で与え、また符号設定RT, GT,BT をボタンでブール 値として与えることにより、色相変化、ネガ表示を可能にした例(実行例は図23)。
R = (x[i][j] & 0xFF0000)>>16; G = (x[i][j] & 0xFF00)>>8; B = x[i][j] & 0xFF;
Rp = int((RR*R+RG*G+RB*B)*S); if (RT) Rp = min(Rp,255); else Rp = max(255-Rp,0); Gp = int((GR*R+GG*G+GB*B)*S); if (GT) Gp = min(Gp,255); else Gp = max(255-Gp,0); Bp = int((BR*R+BG*G+BB*B)*S); if (BT) Bp = min(Bp,255); else Bp = max(255-Bp,0); y[i][j] = (Rp*256+Gp)*256+Bp; 図23 元の色の重み 1(対角行列)で反転指定によりカラーネガを表示 処理例3:調子変更 各画素の値をルックアップテーブルtにより変換することで調子を変更する。tは下記の内容のフォ ーミュラノードで生成される256 要素の 1 次元配列で、その入力値 s をスライドで与える。sの値が1 より大きいと硬調に、1より小さいと軟調になる。
uInt8 t[256]; float64 a; int i; for(i=0; i<256; i++){ a = ((i/255)**s)*255; t[i] = int(a); } 本体処理のフォーミュラノード(yを求めるブロック)の入力には画像ファイルxの他にテーブルt を加える。本体処理の中では、各画素の色ごとにR = t[R]; G = t[G]; B = t[B]; の様に変換する(実行例 はp.17 図 24)。
図24 テーブルを用いた軟調表現の例 スライドのスケールは対数目盛 処理例4:シュードカラー 処理例1 と 3 の応用で、ここでは S をシュードカラーのビット数としてスライドで読み込み、フォー ミュラノードの中ではグレーレベル N を用いて輝度の高い順に R,Y,G,C,B と割付けている。1次式で 割付けると中間のY,C が暗くなるのでここでは平方根を用いている(実行例は図 25)。 N = (R+G+B)/3; if(N>127) {T=(N-128)>>(8-S); R=int(sqrt(T)*2**((17-S)*0.5)); T=2**(S-1)-T; G=int(sqrt(T)*2**((17-S)*0.5)); B=0;} else {T=(N)>>(8-S); R=0; G=int(sqrt(T)*2**((17-S)*0.5)); T=2**(S-1)-T; B=int(sqrt(T)*2**((17-S)*0.5));}; 図25 シュードカラーの例 ビット数 4 処理例5:歪曲補正 デジカメ画像用のアプリケーションにはレンズの歪曲収差を補正する機能の付いたものも多い。下記 の例はスライドで歪曲パラメータkとして、樽型(負の歪曲)には正、糸巻型(正の歪曲)には負の値 を入力し補正するものである。使用しているのは単純な歪曲モデルであり、個々のレンズの収差特性に 合わせられないため、図 26 の例でも周辺の歪を完全補正すると中心部が過剰補正となるため歪みを取
り切れていない。
註:LabVIEW ヘルプの「フォーミュラノードおよび数式ノード関数」の atan2(y, x)の説明「x/yの逆 正接をラジアンで計算します。」は誤り。正しくは、atan2(y,x)が「y/xの逆正接をラジアンで計算し ます。」である。「対応するLabVIEW 関数」をクリックして表示される「Inverse Tangent(2 Input)」 も同様に誤っている。
uInt32 y[256][256]; int i,j,i1,j1; float64 u,v,u1,v1,r,r1,theta; for(i=0; i<256; i++) { u = i-127.5;
for(j=0; j<256; j++) { v = j-127.5; r = sqrt(u**2+v**2); theta = atan2(v,u);
r1=r*(1-k*r/127.5)/(1-k); u1=r1*cos(theta); v1=r1*sin(theta); i1=int(u1+127.5); j1 = int(v1+127.5); if(i1>=0 && i1 < 256 && j1>=0 && j1<256) y[i][j]=x[i1][j1]; else y[i][j] = 0; } }
図26 強い糸巻型歪のあるルーペで撮影したクロスパタンの歪を軽減した例 処理例6:パースペクティブコントロール 写真で鉛直線群を平行に表示するためにはレンズの光軸を水平にして撮影する必要があるが、その場 合かなりの広角レンズでなければ高層建築の全体を収めることはできないため、建築写真ではシフトレ ンズがよく用いられる。下記の例は正方形画面にトリミングする前のアスペクト比r、35mm 版換算の 焦点距離f(mm 単位)と撮影時の仰角(又は伏角)theta(ラジアン)をスライド入力で与え、通常 のレンズで撮った画像のパースペクティブを補正するものである(処理例はp.19 図 27、28)。 uInt32 y[256][256]; int i,j,i1,j1; float64 u,v,p,t,a,b,k,d,phi,phi0;
p = f * sqrt((r**2+1)/(12**2+18**2)); d = p * 127.5; phi0 = atan(1/p);
b = 127.5 * cos(phi0) / cos(theta + phi0); a = -127.5 * cos(phi0) / cos(theta - phi0); for(i=0; i<256; i++) { u = i-127.5; phi = atan(u/d); t = u*cos(phi)/cos(theta+phi); k = 1/sin(phi) * t / sqrt(d**2+u**2); i1 = int((t-a) / (b-a) * 255);
for(j=0; j<256; j++) { v = j-127.5; j1 = int(v * k + 127.5); if(j1>=0 && j1<256) y[i][j]=x[i1][j1]; else y[i][j] = 0; } }
図27 35mm 相当レンズでの形状補正例 図28 24mm 相当レンズでの形状補正例 処理例7:隣接画素処理 画像の特徴抽出や雑音除去には、当該画素以外に周辺の画素(場合によっては全画像)の情報を必要 とするが、単純なエッジ抽出や隣接画素による移動平均であれば 9 個の係数(ある画素を中心として、 上下左右と斜め4 方向に自身を含めた計 9 個の画素データに対する重み付け)による線形な処理である 程度の結果が得られる。以下の例では、9 個の係数 l, m, n, … s, t(整数に限定しているので全体にか かる実数の係数fも)を数値入力で与え、また効果確認のために押しボタンでドット雑音付加の ON/OFF を切替えている。 本体処理への入力として、元の2 次元配列を p.14 図 20 などに示されている方法で 3 色分解した 2 次 元配列R[256][256], G[256][256], B[256][256](データ型は uInt8)をフォーミュラノードで作ってお く。本体処理では、2 重 for ループの範囲が 1~254 と一回り小さくなることに注意する。各色は重み付 けにより、たとえば赤については次の様に求める。
+ s*R[i+1][j] + t*R[i+1][j+1] ) * f; Rp = min(255,Rp); Rp = max(0,Rp);
また、ドット雑音付加は次の内容のフォーミュラノードで生成し、処理部分、表示部分へ入力する。 ここでdは押しボタンの出力を「ブールから(0,1)に変換」で整数に変換して入力するものである。
uInt32 y[256][256]; int i,j; for(i=0; i<256; i++) {for(j=0; j<256; j++)
{ if(mod(i,16)==8 && mod(j,16)==8 && d) y[i][j]=0xFFFFFF; else y[i][j]=x[i][j]; } }
図29 は縦横両方向の 2 階微分であるラプラシアンオペレータによるエッジ抽出の例で、中心の係数 を8 から 9 に変更するとエッジと元画像を加算した輪郭強調画像になる。図 30 は各係数を全て 1 とし (全体に1/9 を掛けているので単純な移動平均になる)付加したドット雑音を軽減した例である。この 処理では画像全体が甘くなり雑音も滲んだ様に広がるので、実際の処理では隣接画素と中心画素の9 個 の中央値を取るメジアンフィルタがよく用いられる。 図29 ラプラシアンオペレータによるエッジ抽出の例 図30 付加したドット雑音を移動平均により軽減した例 処理例8:ヒストグラム スライド入力でライン番号lと度数表示の最大値r、押しボタンwでラインまたは全体の切替え、押
しボタンRt、Gt、Bt で度数を表示する色を指定して、画像中の指定ライン(処理例:図 31)または画 像全体(処理例:図32)の度数分布を重ねて表示する例である。横軸が R,G,B の値で 0~255、縦軸が 度数で、0~rを示している。ヒストグラムの画像データyを生成するフォーミュラノードは以下の通 りである。
uInt32 y[256][256], hR[256],hG[256],hB[256]; uInt8 R,G,B; int i,j,k;
for(i=0; i<256; i++) { hR[i]=0; hG[i]=0; hB[i]=0; for(j=0; j<256; j++) { y[i][j]=0; } }
if(w) for(i=0; i<256; i++) { for(j=0; j<256; j++) { R= (x[i][j] & 0xFF0000)>>16; hR[R]++; G= (x[i][j] & 0xFF00)>>8; hG[G]++; B= x[i][j] & 0xFF; hB[B]++; } }
else for(j=0; j<256; j++) { R= (x[l][j] & 0xFF0000)>>16; hR[R]++; G= (x[l][j] & 0xFF00)>>8; hG[G]++; B= x[l][j] & 0xFF; hB[B]++; };
for(j=0; j<256; j++) { if(Rt){ k=min(256,int(hR[j]/r*256)); if(k) for(i=256-k; i<256; i++) { y[i][j]=y[i][j] | 0xFF0000; } }
if(Gt){ k=min(256,int(hG[j]/r*256)); if(k) for(i=256-k; i<256; i++) { y[i][j]=y[i][j] | 0xFF00; } } if(Bt){ k=min(256,int(hB[j]/r*256)); if(k) for(i=256-k; i<256; i++) { y[i][j]=y[i][j] | 0xFF; } }
左側の画像では、ライン指定が有効な場合に指定ラインを白く表示するため、for ループの中で if(i==l && !w) y[i][j]=0xFFFFFF; else y[i][j]=x[i][j]; } とすればよい。
図31 指定ラインのヒストグラム