# 第3回高木研究室勉強会
## 必要なものをインストール
<!-- * glob
```
$ pip install glob
``` -->
* OpenCV2
```
$ pip install opencv-python
```
* Keras
```
$ pip install keras
$ pip install tensorflow
```
* PIL
```
$ pip install pillow
```
## データフレームを整形しよう
1. 前回作成したデータフレームを読み込もう
```python=
import pandas as pd
if __name__=="__main__":
df = pd.read_csv(csvのpath)
print(df["着差"])
```
1. NaNの列を削除する
```python=
import pandas as pd
if __name__=="__main__":
df = pd.read_csv(csvのpath)
#ここの行を追記
df.drop(df.loc[pd.isnull(df["着差"])].index, inplace=True)
print(df["着差"])
```
1. indexを整える
```python=
import pandas as pd
if __name__=="__main__":
df = pd.read_csv(csvのpath)
df.drop(df.loc[pd.isnull(df["着差"])].index, inplace=True)
#ここの行を追記
df = df.reset_index(drop=True).copy()
print(df["着差"])
```
1. `map`と`lambda`を使ってみよう
```python=
import pandas as pd
# こkの関数を追記
def minus_to_zero(x):
if x < 0:
return 0
return x
if __name__ == "__main__":
df = pd.read_csv("csv/tabel.csv")
df.drop(df.loc[pd.isnull(df["着差"])].index, inplace=True)
df = df.reset_index(drop=True).copy()
# ここの行を追記
df["着差_マイナス排除"] = df["着差"].map(lambda x : minus_to_zero(x))
print(df["着差_マイナス排除"])
```
## 画像の加工方法を覚えよう
1. 前回のコードを利用して、好きな画像を2種類収集しよう
2. サイズを統一
```python=
import os
import cv2
import glob
word_list = [ディレクトリのリスト]
for word in word_list:
os.makedirs("./resize/"+word, exist_ok=True)
in_dir = "./assets/"+word+"/*.jpg"
out_dir = "./resize/"+word
img_list = glob.glob(in_dir)
# print(img_list)
for i, img_path in enumerate(img_list):
img_data = cv2.imread(img_path)
img_resize = cv2.resize(img_data,dsize=(64,64))
fileName = os.path.join(out_dir,str(i)+"_"+".jpg")
cv2.imwrite(str(fileName),img_resize)
```
3. テストデータと学習データに分ける
```python=
import shutil
import random
import glob
import os
word_list = [ディレクトリのリスト]
os.makedirs("./test",exist_ok=True)
for word in word_list:
in_dir = "./resize/" + word + "/*.jpg"
img_list = glob.glob(in_dir)
random.shuffle(img_list)
os.makedirs("./test/"+word, exist_ok=True)
for t in range(len(img_list)//5):
shutil.move(str(img_list[t]), "./test/"+word)
```
4. いくつか加工しよう
```python=
import os
import cv2
import glob
def mosaic(img_data, scale):
h,w = img_data.shape[:2]
dst = cv2.resize(img_data, dsize=None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST)
dst = cv2.resize(dst, dsize=(w, h), interpolation=cv2.INTER_NEAREST)
return dst
word_list = ["リンゴ","バナナ","ブドウ"]
for word in word_list:
os.makedirs("./data/"+word, exist_ok=True)
in_dir = "./resize/" + word + "/*.jpg"
out_dir = "./data/" + word
img_list = glob.glob(in_dir)
for i, img_path in enumerate(img_list):
img_data = cv2.imread(img_path)
fileName = os.path.join(out_dir,str(i)+"_ori.jpg")
cv2.imwrite(str(fileName), img_data)
# 閾値
img_thr = cv2.threshold(img_data, 80, 255, cv2.THRESH_TOZERO)[1]
fileName = os.path.join(out_dir,str(i)+"_thr.jpg")
cv2.imwrite(str(fileName), img_thr)
# ぼかし
img_gas = cv2.GaussianBlur(img_data, (3, 3), 0)
fileName = os.path.join(out_dir,str(i)+"_gas.jpg")
cv2.imwrite(str(fileName), img_gas)
# コントラスト
img_res = cv2.convertScaleAbs(img_data, alpha=0.6, beta=0.0)
fileName = os.path.join(out_dir,str(i)+"_res.jpg")
cv2.imwrite(str(fileName), img_res)
# モザイク
img_dst = mosaic(img_data, 0.6)
fileName = os.path.join(out_dir,str(i)+"_dst.jpg")
cv2.imwrite(str(fileName), img_dst)
```
5. 特徴量を抽出する計算式を定義しよう
```python=
import os
import cv2
import numpy as np
#import matplotlib.pyplot as plt
from keras.layers import Activation, Conv2D, Dense, Flatten, MaxPooling2D
from keras.models import Sequential
from keras.utils.np_utils import to_categorical
word_list = ["リンゴ","バナナ","ブドウ"]
# 教師データのラベル付け
X_train = []
Y_train = []
i = 0
for word in word_list:
#ファルダーの中身の画像を一覧にする
img_file_name_list=os.listdir("./data/"+word)
#画像ファイルごとに処理
for img_file_name in img_file_name_list:
#パスを結合
n=os.path.join("./data/"+word+"/"+img_file_name)
img_data = cv2.imread(n)
#色成分を分割
b,g,r = cv2.split(img_data)
#色成分を結合
img = cv2.merge([r,g,b])
X_train.append(img)
Y_train.append(i)
i += 1
# テストデータのラベル付け
X_test = [] # 画像データ読み込み
Y_test = [] # ラベル(名前)
#飲み物の名前ごとに処理する
i = 0
for word in word_list:
img_file_name_list=os.listdir("./test/"+word)
#確認
print(len(img_file_name_list))
#ファイルごとに処理
for img_file_name in img_file_name_list:
n=os.path.join("./test/" + word + "/" + img_file_name)
img_data = cv2.imread(n)
#色成分を分割
b,g,r = cv2.split(img_data)
#色成分を結合
img = cv2.merge([r,g,b])
X_test.append(img)
# ラベルは整数値
Y_test.append(i)
i += 1
#配列化
X_train=np.array(X_train)
X_test=np.array(X_test)
#ラベルをone-hotベクトルにする?
y_train = to_categorical(Y_train)
y_test = to_categorical(Y_test)
# モデルの定義
model = Sequential()
#畳み込みオートエンコーダーの動作
#ここの64は画像サイズ
#画像サイズがあっていないと、エラーが発生する
#3×3のフィルターに分ける
model.add(Conv2D(input_shape=(64, 64, 3), filters=32,kernel_size=(3, 3),
strides=(1, 1), padding="same"))
#2×2の範囲で最大値を出力
model.add(MaxPooling2D(pool_size=(2, 2)))
#畳み込みオートエンコーダーの動作
#3×3のフィルターに分ける
model.add(Conv2D(filters=32, kernel_size=(3, 3),
strides=(1, 1), padding="same"))
#2×2の範囲で最大値を出力
model.add(MaxPooling2D(pool_size=(2, 2)))
#畳み込みオートエンコーダーの動作
#3×3のフィルターに分ける
model.add(Conv2D(filters=32, kernel_size=(3, 3),
strides=(1, 1), padding="same"))
#2×2の範囲で最大値を出力
model.add(MaxPooling2D(pool_size=(2, 2)))
#1次元配列に変換
model.add(Flatten())
#出力の次元数を256にする
model.add(Dense(256))
#非線形変形の処理をするらしい
model.add(Activation("sigmoid"))
#出力の次元数を128にする
model.add(Dense(128))
#非線形変形の処理をするらしい
model.add(Activation('sigmoid'))
#出力の次元数を3にする
model.add(Dense(3))
#非線形変形の処理をするらしい
model.add(Activation('softmax'))
# コンパイル
model.compile(optimizer='sgd',
loss='categorical_crossentropy',
metrics=['accuracy'])
# 学習
history = model.fit(X_train, y_train, batch_size=128,
epochs=50, verbose=1, validation_data=(X_test, y_test))
# 汎化制度の評価・表示
score = model.evaluate(X_test, y_test, batch_size=128, verbose=0)
print('validation loss:{0[0]}\nvalidation accuracy:{0[1]}'.format(score))
# モデルを保存
model.save("./flute.h5")
```
6. 水増しした場合としなかった場合の評価
* 水増しあり:精度81%
* 水増しなし:精度67.5%
## カスケード分度器を使ってみよう
* 人の顔を切り取ろう
1. なんでもよいので、人の顔が映っている画像を保存する
2. カスケード分度器を使って顔を切り取る
```python=
import cv2
import os
from PIL import Image
# カスケード分度器を作成
face_cascade_path = os.path.join(cv2.data.haarcascades, "haarcascade_frontalface_default.xml")
face_cascade = cv2.CascadeClassifier(face_cascade_path)
#バウンディングボックス座標データを取得
def Get_Bounding_Box(img_path):
#画像を読み込む
img_b = cv2.imread(img_path)
if img_b is None:
print("No Object")
return -1
#ここでオブジェクトを検出
#バウンディングボックスもろもろ検出してる
img_b_gray = cv2.cvtColor(img_b, cv2.COLOR_BGR2GRAY)
#バウンディングボックスの座標情報をゲット
face = face_cascade.detectMultiScale(img_b_gray)
bbox = []
for x, y, w, h in face:
bbox.append([x,y,x+w,y+h])
print(face)
#バウンディングボックス座標データを返却
return bbox
def Cut_draw(img_path, bbox_Coordinate):
#画像読み込み
#RGBモードとしてやる RGBAモードだと上手く行かない
img = Image.open(img_path).convert("RGB")
#画像を切り取る
#座標を格納する箱
item_position_list = []
i = 0
#座標を一個ずつ読み取る
for item_position in bbox_Coordinate:
for item_coordinate in item_position:
item_position_list.append(item_coordinate)
#取得した座標のところだけを抜き取る
img_crop = img.crop(item_position_list)
img_crop.convert("RGB")
#画像出力
img_crop.save("./assets/cut_person/cut_image{0}.jpg".format(i))
i += 1
#座標リストを空にする
item_position_list.clear()
if __name__ == "__main__":
#使用する画像のパスを指定する
img_path = "./assets/person/kaki.jpg"
#切り取った画像を保存するフォルダーを作成
os.makedirs("./assets/cut_person", exist_ok=True)
#バウンディングボックスの座標データを取得&格納
bbox_Coordinate = Get_Bounding_Box(img_path)
print(bbox_Coordinate)
if type(bbox_Coordinate) is not int:
#画像の抜き取り
Cut_draw(img_path, bbox_Coordinate)
```
* カスケード分度器一覧
<table>
<thead><tr>
<th>ファイル名</th>
<th>内容</th>
<th>特徴量</th>
</tr>
</thead>
<tbody>
<tr>
<td>haarcascade_eye.xml</td>
<td>目</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_eye_tree_eyeglasses.xml</td>
<td>メガネ</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_frontalcatface.xml</td>
<td>猫の顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_frontalcatface_extended.xml</td>
<td>猫の顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_frontalface_alt.xml</td>
<td>顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_frontalface_alt2.xml</td>
<td>顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_frontalface_alt_tree.xml</td>
<td>顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_frontalface_default.xml</td>
<td>顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_fullbody.xml</td>
<td>全身</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_lefteye_2splits.xml</td>
<td>左目</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_licence_plate_rus_16stages.xml</td>
<td>ロシアのナンバープレート</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_lowerbody.xml</td>
<td>下半身</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_profileface.xml</td>
<td>顔 (正面)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_righteye_2splits.xml</td>
<td>右目</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_russian_plate_number.xml</td>
<td>ロシアのナンバープレート</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_smile.xml</td>
<td>顔 (笑顔)</td>
<td>Haar-like</td>
</tr>
<tr>
<td>haarcascade_upperbody.xml</td>
<td>上半身</td>
<td>Haar-like</td>
</tr>
</tbody>
</table>
## KerasDocuments
[ここ](https://keras.io/ja/preprocessing/image/)のサイトにいろんなアルゴリズムが載ってます。