機械学習(SVM)で花とそれ以外の部分を自動分類してみた <その2>
こんばんは。らずべりーです。
ちょっと前のブログで機械学習による自動分類に無謀にもチャレンジし始めていました。
plant-raspberrypi3.hatenablog.com
今回、やっとその続きができたので書いていきます。
以下はこれまでのおさらいです。
目標
紅色の花の部分画像と、それ以外(葉や枝)の部分画像を自動で区別してくれる分類器を作成する
まだ難しい方法はハードルが高いので、上記のような単純な課題設定にしてみました。 紅色の花の画像として、自分で過去に撮影していたツバキとツツジの写真を使用しました。
実行環境
手順
- 一枚の画像から部分画像を作成
- 部分画像をフォルダ分け (花の部分かそれ以外か)
- 各フォルダからランダムに同数の画像を読み込んでラベルつけ
- 個々の画像データから、基本統計量を計算
- サポートベクターマシンで学習させ、分類器を作成
- 分類器の性能をテスト
4. 個々の画像データの基本統計量を計算
ここからが今回進めた部分になります。
4-1. 画像データの読み込み
まず、分類済みの画像データを読み込みます。
前回使用したのと同じ画像取り込み用の関数を流用。
import os import cv2 def img_bulk_read_cv2(path1,format=".png"): os.chdir(path1) all_files = os.listdir(path1) file_names = [i for i in all_files if i.endswith(format)] png_files = [cv2.imread(i) for i in file_names] return file_names, png_files path1 = "/usr/local/working/20171105-tsubaki_tsutsuji/flower" #花の部分の分類画像を格納したフォルダ path2 = "/usr/local/working/20171105-tsubaki_tsutsuji/others" #花以外の部分の分類画像を格納したフォルダ fn1, flower = img_bulk_read_cv2(path1,format="jpg") fn2, others = img_bulk_read_cv2(path2,format="jpg")
花の画像の数と花以外の部分の画像の数を調べ、多い方の画像から少ない方の画像と同じ数の画像をランダムにピックアップします。
len(flower) #133 len(others) #799 import random others_choice = random.sample(others,len(flower))
4-2. BGRをHSVに変換
OpenCVのBGR情報をHSVに変換する関数を利用してH, S, Vを個別に取り出す関数を作成します。
過去の記事でOpenCVの関数を使いやすくするための関数を作成していたので、それを活用しました。
plant-raspberrypi3.hatenablog.com
def bgr2h_s_v(img): return cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV)) h,s,v = bgr2h_s_v(flower[0])
変換後の画像の一例を示します。(元画像、H、S、Vの順)
花の部分
花以外の部分
結構違うのでちゃんと分類できそうな予感、、、
4-3. 画像の基本統計量を計算
個々の画像のH、S、Vそれぞれについて、基本統計量を求めていきます。
画像データは2次元データなので、これを1次元データに変換する必要があります。
基本統計量としてpandas.describe()
で計算できるものに加え、最頻値・尖度・歪度を追加したものをまとめてpandasシリーズとnumpyアレイで返す関数を作成しました。最頻値・尖度・歪度はscipy.stats
で計算できます。
参照URL
import pandas as pd import numpy as np import scipy.stats as ss def img_stats(img): array1 = img.flatten() #2次元データを1次元データに変換 index_list = list(pd.Series(array1).describe().index) value_list = list(pd.Series(array1).describe().values) mode = float(ss.mode(array1)[0]) kurtosis = ss.kurtosis(array1) skew = ss.skew(array1) index_list += ["mode","kurtosis","skew"] value_list += [mode, kurtosis, skew] return pd.Series(value_list, index=index_list), np.array(value_list) stat_df, stat_array = img_stats(h)
上で示した花部分の画像のHの統計値は以下の通り。
count 31212.000000 mean 144.073049 std 45.049873 min 0.000000 25% 156.000000 50% 158.000000 75% 160.000000 max 179.000000 mode 158.000000 kurtosis 4.544948 skew -2.522000 dtype: float64
これを個々の画像のH、S、Vについて求めていきます。
今回はここまでで力尽きたので、続きはまた後日、、、
2017/11/12 18:25
その3をアップしました!