Ccmmutty logo
Commutty IT
0 pv3 min read

opencv-pythonでkmean法を試してみよう

https://cdn.magicode.io/media/notebox/blob_uANsGUx

初めに

テストも兼ねた単発記事です!教師なし学習で有名なkmean法は自身で作成するのもよいですが画像処理モジュールであるopencvにも関数が用意されています。
お手軽に機械学習が体験できおすすめです。

kmean法とはなにか

kmean法とはクラスタリングに使われる教師なし学習のことで具体的に初めにデータを適当にクラスタリングし、それぞれのクラスタの重心に合わせて再クラスタし、最終的に重心が変動しなくなったらクラスタリング終了というものです。

cv2.kmeansの使い方

kmeans: (data: Any, K: Any, bestLabels: Any, criteria: Any, attempts: Any, flags: int, centers: ... = ...)
dataは入力データのことで必ずnp.float32型のデータであること、それぞれの特徴ベクトルが一列であることという決まりがあります。
Kは分類したいクラスタの数です。
criteriaは繰り返し処理の終了条件です。具体的に以下のフラグがあります。
cv2.TERM_CRITERIA_EPS - 指定された精度に到達したら繰り返し計算を終了する.
cv2.TERM_CRITERIA_MAX_ITER - 指定された繰り返し回数に到達したら繰り返し計算を終了する.
flagsは重心の初期値を決める方法を指定します.普通は二つのフラグ cv2.KMEANS_PP_CENTERScv2.KMEANS_RANDOM_CENTERS が使われます。 PPのほうは初期値自身の重心が偏らないようになっているので精度向上に期待できます

プログラム

具体的なプログラムです。このページのヘッダになっている画像で画素のクラスタリング(代表色の抽出)をやってみたいと思います。
基本的にはcurlで画像をダウンロードしてそれを読み込むようにしています。
matplotlibで日本語表示させるためjapanize-matplotlibを使用しています。
python
%matplotlib inline
#curlで画像を取得しています
!curl -s -o test.jpeg https://cdn.apollon.ai/media/notebox/blob_uANsGUx
!pip install japanize-matplotlib --quiet

import matplotlib.pyplot as plt
import japanize_matplotlib
import cv2
import numpy as np
import os
#取得した画素を一列に並べる
def make_rect(bgrs,num):
    img=[[bgrs[0] for ii in range(num)] for i in range(num)]
    for ffi in range(1,len(bgrs)):
        tem=[[bgrs[ffi] for ii in range(num)] for i in range(num)]
        img=np.hstack([tem,img])
    return np.array(img,np.uint8)

#kmean法でクラスタリング、各クラスの重心の画素を表示
def make_kmean(img):
    criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0)

    colors= img.reshape(-1, 3).astype(np.float32)

    ret,label,center=cv2.kmeans(colors,4,None,criteria,10,cv2.KMEANS_PP_CENTERS)
    os.remove("test.jpeg")
    plt.title("入力画像")
    plt.imshow(img[:,:,::-1])
    plt.show()
    plt.title("出力画像")
    plt.imshow(make_rect(center,50)[:,:,::-1])
    #表示
    plt.show()

make_kmean(cv2.imread("test.jpeg"))

まとめ

簡単な組み合わせでクラスタリングできるので、メインカラーを自動的取得するなどいろいろな使い方ができます!

Discussion

コメントにはログインが必要です。