ディジタル画像

目的

ここでは,コンピュータで扱うことのできるディジタル画像について学ぶ.また,画像処理をする際には画像を入力する必要があり,処理した結果を画像としてウィンドウに表示したりファイルに保存することがある.ここでは,OpenCVモジュールを使用して画像を入出力する方法を学ぶ.

説明

ディジタル画像

グレースケール静止画像

グレースケール画像は2次元の平面上の明暗で表現され,2次元平面の座標を\((x,y)\)とすると,\(f(x,y)\)と表される.ここで\(f\)は輝度と呼ばれる量であり,この値が大きいほど明るく,小さいほど暗いことを表す.

コンピュータでは連続量を表現できないため,2次元平面の座標\((x,y)\)を離散化する必要がある.この空間方向に離散化する操作を標本化と呼ぶ.標本化を行うと,離散値\([x,y]\)に関してのみ輝度\(f[x,y]\)が存在することとなる.標本化された画像には図のような升目ができ,この升目を画素(pixel)と呼ぶ.標本化によって,横方向に\(W\)個・縦方向に\(H\)個の画素が作成されたとき,その画像の解像度は\(W \times H\)であると言う.解像度は空間方向の表現の細かさを表す量である.

以下は,同じグレースケール静止画像の解像度を変えたものである.解像度が大きいほど空間的な表現の細かさが細かく,解像度が小さいほど空間的な表現の細かさが粗いことがわかる.

標本化された各画素に入る輝度に関しても,コンピュータでは連続値として表現できないため,離散化する必要がある.この操作を量子化と呼ぶ.各画素の輝度を表現するのに割り当てられるビット数を量子化数,それによって表現できる明暗の段階の数を階調数と呼ぶ.以下は,同じグレースケール静止画像の量子化数・階調数を変えたものである.左から右に向かって空がだんだん暗くなっているが,量子化数・階調数が小さすぎると,肉眼では見られない輪郭(疑似輪郭と呼ぶ)が現れていることがわかる.8bit・256階調のグレースケール画像では疑似輪郭は見られず,この程度量子化数・階調数があれば肉眼と遜色ない程度に明暗が表現されていることがわかる.8bit・256階調はディジタルグレースケール画像でよく使用される量子化数・階調数である.

カラー静止画像

カラー静止画像の標本化はグレースケール静止画像の標本化と同じである.グレースケール静止画像では明暗を輝度で表したが,カラー静止画像では色を光の三原色である赤(red)・緑(green)・青(blue)で表現するため,カラー静止画像の量子化はRGBの各値を離散化する操作となる.カラー静止画像でよく使用される量子化数に24bitカラーがある.これはRGBそれぞれを8bitで表現したものであり,約1700万色の色が表現できる.そのため,フルカラーやトゥルーカラーと呼ばれる.また,24bitカラーに不透明度を表すアルファ値を8bit分付け加えたものを32bitカラーと呼ぶ.グレースケール画像は1つの画素に輝度のみが入っていることからチャンネル数が1であると言い,24bitカラー画像では1つの画素にRGBの3つの値が入っていることからチャンネル数が3であると言い,32bitカラー画像ではRGBとアルファ値が入っていることからチャンネル数が4であると言う.

ディジタル静止画像の座標と画素の並び順

ディジタル静止画像では通常,左上が原点・右向きが\(x\)軸の正の向き・下向きが\(y\)軸の正の向きとすることが多い.また,各画素は図に示すように左上から右下に向かう順(ラスタ捜査順)に1次元的にメモリに格納されることが多く,この順に処理されることが多い.複数チャンネルの場合,各画素にはRGBの順に値が入ることもあれば,BGRの順に値が入ることもある.OpenCVと呼ばれるComputer Vision用のライブラリではBGRの順に値が保存される.

動画像

動画像の場合は空間\([x,y]\)に加えて時間\(t\)に関しても明暗やRGB値が変化する.そのため,動画像は\([x,y,t]\)によって変化する3次元信号となり,空間的にも時間的にも標本化する必要がある.動画像中の1枚の静止画像をフレームと呼び,1秒間に標本化するフレーム数をフレームレートと呼ぶ.フレームレートの単位はfps(frames per second)であり,この値が大きいほど時間方向の表現の細かさが細かく,この値が小さいほど時間方向の表現の細かさが粗くなる.

