Pythonでの画像処理の基本

画像形式の基礎知識

  • JPEGとかは圧縮されているとして、PNGBMPの違いが分からなくなるのでメモ。

PNG(Portable Network Graphics)

  • Webでのビットマップ画像を扱うために1996年に生まれた。GIFなどに対して後発なのでGIFなどで足りない機能が追加されている。
  • 8bit/24bitの2つの形式がある。8bitは256色での保存、24ビットはフルカラー写真、透明色を持たせられる。
  • PNGも圧縮されている(なんと知らなかった。。。)。ただし、JPEG非可逆圧縮であるのに対して可逆圧縮

BMP(Microsoft Windos Bitmap Image)

  • 名前の通りMS Windows向けに作成された。
  • 圧縮されない。

メモ

グレースケール化

  • RGBをグレースケール化する場合、単純にRGBの平均値を取るわけじゃないらしい。実際には下記の式で変換するらしい。
Gray = 0.3 \cdot R + 0.59 \cdot G + 0.11 \cdot B

pythoでの扱い

  • openCV使わなくてもPIL(Python Image Library)でも多くのことが出来て使い方も簡単な印象だ。
  • scikit-imageというのも使いやすそうだ。

画像のピクセルデータの読み書き

# Open
img = Image.open(sys.argv[1])
# Show
img.show()
# モード確認
img.mode #=>RGBAとかだとsplitとかは4値を返すので注意
# Get, Size
img.size  #=> (x, y)
img.height
img.width
# Get pixel data
img.getpixel((32, 32)) #=> r,g,b(,a)
# Overwrite pixel data
img.putpixel((5,5), (0,0,255))  #=> 5,5を青(0,0,255)で塗る
# Convert to Numpy array
img_array = np.array(img)
# Conver from Numpy array
Image.fromarray(arr_data) 

基本的な処理

  • 基本的な処理は自分で書かなくても用意されている。
  • RGBの分離が良くわからない。splitしたものと、他を0に潰したものって違うのかな??
# サイズの変更
img.resize((100, 100)) #=>100x100に変換
# 回転(degreeで与える)
img.rotate(45) 
# グレースケール化
img.convert('L')
# アルファ値付きのグレースケール化
img.convert('LA')
# 画像の結合(並べて1つの画像にする)
canvas = Image.new('RGB', (600, 200), (255, 255, 255))  #=>白い下地を作成
canvs.paste(img1, (0,0))  #=>左上の座標で貼り付け位置を指定
canvs.paste(img2, (200,0))
canvs.paste(img3, (400,0))
# 切り出す
canvas.crop((0,0,200,200)) #=>左上の座標(x,y), 右下の座標(x,y)
# RGB(A)の分離
r, g, b, a = img.split()
# RGB分離2(他の値を0にする)
img_array = np.array(img)
r_img_array = img_array[:,:,(1,2)] = 0 #=> (200x200x3ch)の1(G),2(B)チャンネルを0にする。
r_img_array = img_array[:,:,(0,1)] = 0 #=> (200x200x3ch)の0(R),1(B)チャンネルを0にする。
r_img_array = img_array[:,:,(0,2)] = 0 #=> (200x200x3ch)の0(R),2(B)チャンネルを0にする。
# RGBの入れ替え
r, g, b = img.split()
img2 = Image.merge('RGB', (g, b, r)) #=> 好きな順番に入れ替えてマージ
# 簡易モザイク化(一旦小さくして戻す)
img.resize((32,32)).resize(200,200)

画像生成

  • 結構簡単に画像を作れる。下の例は白黒のモザイク画像。
img = Image.new('RGB', (32, 32))
for y in range(img.width):
    for x in range(img.width):
        if (y+x)%2 == 0:
            img.putpixel((x,y), (255, 255, 255))
        else:
            img.putpixel((x,y), (0, 0, 0))
img.save('mozaic.png')