plant-raspberrypi3のブログ

ラズベリーパイ3とPythonに挑戦して、植物を愛でたり画像を加工したりします。最近はscikit-imageの勉強してます。

機械学習(SVM)で花とそれ以外の部分を自動分類してみた <その2>

こんばんは。らずべりーです。

ちょっと前のブログで機械学習による自動分類に無謀にもチャレンジし始めていました。

plant-raspberrypi3.hatenablog.com

今回、やっとその続きができたので書いていきます。

以下はこれまでのおさらいです。

目標

紅色の花の部分画像と、それ以外(葉や枝)の部分画像を自動で区別してくれる分類器を作成する

まだ難しい方法はハードルが高いので、上記のような単純な課題設定にしてみました。 紅色の花の画像として、自分で過去に撮影していたツバキとツツジの写真を使用しました。

実行環境

手順

  1. 一枚の画像から部分画像を作成
  2. 部分画像をフォルダ分け (花の部分かそれ以外か)
  3. 各フォルダからランダムに同数の画像を読み込んでラベルつけ
  4. 個々の画像データから、基本統計量を計算
  5. サポートベクターマシンで学習させ、分類器を作成
  6. 分類器の性能をテスト

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の順)

花の部分

f:id:plant-raspberrypi3:20171112013115j:plain f:id:plant-raspberrypi3:20171112013134j:plain f:id:plant-raspberrypi3:20171112013148j:plain f:id:plant-raspberrypi3:20171112013157j:plain

花以外の部分

f:id:plant-raspberrypi3:20171112013232j:plain f:id:plant-raspberrypi3:20171112013244j:plain f:id:plant-raspberrypi3:20171112013255j:plain f:id:plant-raspberrypi3:20171112013305j:plain

結構違うのでちゃんと分類できそうな予感、、、

4-3. 画像の基本統計量を計算

個々の画像のH、S、Vそれぞれについて、基本統計量を求めていきます。

画像データは2次元データなので、これを1次元データに変換する必要があります。

基本統計量としてpandas.describe()で計算できるものに加え、最頻値・尖度・歪度を追加したものをまとめてpandasシリーズとnumpyアレイで返す関数を作成しました。最頻値・尖度・歪度はscipy.statsで計算できます。

参照URL

www.codereading.com

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をアップしました!

plant-raspberrypi3.hatenablog.com