# 第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/)のサイトにいろんなアルゴリズムが載ってます。