画像の入出力

静止画像ファイル入力・ウィンドウ出力

まずは静止画像をファイルから読み込み,ウィンドウに表示してみよう.

1行目でOpenCVのcv2モジュールをインポートしている.19行目でファイル名を指定して静止画像を読み込み,20行目でウィンドウを生成し,画像を表示している.imshow関数の第1引数にはウィンドウのタイトルバーに表示する文字列を指定する.ここでは,ファイル名を指定している.画像をウィンドウに表示するプログラムはすぐに終了してしまうと結果が確認できないため,しばらく表示し続ける必要がある.21行目では指定した時間だけキー入力を待つようにしている.ここでは引数に0を指定することで,何かキーが押されるまで待つようにしている.22行目で,何かキーが押されたときに全てのウィンドウを消去するようにしている.

実行するとウィンドウが表示され,以下のような画像が出力される.ウィンドウをアクティブにした状態で何かキーを押すと,プログラムが終了する.

静止画像ファイル入力・静止画像ファイル出力

次に,静止画像をファイルから読み込み,ファイルに出力してみよう.

20行目でファイル名を指定して静止画像を読み込み,21行目でファイル名を指定して静止画像をファイルに保存している.実行すると,「output_image.png」という名前のファイルができ,入力画像と同じ画像が保存される.

カメラ入力・ウィンドウ出力

次に,カメラから画像を読み込み,ウィンドウに表示してみよう.

10行目でカメラIDを指定し,カメラをオープンしている(カメラオブジェクトを生成している).カメラIDは複数台カメラが繋がっているときにどのカメラをオープンするかを指定するための番号であり,ここでは0としている.13行目でカメラから画像を1フレーム読み込み,14行目で表示している.12行目でこれを繰り返すことにより,カメラから連続して画像を取得し表示している.15行目から17行目で,qキーが押されたときに繰り返しを終了するようにしている.19行目でカメラをクローズし,20行目でウィンドウを全て消去して終了するようにしている.

実行するとカメラから取得した画像がウィンドウに表示され,ウィンドウをアクティブにした状態でqキーを押すと,プログラムが終了する.

カメラ入力・静止画像ファイル出力

カメラから画像を読み込み,あるキーを押したときに静止画像をファイルに保存してみよう.

17,18行目で,cキーが押されたときにカメラから取得した画像をファイルに保存するようにしている.実行するとカメラから取得した画像がウィンドウに表示され,ウィンドウをアクティブにした状態でcキーを押すと,「captured_image.png」という名前のファイルができ,カメラから取得した画像が保存される.

動画像ファイル入力・ウィンドウ出力

次に,動画像をファイルから読み込み,ウィンドウに表示してみよう.

20行目でファイル名を指定することで,動画像ファイルをオープンしている.21行目で動画像ファイルのフレーム数を取得している.また,22行目でフレームレートを取得し,23行目で1フレームあたりの時間(単位はミリ秒)を求めている.26行目で動画像ファイルから1フレーム画像を読み込み,27行目で表示している.25行目でこれをフレーム数分だけ繰り返すことにより,動画像ファイルから連続して画像を読み込み,表示している.28行目から30行目で,qキーが押されたときに繰り返しを終了するようにしている.

実行するとウィンドウに以下の動画が表示される.

動画像ファイル入力・動画像ファイル出力

次に,動画像をファイルから読み込み,ファイルに書き出してみよう.

25,26行目で動画像ファイルの解像度を取得している.25行目で出力する動画像ファイルのコーデックを指定し,29行目で出力動画像ファイルをオープンし,34行目で書き出している.実行すると,「output_video.avi」という名前のファイルができ,入力動画像と同じ内容の動画像が保存される.

カメラ入力・動画像ファイル出力

カメラから取得した画像を動画像としてファイルに保存してみよう.

11行目でカメラをオープンし,12行目から14行目でフレームレートと解像度を取得している.16行目でコーデックを指定し,17行目で出力動画像ファイルをオープンしている.19行目から25行目で,カメラから画像を取得し,ウィンドウに表示し,ファイルに書き出している.

実行するとカメラから取得した画像がウィンドウに表示され,ウィンドウをアクティブにした状態でqキーを押すと,プログラムが終了する.「captured_video.avi」という名前のファイルができ,カメラから取得した動画像が保存される.

