画像処理はじめました。

AI/AR/VRという近未来的な言葉に惹かれ、その技術分野に参戦するために立ち上げたブログです。日々の格闘結果を記録に残してゆこうと思います。

0-3 「Python Numpyによる画像表現(グレー画像)」

PILで取得した画像データをNumpy配列へ代入した際、Numpy配列の内容がどのようになるのか調べました。
比較のためにカラー画像と、カラー画像をグレースケールへ変換したデータを記載します。

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Numpyによる画像表現(グレースケール)

from PIL import Image 
import numpy as np
from matplotlib import pylab as plt

# 画像の読み込み (カラー画像)
im = np.array(Image.open('input2x3.bmp'))
print(im.shape, im.dtype)

#画像の表示
plt.imshow(im)
plt.show()


# 画像の読み込み (グレースケール)
im = np.array(Image.open('input2x3.bmp').convert('L'))
print(im.shape, im.dtype)

# 上記を実行すると次のように表示される
# ((2L, 3L, 3L), dtype('uint8'))
# ((2L, 3L), dtype('uint8'))
# 最初のタプルは行、列、色数を表し、続く文字列は要素のデータ型をあらわす。
# uint8 は、符号なし整数8ビットという意味。
# 2番目のimでは、'L'を指定してグレースケールに変換しており、その場合、
# 色情報がなく、shapeのタプルは2つの値のみとなる。

print(im)
#[[ 76 149  29]
# [  0 128 255]]


#画像の表示
plt.gray() # 表示カラーマップをグレースケールとする(*)
plt.imshow(im)
plt.show()

# (*) YIQフォーマットのY画像?
# Y = 0.298912 x R + 0.586611 x G + 0.114478 x Bで計算される。
# RGB(255,0,0) の場合 Y= 76.22256 + 0 + 0
# RGB(0,255,0) の場合 Y= 0 + 149.585805 + 0
# RGB(0,0,255) の場合 Y= 0 + 0 + 29.19189
#
# RGB(128,128,128) の場合 Y= 38.260736 + 75.086208 + 14.653184 = 128.000128
# RGB(255,255,255) の場合 Y= 76.22256 + 149.585805 + 29.19189 = 255.000255


#保存
Image.fromarray(im).save('input2x3_save.bmp')


実行結果
f:id:genetaka1810:20191023220039p:plain


プログラムの実行結果を確認していきます。


# 画像の読み込み (カラー画像)
>im = np.array(Image.open('input2x3.bmp'))
>print(im.shape, im.dtype)
>(2L, 3L, 3L), dtype('uint8')

print文で表示された (2L, 3L, 3L), dtype('uint8') の意味は、読み込ませた画像ファイルが高さ2ピクセル、幅3ピクセルのカラーBMP形式ですので、(2L, 3L, 3L)のタプルは、順に、画像の高さ(行)、画像の幅(列)、色数を表していることがわかります。
また、続く文字列 uint8 (符号なし整数8ビット)は各要素のデータ型をあらわします。

# 画像の読み込み (グレースケール)
>im = np.array(Image.open('input2x3.bmp').convert('L'))
>print(im.shape, im.dtype)
>(2L, 3L), dtype('uint8')

グレースケールでは、(2L, 3L), dtype('uint8') と表示され、色情報がなく、shapeのタプルは2つの値となることが確認できます。
なお、カラー画像からグレースケールへの変換は、PILのImage openの時に、'L'を指定してます。


次に実際にnumpy配列へ代入した画像データをprint(im) 文により確認してみます。
すると、以下の様な結果が得られました。

[[ 76 149 29] <- im[0]
[ 0 128 255]] <- im[1]


これらは、画像の各ピクセル座標に対する輝度情報が表示された結果です。
例えば、 im[0,0] は、ピクセル座標 (0,0) の輝度値 76を示しています。
同様に im[0,1] は、ピクセル座標 (0,1)の輝度値 149を示しています。


カラー画像の読み込み時に、'L'を指定しグレースケールへ変換しているわけですが、カラー画像の場合、ピクセル座標(0,0)のカラー値は、(R,G,B) = (255, 0, 0)となっています。このカラー画素値をグレースケールへ変換すると、76 という値に変換されています。


(補足:要確認)
カラー画像からグレースケールへ変換したときのカラー値は、YIQフォーマットのY画像を表しているのではないかと思われます。
Y画像は、RGBのカラー画像から、人間の目の明るさ感度に特化して作成する画像で、次の計算式により求まります。

Y = 0.298912 x R + 0.586611 x G + 0.114478 x B

(R,G,B) = (255, 0, 0)の場合、 Y= 76.22256 + 0 + 0 と計算され、'L'指定で作成したグレースケールの値 76 とほぼ一致します。
同様に、ピクセル座標(0,1)の カラー値は、RGB(0,255,0)なので、 Y= 0 + 149.585805 + 0 となり、ピクセル座標(0,2)の カラー値は、RGB(0,0,255)の場合、 Y= 0 + 0 + 29.19189 と計算されます。

もう少し調べてみて、何かわかったら記事を更新します。