画像処理ライブラリに頼らず、行列演算だけで画像処理・グレースケール化をするお話。Pythonistaでも可能
#「再発明家」とは
Open CVとかPillowに頼らず、numpyとmatplotlibを使って、様々な画像処理を実際に書いてみる。iOSアプリのPythonistaでも使える組み合わせだ。
import numpy as np
import matplotlib.pyplot as plt
また、画像表示には以下の関数が便利である。(詳しくは基礎編)
def img_show(img : np.ndarray, cmap = 'gray', vmin = 0, vmax = 255, interpolation = 'none') -> None:
'''np.arrayを引数とし、画像を表示する。'''
#dtypeをuint8にする
img = np.clip(img,,vmin,vmax).astype(np.uint8)
#画像を表示
plt.imshow(img, cmap = cmap, vmin = vmin, vmax = vmax, interpolation = interpolation)
plt.show()
plt.close()
#グレースケール化
グレースケール化、とは各ピクセルに充てられたRGBの値を白黒の値Yを計算する手法である。
ここでは、基礎編で扱わなかった様々なグレースケールの手法も試してみる。
詳しい説明はリンクを参照。同じ順序で扱っている。
使用画像は'tiger.jpeg'
img = plt.imread('tiger.jpeg')
R, G, B = img[...,0], img[...,1], img[...,2]
カラーと白黒を比較して並べるための関数をここで定義しておく。
def align_show(img_gray):
#img_grayをN*M*3に変換
img_pseudogray = np.einsum('ij,k->ijk',img_gray,[1,1,1])
#横に並べて表示
img_show(np.concatenate((img,img_pseudogray), axis = 1))
##中間値法
$\rm Y=\frac{\max(R,G,B) + \min(R,G,B)}{2}$とする。手法である。要するに、最大値と最小値の平均。
なお実際の計算ではオーバーフローを避けるために上式とは一部、計算の順序を変えてある。
img_mid_v = np.max(img, axis = 2)/2 +np.min(img, axis = 2)/2
img_show(img,img_mid_v)
パッと見問題ないが、迷路の真ん中のボタン(?)が見えにくい。
##NTSC 係数による加重平均法
$\rm Y = ( 0.298912 R + 0.586611 G + 0.114478 B )$とする手法である。これらの係数は、各RGBが人間の目に与える影響(心理的加重)を考慮に入れた結果である。
img_ntsc = (0.298912 * R + 0.586611 * G + 0.114478 * B)
align_show(img_ntsc)
良さげ
##HDTV 係数による加重平均と補正
$\rm Y = ((0.222015 R)^X + (0.706655 G)^X + (0.071330 B)^X )^{1/X}$とする手法である。これも心理的加重を取り入れている。
X = 2.2
img_hdtv = ((0.222015*R)**X + (0.706655*G)**X + (0.071330*B)**X)**(1/X)
align_show(img_hdtv)
私にはNTSC法との違いがわからないくらいの違いである。
##単純平均法
$\rm Y = \frac{R + G + B}{3}$という平均をとる方法である。一番直感的なやり方だろう。加重平均をとる前のNTSC法ともいえるかも。
img_mean = np.mean(img)
align_show(img_mean)
##Gチャンネル法
$\rm Y = G$というGチャンネルのみを取り出す方法。一番速そう。
img_g_channel = G
align_show(img_g_channel)
赤色部分がちょっと濃すぎるかな…
##中央値法
$\rm Y = median(R, G, B)$という中央値を取り出す方法。中間値法と似た発想な気がする。
img_median = np.median(img, axis = 2)
align_show(img_median)
中間値法と同じく、緑が濃すぎる。
##まとめ
中間値 | NTSC | HDTV |
---|---|---|
元画像 | ||
単純平均 | Gチャンネル | 中央値 |