K-means(K平均法)で花の写真を色でクラスタリングする
K-Meansクラスタリングは、与えられたデータを自動的に分類するアルゴリズムであるクラスタリングの一種で、クラスタの平均を用い、与えられたクラスタ数k個に分類する手法です。(Wikipedia >> k平均法)
cv2.kmeans()を用いるとK-Meansクラスタリングが簡単に実装できます。
様々な色の花の写真を色に応じてクラスタリングします。写真全体のBGR各チャンネルの比率を特徴量として(特徴量3つ)、クラスタリングを行い、それぞれのクラスタ別にフォルダを作り画像ファイルを移動します。
関連記事
環境
準備
画像ファイルはフリー写真素材ぱくたそから花の写真25枚をダウンロードさせていただき、jupyter notebookファイル(***.ipynb)と同じディレクトリに、'flowers'ディレクトリを作成しそこに保存しました。
コード
import os import cv2 import numpy as np # 画像ファイルのあるフォルダの相対パス dir_path = 'flowers/' # フォルダ内のファイルのリスト生成 files = os.listdir(dir_path) # jpgファイルのリスト生成 files_jpg = [s for s in files if '.jpg' in s] list_all =[] for i in files_jpg: # ファイル数だけ繰り返す img = cv2.imread(dir_path+i) # 画像の読み出し #BGR各チャンネルの輝度をすべての輝度の合計で規格化しリスト化 bgr_sum = np.sum(img ,axis = (0,1)) b_ratio,g_ratio,r_ratio = bgr_sum/np.sum(bgr_sum) bgr_list = [b_ratio,g_ratio,r_ratio] list_all.append(bgr_list) # リストをndarrayに変換 list_all_n = np.array(list_all) # リストをfloat32に変換 list_all_n = np.float32(list_all_n) # 計算終了条件の設定。指定された精度(1.0)か指定された回数(10)計算したら終了 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 10, 1.0) # クラスター数 K = 4 # K-Meansクラスタリングの実施 ret,label,center=cv2.kmeans(list_all_n,K,None,criteria,10,cv2.KMEANS_RANDOM_CENTERS) # ラベル別ディレクトリ作成 for i in range(K): new_dir_path =dir_path+str(i) os.mkdir(new_dir_path) # クラスタリング結果に応じたディレクトリに画像ファイルを移動 for file_name,dir_name in zip(files_jpg,label): original_file_name = dir_path+file_name new_file_name = dir_path+str(int(dir_name))+'/'+file_name os.rename(original_file_name,new_file_name)
実行結果
label0に分類された画像はピンクや紫の花が多いようです。
label1には青い花が分類されました
label2には赤い花が分類されました
label3には黄色い花が分類されました
それなりに分類されましたが、黄色い花がlabel0に分類されるなど人間が分類する場合とは合わなそうな結果が見られます。今回用いた特徴量は写真全体のBGRチャンネル比を用いているため花以外の背景の色も加味されるためそこは改善の余地がありそうです。
以下のサイトを参考にさせていただきました
OpenCV >> K-Means Clustering in OpenCV
OpenCV-Python Tutorials 1 documentation >> OpenCVのK-Meansクラスタリング