画像処理はじめました。

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

0-2 「Python Numpyによる画像表現(カラー画像)」

内容

PILで取得した画像データをNumpy配列へ代入した際、Numpy配列の内容がどのようになるのか調べました。

やり方

ペイントツールで作成した画像サイズ縦2ピクセル、横3ピクセルのビットマップカラー画像(input2x3.bmp)をPILを使用して読み込み、numpy配列化します。配列の中身を print文で表示し、ビットマップ画像データがどのように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)
# ((2L, 3L, 3L), dtype('uint8'))
# 行、列、色数に続いて、続く文字列は要素のデータ型をあらわす。
# uint8 は、符号なし整数8ビットという意味。
# したがって、 2x3サイズ(縦x横)のカラー画像の意味

## 配列の中身を確認
print(im)
#[[[255   0   0]    <- 赤色 (Red=255, Green=0, Blue=0)
#  [  0 255   0]    <- 緑色 (Red=0, Green=255, Blue=0)
#  [  0   0 255]]   <- 青色 (Red=0, Green=0, Blue=255)
#
# [[  0   0   0]    <- 黒色 (Red=0, Green=0, Blue=0)
#  [128 128 128]    <- 灰色 (Red=128, Green=128, Blue=128)
#  [255 255 255]]]  <- 白色 (Red=255, Green=255, Blue=255)

## 座標i,jの色チャンネルkの値は、 im = [i,j,k]で取得できる。
print(im[0,0])
# [255   0   0]

print(im[0,0,0]) # R
print(im[0,0,1]) # G
print(im[0,0,2]) # B
# 255
# 0
# 0

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

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

実行結果
f:id:genetaka1810:20191022183803p: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ビット)は各要素のデータ型をあらわします。


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

[[[255 0 0] <- ピクセル座標(0,0)の色情報
[ 0 255 0] <- ピクセル座標(0,1)の色情報
[ 0 0 255]] <- ピクセル座標(0,2)の色情報

[[ 0 0 0]    <- ピクセル座標(1,1)の色情報
[128 128 128]  <- ピクセル座標(1,1)の色情報 
[255 255 255]]] <- ピクセル座標(1,1)の色情報

これらは、画像の各ピクセル座標に対する色情報が表示された結果です。例えば、 im[0,0] は、ピクセル座標 (0,0) の色情報を表し、R,G,Bの色情報は、[255 0 0] と取得でき、これは 赤:255, 緑:0, 青:0 の色であることを意味しています。
同様に im[0,1] は、ピクセル座標 (0,1)の色情報を示しており、 赤:0, 緑:255, 青:0 の色を持つことがわかります。


ピクセル座標と色の関係を改めて図示しておきます。

f:id:genetaka1810:20191022183431p:plain

im[1,0] は黒色なので、RGBがすべて0となり、im[1,2]は、白色なのでRGBがすべて255となっています。
つまり、ピクセル座標 ( i, j )、色チャンネル k の値は、 im = [i, j, k]で取得できることがわかると思います。

補足

numpy配列を用いて画像を作成してみました。

補足プログラム

#!/usr/bin/python
# -*- coding: utf-8 -*-
# Numpyによる画像表現

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

# 2x3サイズのテスト画像作成 (カラー画像)
im=np.zeros((2, 3, 3), np.uint8)

im[0,0,0]=255   # R
im[0,1,1]=255   # G
im[0,2,2]=255   # B

im[1,0,:]=0     # Black
im[1,1,:]=128   # Glay
im[1,2,:]=255   # white

print(im.shape, im.dtype)
# ((2L, 3L, 3L), dtype('uint8'))
# 行、列、色数に続いて、続く文字列は要素のデータ型をあらわす。
# uint8 は、符号なし整数8ビットという意味。
# したがって、 2x3サイズ(縦x横)のカラー画像


## 配列の中身を確認
print(im)
#[[[255   0   0]    <- 赤色 (Red=255, Green=0, Blue=0)
#  [  0 255   0]    <- 緑色 (Red=0, Green=255, Blue=0)
#  [  0   0 255]]   <- 青色 (Red=0, Green=0, Blue=255)
#
# [[  0   0   0]    <- 黒色 (Red=0, Green=0, Blue=0)
#  [128 128 128]    <- 灰色 (Red=128, Green=128, Blue=128)
#  [255 255 255]]]  <- 白色 (Red=255, Green=255, Blue=255)

## 座標i,jの色チャンネルkの値は、 im = [i,j,k]で取得できる。
print(im[0,0])
# [255   0   0]

print(im[0,0,0]) # R
print(im[0,0,1]) # G
print(im[0,0,2]) # B
# 255
# 0
# 0


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

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