Pythonによるデータ処理12 ~ ウェーブレット変換5
前回はウェーブレット変換で高次特徴量はマスクとスパース行列を使うことで、画像を構成する要素数が削減できることを示したが、今回はメモリ削減の効果について検証してみる。
1. 変数のメモリ量の確認
前回までと同様に標準画像データベースのboatを読み込み、変数をgray
とする。
import numpy as np from scipy import signal import matplotlib.pyplot as plt %matplotlib inline import pywt from scipy.sparse import csr_matrix from google.colab import files uploaded_file = files.upload() uploaded_file_name = next(iter(uploaded_file)) orig = cv2.imread(uploaded_file_name) gray = cv2.cvtColor(orig, cv2.COLOR_BGR2GRAY)
まず、メモリの使用量を調べるコマンドとして変数名.nbytes
を使用する。読み込んだグレースケールの画像のgray
のメモリサイズは
gray.nbytes
> 65536
前回のウェーブレット処理方法のままで、メモリ削減の効果を示すためにuint8のgrayを.astype(np.int16)
としてint16に変換する。
(uint8で以下の方法で進めると復元した画像がよくなかったため、何か他に工夫がいる)
gray2 = gray.astype(np.int16)
gray2.nbytes
> 131072
メモリの使用量も2倍に増えていることが確認できる。念のためtypeで型の表示と要素数を確認すると、gray2はint16で要素数は256x256になっていることがわかる。 ここでint16は2byteなので256x256x2=131072 byteで一致している。
print(type(gray2[0][0])) np.shape(gray2) ><class 'numpy.int16'> >(256, 256)
2. スパース行列のメモリ
int16のgray2
を2Dウェーブレット変換し、Approximation:LLと高次情報(LH,HL,HH)を取得する。
coeffs2 = pywt.dwt2(gray2, 'bior1.3')
LL, (LH, HL, HH) = coeffs2
ここでウェーブレット変換された係数はすべてfloat64になっているため、多くのメモリが必要になる。
print(type(LL[0][0])) ><class 'numpy.float64'>
そこでApproximation:LLのみをint16に変換し、スパース行列に変換するLH,HL,HHはfloat64として扱う。
LL2 = LL.astype(np.int16)
高次情報はマスク処理とスパース行列への変換は以下。
MLH=(np.abs(LH)>20) MHL=(np.abs(HL)>20) MHH=(np.abs(HH)>20) LH2=LH*MLH HL2=HL*MHL HH2=HH*MHH cLH = csr_matrix(LH2) cHL = csr_matrix(HL2) cHH = csr_matrix(HH2)
ここでスパース行列のメモリを評価するための関数を以下のように定義する。
def get_size_csr(csr): return csr.data.nbytes+csr.indices.nbytes+csr.indptr.nbytes
参照元は以下。 note.nkmk.me
以下のようにfloat64の高次情報とint16のApproximation:LL2のメモリとウェーブレット変換前のgray2
のメモリを比較すると半分強程度に圧縮されていることがわかる。
cLH = csr_matrix(LH2) cHL = csr_matrix(HL2) cHH = csr_matrix(HH2) print('Original memory: ',gray2.nbytes) sparse_mem = get_size_csr(cLH)+get_size_csr(cHH)+get_size_csr(cHL)+LL2.nbytes print('Compressed memory: ',sparse_mem) >Original memory: 131072 >Compressed memory: 71456
3. 画像の復元
確認のためint16に変換したLL2とマスク処理、スパース行列に変換した高次情報を用いて2Dウェーブレット逆変換を用いて画像が復元できることを確認した。
rLH = cLH.toarray() rHL = cHL.toarray() rHH = cHH.toarray() recov3=pywt.idwt2([LL2,(rLH,rHL,rHH)],'bior1.3') plt.figure(figsize=(15,8)) plt.subplot(1,3,1) plt.imshow(gray,cmap='gray',vmax=255,vmin=0) plt.title('original') plt.subplot(1,3,2) plt.imshow(LL,cmap='gray') plt.title('Approximation') plt.subplot(1,3,3) plt.imshow(recov3,cmap='gray',vmin=0,vmax=255) plt.title('recovered')
4. まとめ
今回は`ウェーブレット変換+スパース行列のが画像圧縮の効果を変数のメモリ量から確認した。