行列による画像処理

計算機演習A,B 2021年8月9日 担当教員: 劉 雪峰

1. ピクセルと行列

画像ファイルは、ピクセル(色情報を持った点)によって構成されています。例えば、サイズが$200\times 200$の画像ファイルの場合、$200\times 200=40000$個のピクセルから成っています。

カラー画像において、各ピクセルの色の表現にはRGB(赤、緑、青)の値($0$~$255$)が使用されます。RGBの値を格納するために、サイズが$M\times N$の画像ファイルに対しては$M\times N\times 3$の$3$次元行列が必要となります。

画像の行列を$A$とすると、

(ここで、配列の番号は$0$から始まることに注意してください。)

画像におけるピクセルの座標系は下の図の通りです。

2. Pythonでの画像処理

Pythonで画像処理を行うためのライブラリはOpenCVなど様々にありますが、ここではPillow(パッケージ名=PIL)とNumPyを組み合わせた方法を扱います。

2.1 画像の読み込み・表示・保存

初めに、授業のホームページからトマトの画像(tomato.jpg)をダウンロードし、JupyterLab上でこのノートブックと同じフォルダ内にアップロードしてください。その上で、次のようにして画像ファイルをNumPyの行列として読み込みます。

画像に対応する行列の各成分のデータ型は、$8$ビット符号なし整数(uint8)になります。

Matplotlibを利用すれば、読み込んだ画像をノートブック上で表示することができます。

画像の行列に対して何らかの処理(例えば色の反転)を行った後に画像ファイルとして保存するには、次のようにします。

色が反転したトマトの画像(new_tomato.jpg)が同じフォルダ内に作成されます。

2.2 画像に対する様々な処理

トマトの複製を例にして、行列の計算による画像ファイルの処理方法を説明します。

新しい画像を作成するために、列のサイズが2倍になっている行列(img_2)を利用します。 行列のデータタイプを8 ビット符号なし整数(uint8)とします。

新しい行列(img_2)の1からcolsまでの列と、(2cols+1)から(2cols)までの列に元々の行列(img) のデータをコピーします。

画像に対して行う処理(加工)として、例えば以下のものが考えられます。

new_img = 255-img
new_img = img[:,:,0]/3+img[:,:,1]/3+img[:,:,2]/3
plt.imshow(new_img,cmap='gray')

(2次元行列をグレースケール画像としてplt.imshow()で表示するには、cmap='gray'の指定が必要です。)
new_img = (img[:,:,0]+img[:,:,1]+img[:,:,2])/3とするのは、各成分の値が$8$ビット符号なし整数の範囲$0$~$255$を計算途中で超える可能性があるため良くありません。)

new_img = img.copy()
new_img[:,:,[1,2]] = 0

(単にnew_img = imgとすると、配列やNumPyの行列では代入元と代入先の値が連動して変わってしまうため、オブジェクトのコピーを行っています。)

new_img = img[100:200,400:500,:]
new_img = img[::2,::2,:]

(必要なピクセルの個数が$\frac{1}{2}\times\frac{1}{2}=\frac{1}{4}$倍になるため、縦横ともに偶数番号のピクセルの情報のみを利用します。)

new_img = img.repeat(2,axis=0).repeat(2,axis=1)

(必要なピクセルの個数が$2\times 2=4$倍になるため、各ピクセルの情報を4個のピクセルに対して利用します。)

演習1

画像に対する上記の様々な処理を試して、それぞれ処理後の画像を表示してください。

演習2

トマトの画像に対して、上で試したもの以外の自由な処理を考えて行い、処理後の画像を表示してください。例えば、回転(np.rot90()が利用可能)、上下左右に反転(np.flip()が利用可能)、色の交換など。授業で提供したトマトの画像以外にも、画像を自由に使用してください。

本資料に使用したトマトの写真に関する著作権: https://en.wikipedia.org/wiki/File:Bright_red_tomato_and_cross_section02.jpg