Posted at

Coursera Machine Learningの課題をPythonで: ex7-1 (K-meansクラスタリングで画像圧縮)

More than 3 years have passed since last update.

CourseraのMachine LearningのMatlab/Octaveプログラミング課題をPythonで実装していくシリーズ。

今回は教師なし学習の最初の課題、K平均クラスタリングをやります。


はじめに:課題の内容

元画像(.png)は、RGBそれぞれ256階調で、1677万色のもの。この色情報を、K平均クラスタリングによって16のクラスタに分類し、16色の画像にするのが課題です。


PILライブラリのインストール

画像処理にはpillowというライブラリを使うのでインストールしておきましょう。

pip install pillow

pillowのドキュメントはこちら


コードの最初:ライブラリをインポート

import numpy as np

from PIL import Image
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans


最初に画像を読み込み

画像データの読み込みにはPIL.Image.open() を使い、128 x 128 x 3 の3次元のnumpy arrayに読み込みます。これを、reshape(128*128, 3)して、クラスタリングに渡せる形の 16384 x 3 の2次元行列に変換(flatten)します。

img = np.array(Image.open('bird_small.png')) # imgは128x128x3 の3次元行列 

img_flat = img.reshape(128*128,3)/255 # 16384x3 の2次元行列に変換


クラスタリングを実施

クラスタリングは、KMeans.fit(data)一発でできます。KMeansのパラメータでn_clusters=16と、16個のクラスタに分けるよう指定します。

model = KMeans(n_clusters=16).fit(img_flat)


結果の表示

クラスタリングの結果、各ピクセルがどのクラスタに分類されたかは model.labels_(0-15の数字)、各クラスタの重心の値はmodel.cluster_centers_(16x3行列) に格納されています。

これを使って、各ピクセルの値をクラスタの重心で置き換えた行列は、model.cluster_centers_[model.labels_]として作成することができます(16384 x 3 の2次元行列)。これを、画像で表示できる形の 128 x 128 x 3 の3次元行列に戻すため、reshape(128, 128, 3)します。

img_comp = model.cluster_centers_[model.labels_].reshape(128,128,3)

plt.imshow(img_comp)

元画像と結果の画像はこちら。16色に減色されているのがわかります。

ex7-1.png

ex7-2.png


全コード

全コードはこちらになります。短いですね。

import numpy as np

from PIL import Image
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

img = np.array(Image.open('bird_small.png')) # imgは128x128x3 の3次元行列
img_flat = img.reshape(128*128,3)/255 # 16384x3 の2次元行列に変換

model = KMeans(n_clusters=16).fit(img_flat)
img_comp = model.cluster_centers_[model.labels_].reshape(128,128,3)
plt.imshow(img_comp)


おわりに

10ウン年前に画像処理を研究する学生だった頃にK平均クラスタリングをC++でスクラッチ実装しましたが、数百行のプログラムにはなっていたような...

ライブラリが整備されて、いい時代ですね。