つれづれなる備忘録

日々の発見をあるがままに綴る

Pythonによるデータ処理12 ~ ウェーブレット変換5

 前回はウェーブレット変換で高次特徴量はマスクとスパース行列を使うことで、画像を構成する要素数が削減できることを示したが、今回はメモリ削減の効果について検証してみる。

atatat.hatenablog.com

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)

"Boat"
Boat

まず、メモリの使用量を調べるコマンドとして変数名.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')

"スパース行列から画像復元2"
スパース行列から画像復元2

4. まとめ

今回は`ウェーブレット変換+スパース行列のが画像圧縮の効果を変数のメモリ量から確認した。