Study Blog

自分の興味関心が向いたものを、好きな時好きなだけ気分で勉強したことを記すブログ

Raspberry Pi4 画像認識 ~⑤独自画像学習 アノテーションデータ変更~

前回はじゃんけんの手をアノテーションしました。
今回はそれを「Tensorflow model maker」というTensorflowが作成したツールに読み込める様、変更していきます。

コードはgoogle colaboratoryで共有していますので、適宜変更して頂けると使用できます。
コードの解説を簡単に行っていきます。

1. 下準備

#必要なライブラリをインポートする
import pandas as pd
import numpy as np
import cv2

pandasはアノテーションcsvを確認、編集するため
numpyはアノテーションcsvの数値を変更・計算するため
cv2(opencv)は画像を表示、確認するため
に使用します。

# MIN_DIR,CSVのパスは適宜変更してください
MAIN_DIR = "/content/drive/MyDrive/ML/Tensorflow/dataset_janken/"
CSV = MAIN_DIR + "janken_dataset-export.csv"

アノテーションcsvの格納されているディレクトリを「MAIN_DIR」に指定
csvのパスを「CSV」で指定

# pandasでcsvを確認
df = pd.read_csv(CSV)
df


	image	xmin	ymin	xmax	ymax	label
0	choki_01.jpg	68.710074	15.982533	236.703522	221.397380	Scissors
1	IMG_0728.JPG	62.420147	35.371179	245.090090	195.458515	rock
2	IMG_0729.JPG	65.565111	21.222707	256.097461	193.362445	rock
3	IMG_0731.JPG	73.951679	24.104803	217.047502	205.938865	rock
4	IMG_0730.JPG	84.434889	26.724891	239.848485	211.441048	rock
...	...	...	...	...	...	...
162	IMG_0890.JPG	102.780508	51.615721	237.489762	192.576419	rock
163	IMG_0892.JPG	48.267813	26.200873	208.136773	189.694323	rock
164	IMG_0891.JPG	91.773137	41.659389	235.917281	195.458515	rock
165	IMG_0893.JPG	89.152334	27.510917	248.759214	200.174672	rock
166	IMG_0894.JPG	47.481572	24.890830	213.116298	195.982533	rock

pandasの説明はここでは省きます。csvの中身が確認できます。

2. csvファイルの変更

2-1. 画像名を画像パスに変更する

# imageの値をパスに変更する
for idx, col in enumerate(df.image):
    df.image[idx] = MAIN_DIR + col

df.head()


image	xmin	ymin	xmax	ymax	label
0	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	68.710074	15.982533	236.703522	221.397380	Scissors
1	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	62.420147	35.371179	245.090090	195.458515	rock
2	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	65.565111	21.222707	256.097461	193.362445	rock
3	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	73.951679	24.104803	217.047502	205.938865	rock
4	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	84.434889	26.724891	239.848485	211.441048	rock

2-2. xmin/ymin/xmax/ymaxの値を正規化する

img = cv2.imread(df.image[0])
y, x, _ = img.shape
for idx, col in enumerate(df.xmin):
    df.xmin[idx] = col / x
for idx, col in enumerate(df.ymin):
    df.ymin[idx] = col / y
for idx, col in enumerate(df.xmax):
    df.xmax[idx] = col / x
for idx, col in enumerate(df.ymax):
    df.ymax[idx] = col / y
df.head()


image	xmin	ymin	xmax	ymax	label
0	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	0.214719	0.066594	0.739699	0.922489	Scissors
1	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	0.195063	0.147380	0.765907	0.814410	rock
2	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	0.204891	0.088428	0.800305	0.805677	rock
3	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	0.231099	0.100437	0.678273	0.858079	rock
4	/content/drive/MyDrive/ML/Tensorflow/dataset_j...	0.263859	0.111354	0.749527	0.881004	rock

今回は、すべての画像が同じ大きさなので、1枚の画像を参照しています。
1枚の画像の縦・横のpx数を取得し、xmin/xmaxをxで、ymin/ymaxをyで割ることで、0.0-1.0の間の数値に正規化します。

2-3. 新たな列を追加して、列を並べ替える

df["type"] = ""
df["dummy_1"] = ""
df["dummy_2"] = ""
df["dummy_3"] = ""
df["dummy_4"] = ""
df = df.reindex(columns=["type","image","label","xmin","ymin","dummy_1","dummy_2","xmax","ymax","dummy_3","dummy_4"])
df.head()


	type	image	label	xmin	ymin	dummy_1	dummy_2	xmax	ymax	dummy_3	dummy_4
0		/content/drive/MyDrive/ML/Tensorflow/dataset_j...	Scissors	0.214719	0.066594			0.739699	0.922489		
1		/content/drive/MyDrive/ML/Tensorflow/dataset_j...	rock	0.195063	0.147380			0.765907	0.814410		
2		/content/drive/MyDrive/ML/Tensorflow/dataset_j...	rock	0.204891	0.088428			0.800305	0.805677		
3		/content/drive/MyDrive/ML/Tensorflow/dataset_j...	rock	0.231099	0.100437			0.678273	0.858079		
4		/content/drive/MyDrive/ML/Tensorflow/dataset_j...	rock	0.263859	0.111354			0.749527	0.881004		

tensorflow model makerの物体検出ツールではcsvの読み込み形式が決まっており、ダミーの列を追加し、既定の場所に数値が入っていなければうまく動作してくれません。

2-4. 列typeにtrain/validation/testを割り振る

tmp = df[df.label == "rock"].index.tolist()
train_index = tmp[0:int(len(tmp)*0.8)]
validation_index = tmp[int(len(tmp)*0.8):int(len(tmp)*0.9)]
test_index = tmp[int(len(tmp)*0.9):len(tmp)]

for idx in train_index:
    df["type"][idx] = "TRAIN"
for idx in validation_index:
    df["type"][idx] = "VALIDATION"
for idx in test_index:
    df["type"][idx] = "TEST"
tmp = df[df.label == "Scissors"].index.tolist()
train_index = tmp[0:int(len(tmp)*0.8)]
validation_index = tmp[int(len(tmp)*0.8):int(len(tmp)*0.9)]
test_index = tmp[int(len(tmp)*0.9):len(tmp)]

for idx in train_index:
    df["type"][idx] = "TRAIN"
for idx in validation_index:
    df["type"][idx] = "VALIDATION"
for idx in test_index:
    df["type"][idx] = "TEST"
tmp = df[df.label == "paper"].index.tolist()
train_index = tmp[0:int(len(tmp)*0.8)]
validation_index = tmp[int(len(tmp)*0.8):int(len(tmp)*0.9)]
test_index = tmp[int(len(tmp)*0.9):]

for idx in train_index:
    df["type"][idx] = "TRAIN"
for idx in validation_index:
    df["type"][idx] = "VALIDATION"
for idx in test_index:
    df["type"][idx] = "TEST"

次に、type列にtrain/validation/testという割り振りをします。
機械学習では、データを分割して、「学習用/検証用/試験用」として学習の時に、学習用画像を学習してモデルを作り、検証用画像でその正確性を評価します。
最終的に試験用画像で、最終的な学習モデルを評価します。

2-5. 保存

df.to_csv(MAIN_DIR + "dataset.csv", index=False)

以上までで行った処理したデータをcsvとして保存して終了です。

          • 関連記事-----

melostark.hatenablog.com
melostark.hatenablog.com
melostark.hatenablog.com
melostark.hatenablog.com
melostark.hatenablog.com
melostark.hatenablog.com
melostark.hatenablog.com
melostark.hatenablog.com