つまりなにしたの?
Pythonではデータ圧縮とアーカイブが標準ライブラリにあり、そのうちデータ圧縮をやる。
バイナリデータをバイナリデータのまま圧縮して変数に格納する。
ensekitt.hatenablog.com
の続き
圧縮アルゴリズム
基本的には、簡易関数のcompressとdecompressを使う方法にする
13. データ圧縮とアーカイブ — Python 3.6.5 ドキュメント
定性的なことは前編に書いた。
やってみる
やって見るデータ
個人的にちょっとやってみたいデータがあるので以下の4つのデータを圧縮してみる。
- テキスト
日本語で1万字程度のテキストデータ
Wikipediaの秀逸な記事リストから長くてそこそこ語彙が多そうなので
シビュラの信託を選んだ。全体では2〜3万字あるので、先頭から1万字分だけ使った。
- 音声
10分程度の音声(WAVE形式のステレオ音楽)
iMovieの音声データを適当につなげて書き出したものを使った。
無音区間がなく、そこそこ高音まであるものを選ぶ
- 画像
3840x2160のフルカラー画像
いつもサムネイルに使わせてもらっているUnsplashからやや拡大して作った。
真っ黒とか真っ白なところの少ないもので周波数高めな画像を選んだ。
Jezael Melgoza (@lyonpixel) | Unsplash Photo Community
- 大きいバイナリ
UbuntuのOSイメージ
www.ubuntu.com
やりかた
データの読み込み
ここではデータを取り込んで、bytes型のdataに格納する。
適当にクイックルックして、元のサイズを表示する。
- テキスト
with open("text.txt", 'r') as f: data = f.read().encode('utf-8') print("冒頭", data[:100].decode('utf-8')) print("raw size: ", len(data))
- 音声
import wave import numpy as np with wave.open("audio.wav", 'r') as f: data = f.readframes(f.getnframes()) npdata = np.frombuffer(data,'int16') print("raw size: ", len(data)) import matplotlib.pyplot as plt plt.plot(npdata[10000:50000:2]) plt.plot(npdata[10001:50001:2]) plt.show()
- 画像
import cv2 import matplotlib.pyplot as plt data = cv2.imread("img.png") plt.imshow(data)
- 大きいイメージ
with open("img.iso", 'rb') as f: data = f.read() print("raw size: ", len(data))
圧縮を行うコード
3種類の圧縮を行いつつ、各圧縮方式の圧縮率と圧縮率を計算してみた。
compressの引数に圧縮のレベルがある場合はそのレベルを1ずつ変えてどのような結果になるか試してみた。
import gzip levels = [i for i in range(10)] print("gzip") for l in levels: %timeit c_data = gzip.compress(data, l) c_data = gzip.compress(data, l) print("gzip level: ", l, ", size: ", len(c_data), ", rate: ", len(c_data)/len(data)) import bz2 levels = [i for i in range(1,10)] print("\nbz2") for l in levels: %timeit c_data = bz2.compress(data, l) c_data = bz2.compress(data, l) print("bz2 level: ", l, ", size: ", len(c_data), ", rate: ", len(c_data)/len(data)) import lzma print("\nlzma") %timeit c_data = lzma.compress(data) c_data = lzma.compress(data) print("lzma level: ", l, ",size: ", len(c_data), ", rate: ", len(c_data)/len(data))
実行結果
テキストで出てくるものを整形し直している
- テキストの場合
かなり高い圧縮率がどの形式においても発揮された
- 音声の場合
- 画像の場合
Bz2があまりうまく言っていない様子
- 大きいイメージ
lzma圧倒的に時間がかかっている
おわりに
gzipが伝送コストがよっぽど高い場合以外は使い勝手が良さそう。
今更だけど、解答の速度もはかってみればよかった。
今度気が向いたらやってみる。