【失敗】機械学習で堀北真希を探せ

#【環境】
　windows8.1
　Anaconda(python2.7)

#【概要】
　堀北真希かどうか画像から決定するコードを書きました。
　顔画像フォルダを集めて、それらを数値化してscikit-learnで学習させます。


```text:フォルダ構成
|---face_category
　　　　　|---horikita_face(堀北真希の顔画像フォルダ　２００個)
　　　　　|---joyu_face(堀北真希以外の顔画像フォルダ　２００個)
　　　　　|---horikita_siken(テスト用の堀北真希の画像フォルダ　２０個)
　　　　　|---face_rec2.py(horikita_sikenの画像から顔を抽出)
　　　　　|---LinearSVC.py(メイン処理)
　　　　　|---haarcascade_frontalface_alt.xml(カスケードファイル)
```

```py:face_rec2.py
#-*- coding:utf-8 -*-
def picture_face(before_image, num):

    import cv2
    import os
    import sys
    
    cascade_path = "haarcascade_frontalface_alt.xml"
    
    #ファイル読み込み
    image_file = cv2.imread('C:/Users/nobu/Desktop/my_programs/face_category/horikita_siken/%s' % before_image)
    
    #グレースケール変換
    image_gray = cv2.cvtColor(image_file, cv2.COLOR_BGR2GRAY)
    
    #カスケード分類器の特徴量を取得する
    cascade = cv2.CascadeClassifier(cascade_path)
    
    #物体認識（顔認識）の実行
    facerect = cascade.detectMultiScale(image_gray, scaleFactor=1.2, minNeighbors=2, minSize=(10, 10))
    
    if facerect == None:
        sys.exit()
    
    for rect in facerect:
        #顔だけ切り出して保存
        x = rect[0]
        y = rect[1]
        width = rect[2]
        height = rect[3]
        dst = image_file[y:y+height, x:x+width]
        resize_image = cv2.resize(dst,(256,256))
        new_image_path = 'C:/Users/nobu/Desktop/my_programs/face_category/' + str(num) + '_face.jpg'
        print new_image_path
        cv2.imwrite(new_image_path, resize_image)
```

　

```py:LinearSVC.py
# -*- coding:utf-8 -*-

from sklearn.svm import LinearSVC
from PIL import Image
import os
import glob
import numpy as np
import face_rec2

current_dir = os.getcwd()

# 学習データ
#堀北真希の画像を数値へ変換
horikita_list = glob.glob(current_dir + "\\horikita_face\\*") 

horikita_dim2 = []

for image in horikita_list:
    #システムファイルの除外
    if image == current_dir + "\\horikita_face\\Thumbs.db":
        continue
    else:
        x = np.array([])
        horikita_dim3 = np.array(Image.open(image).convert('L'))
        #scikit-learnでは３次元以上は扱えないようなので、２次元へ変換
        for i in xrange(256):
            x = np.r_[x,horikita_dim3[i]]
        horikita_dim2.append(x)

data_training1 = horikita_dim2

#堀北真希以外の画像を数値へ変換
joyu_list = glob.glob(current_dir + "\\joyu_face\\*") 

joyu_dim2 = []

for image in joyu_list:
    #システムファイルの除外
    if image == current_dir + "\\joyu_face\\Thumbs.db":
        continue
    else:
        x = np.array([])
        joyu_dim3 = np.array(Image.open(image).convert('L'))
        #scikit-learnでは３次元以上は扱えないようなので、２次元へ変換
        for i in xrange(256):
            x = np.r_[x,joyu_dim3[i]]
        joyu_dim2.append(x)
data_training2 = joyu_dim2

data_training = np.r_[data_training1, data_training2]

#ラベル設定
label_training = []
for i in xrange(400):
    if i < 200:
        label_training.append(1)
    else:
        label_training.append(0)

 # 学習
estimator = LinearSVC(C=0.5)
estimator.fit(data_training, label_training)

j = 0
# 試験データ
for i in xrange(1,21):
    face_rec2.picture_face(str(i) + '.jpg', i)
    horikita_siken = np.array([])
    try:
        horikita = np.array(Image.open('C:/Users/nobu/Desktop/my_programs/face_category/' + str(i) + '_face.jpg').convert('L'))
        for j in xrange(256):
                    horikita_siken = np.r_[horikita_siken,horikita[j]]
        data_test = horikita_siken
        
        # 予測するよー
        label_prediction = estimator.predict(data_test)
        
        if label_prediction == 1:
            print "----------------------------------------------"
            print str(i) + ".jpg　は堀北真希です"
            print "----------------------------------------------"
        else:
            print "----------------------------------------------"
            print str(i) + ".jpg　は堀北真希ではありません"
            print "----------------------------------------------"
    except:
        print "----------------------------------------------"
        print str(i) + ".jpgは処理できませんでした"
        print "----------------------------------------------"
        continue
```

#【結果】
　失敗・・・ :weary: 
　テスト用の堀北真希の顔画像フォルダ　２０個でテストしましたが、なぜか
　「堀北真希ではありません」といくつか出力されてしまいます。
　何か解決策や改善点があれば教えていただきたいです。

#【参考サイト】
[scikit-learnで機械学習を試す SVM](http://qiita.com/yasunori/items/8720c85e75b4679cae47)
[OpenCVで顔認識を行い、顔の部分だけトリミングして保存する【Python】](http://famirror.hateblo.jp/entry/2015/12/19/180000)