カメラ入力(解像度・フレームレートの指定)

次に,解像度とフレームレートを指定し,カメラから画像を取得してみよう.

10行目でカメラをオープンし,11行目でフレームレートを60fpsに,12,13行目で解像度を320×240に設定している.実行すると,指定した解像度の画像が指定したフレームレートで表示される.指定できるフレームレートや解像度の上限はカメラやコンピュータの性能によって決まるため,指定した通りに表示されないことがある.

解像度・チャンネル数・データ型の取得

以上では,画像の入出力を行った.ここでは,入力した画像データから画像処理に必要な情報として解像度とチャンネル数とデータ型を取得してみよう.

カラー画像

20行目で読み込んだカラー画像の解像度とチャンネル数を取得し,21行目から23行目で表示している.また,24行目で読み込んだカラー画像のデータ型を表示している.実行すると以下のように表示され,解像度が320×240であり,チャンネル数が3であることが確認できる.また,データ型は符号なし8ビット整数型(unsigned 8bit integer)であり,BGR値ともに0から255までの間の整数値で表現されていることがわかる.

グレースケール画像

では,グレースケール画像を入力して解像度とチャンネル数とデータ型を表示してみよう.

実行すると以下のように表示され,解像度が320×240であり,チャンネル数が3であることが確認できる.また,データ型は符号なし8ビット整数型であり,輝度値が0から255までの間の整数値で表現されていることがわかる.グレースケール画像の場合はチャンネル数が1となるはずであるが,OpenCVでグレースケール画像を入力すると,3チャンネル画像として読み込まれていることがわかる.

グレースケール画像を1チャンネル画像として読み込むには,以下のように記述すればよい.

19行目で,imread関数の第2引数にcv2.IMREAD_UNCHANGEDを指定すると,グレースケール画像を1チャンネル画像として読み込むことができる.実行すると以下のように表示され,画像データが2次元配列として表現されていることがわかる.

ある画素値の取得

次に,画像データから画素値を取得してみよう.

カラー画像

カラー画像のある画素のBGR値を取得するには以下のように記述すればよい.

22行目で(100, 100)の画素のBGR値を取得し,23行目で表示している.実行すると以下のように表示され,(100, 100)の画素のBGR値が[247, 248, 239]であることがわかる.

グレースケール画像

グレースケール画像のある画素の輝度値を取得するには以下のように記述すればよい.

22行目で(100, 100)の画素の輝度値を取得し,23行目で表示している.実行すると以下のように表示され,(100, 100)の画素の輝度値が245であることがわかる.

全画素値の取得

次に,ラスタ走査順に画像データの全画素値を取得してみよう.

カラー画像

カラー画像をラスタ走査順に走査し,BGR値を取得するには,以下のように記述すればよい.

20行目で解像度とチャンネル数を取得し,21,22行目でラスタ走査順にy座標とx座標を変化させ,23,24行目でBGR値を表示している.実行すると以下のように表示され,ラスタ走査順にBGR値が表示される.

グレースケール画像

グレースケール画像をラスタ走査順に走査し,輝度値を取得するには,以下のように記述すればよい.

20行目で解像度を取得し,21,22行目でラスタ走査順にy座標とx座標を変化させ,23行目で輝度値を表示している.実行すると以下のように表示され,ラスタ走査順に輝度値が表示される.

課題

課題0

静止画像ファイルから画像データを読み込み,ウィンドウに表示せよ.

課題1

静止画像ファイルから画像データを読み込み,静止画像ファイルに書き出せ.

課題2

カメラから画像データを取得し,ウィンドウに表示せよ.

課題3

カメラから画像データを取得し,何かキーを押したときに静止画像ファイルに書き出せ.

課題4

動画像ファイルから画像データを読み込み,ウィンドウに表示せよ.

課題5

動画像ファイルから画像データを読み込み,動画像ファイルに書き出せ.

課題6

カメラから画像データを取得し,動画像ファイルに書き出せ.

課題7

解像度とフレームレートを指定し,カメラから画像データを取得し,ウィンドウに表示せよ.

課題8

カラー静止画像ファイルから画像データを読み込み,ラスタ走査順に全BGR値を表示せよ.

課題9

グレースケール静止画像ファイルから画像データを読み込み,ラスタ走査順に全輝度値を表示せよ.