どうもなまこです。
今回はプログラミングを勉強して得たアウトプットを紹介したいと思います。
私はPythonをメインにプログラミングを勉強しています。Pythonと言えばAI開発でよく用いられている言語です。現代のAIでは主に機械学習とディープラーニングが使われています。
今回はディープラーニングの技術を使って写真を自動で判別するアプリを作ってみました。
この記事ではPythonを初めとして、NumPy、TensorFlowのライブラリを使用していきます。また、iOSのアプリを作成するため、swiftとXcodeを使用していきます。細かい解説はしませんが要望あれば記事を追加していく予定です。

作成するもの
今回は自動車、オートバイ、自転車、歩行者を写真で見分けるアプリを作成していきます。iOSでアプリを起動し、写真と撮ると自動車かオートバイか自転車か歩行者を判別し、何パーセントの確率で一致しているか表示するアプリを作成します。
用意するもの
なんか料理みたいになってきましたね。でも開発ってそんなものかも。
学習データ用の写真
ディープラーニングを使用するため、学習用のデータが必要になります。今回の場合自動車、オートバイ、自転車、歩行者の写真をそれぞれ300枚ずつ用意します。画像はただでさえ情報を持っているのでそこまでサイズの大きい画像でなくても十分に学習することができます。今回は150×150のサイズにリサイズして集めました。
自力で集めようとするとしんどいのでAPIを使ってダウンロードを自動化して集めました。詳細はここでは書きませんがネットで調べるとさまざまな方法ありますので割愛します。こちらも需要があれば追加していこうかと思います。
GPU搭載のPC
ディープラーニングさせるためには高性能なGPUがあるのが理想です。少々値段が高いのでGPU搭載のPCがない場合はGoogle ColaboratoryのGPUを利用するのも手です。私はMacbook Airを使用していますがクラウドのGPUを使用すれば十分に戦えます。Google ColaboratoryのGPUを使用する方法は過去の記事にも記載していますので参考にしてみてください。

画像をバイナリファイルにする
画像はそのままだと扱えないので画像扱うデータに変換します。car, bicycle, motorcycle, pedestrianの各フォルダに300枚づつ保管しているjpgファイルを見つけ出し、Pillowで読み出し、NumPyでバイナリファイルにしていきます。
画像データをかさ増しする
同じ画像でも上下左右反転しても同一のものだと認識する必要があります。また、ディープラーニングはデータの数の多さが決めてとなるので、データをかさ増ししていきます。角度を少しすつ回転させたデータを作成します。さらに画像を反転したデータも追加していきました。
訓練データとテストデータに分ける
sklearnのモジュールを使って訓練データとテストデータを切り分けていきます。訓練データとテストデータをバイナリファイル(npyファイル)で保存します。
from PIL import Image
import os, glob
import numpy as np
from sklearn import model_selection
classes = ["car", "bicycle", "motorcycle", "pedestrian"]
num_class = len(classes)
image_size = 50
num_testdata = 50
# 画像の読み込み
X_train = []
X_test = []
Y_train = []
Y_test = []
for index, classlabel in enumerate(classes):
photos_dir = "./" + classlabel
files = glob.glob(photos_dir + "/*.jpg")
for i, file in enumerate(files):
if i >=300: break
image = Image.open(file)
image = image.convert("RGB")
image = image.resize((image_size, image_size))
data = np.asarray(image)
if i < num_testdata:
X_test.append(data)
Y_test.append(index)
else:
for angle in range(-20, 20, 5):
# 回転
img_r = image.rotate(angle)
data = np.asarray(img_r)
X_train.append(data)
Y_train.append(index)
# 反転
img_trans = image.transpose(Image.FLIP_LEFT_RIGHT)
data = np.asarray(img_trans)
X_train.append(data)
Y_train.append(index)
X_train = np.array(X_train)
X_test = np.array(X_test)
y_train = np.array(Y_train)
y_test = np.array(Y_test)
xy = (X_train, X_test, y_train, y_test)
np.save("./vehicle_aug.npy", xy)
モデルを作成する
上記のバイナリファイルを使ってモデルを学習させていきます。
モデルを学習させる
畳み込みニューラルネットワーク(以後CNN)というものを使ってモデルを学習していきます。CNNについては以下のサイトを参考ください。
活性関数はreluを使用していきます。
他のプログラムはロースペックのPCでもそれほど時間はかかりませんが、モデルを学習させるここからはGPU搭載のPCを使うのがおすすめです。Google ColaboratoryのGPUを拝借すれば数秒で学習が可能です。過去にアップした動画ですがいかに早く学習できるかわかることができます。
精度を上げるようにパラメータを調整する
Testの精度が6.5〜7割くらいであれば十分かと思います。精度が低い場合はエポックや学習率を変更して精度をあげていきます。
学習モデルをh5ファイルで保存する
学習モデルをh5ファイルに保存していきます。
from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
from keras.utils import np_utils
import numpy as np
import keras
classes = ["car", "bicycle", "motorcycle", "pedestrian"]
num_class = len(classes)
image_size = 50
# メインの関数を定義する
def main():
X_train, X_test, y_train, y_test = np.load("./vehicle_aug.npy", allow_pickle=True)
X_train = X_train.astype("float") / 256
X_test = X_test.astype("float") / 256
y_train = np_utils.to_categorical(y_train, num_class)
y_test = np_utils.to_categorical(y_test, num_class)
model = model_train(X_train, y_train)
model_eval(model, X_test, y_test)
def model_train(X, y):
model = Sequential()
model.add(Conv2D(32, (3,3), padding='same', input_shape=X.shape
))
model.add(Activation('relu'))
model.add(Conv2D(32, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Conv2D(64, (3,3), padding='same'))
model.add(Activation('relu'))
model.add(Conv2D(64, (3,3)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2,2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(4))
model.add(Activation('softmax'))
opt = keras.optimizers.RMSprop(lr=0.0001, decay=1e-6)
model.compile(
loss='categorical_crossentropy',
optimizer=opt,
metrics=['accuracy']
)
model.fit(X, y, batch_size=32, epochs=100)
# モデルの保存
model.save('./vehicle_cnn_aug.h5')
return model
def model_eval(model, X, y):
scores = model.evaluate(X, y, verbose=1)
print('Test Loss: ', scores[0])
print('Test Accuracy: ', scores
)
if __name__ == '__main__':
main()
モデルを使ってアプリでデプロイする
Xcodeを使ってiOSアプリを作成していきます。Xcodeはswiftという言語で書く必要があります。学習モデルをh5ファイルで作成しましたが、そのままではiOSのアプリには使えません。学習モデルをiOSで使用できるmlmodelにしていく必要があります。
h5ファイルをmlmodelに変換する
CNNを使って学習モデルをh5ファイルにしましたが、そのままではiOSのアプリには使えないのでmlmodelファイルにしていきます。
import coremltools
coreml_model = coremltools.converters.keras.convert(
'vehicle_cnn_aug.h5',
input_names='image',
image_input_names='image',
output_names='Prediction',
class_labels=['car', 'bycycle', 'motorcycle', 'pedestrian'],
)
coreml_model.save('./vehicle_cnn_aug.mlmodel')
mlmodelをviewcontrollerに組み込む
func imagePrediction(image: UIImage) {
guard let model = try? VNCoreMLModel(for: vehicle_cnn_aug().model) else {
fatalError("Model not found")
}
let request = VNCoreMLRequest(model: model) {
[weak self] request, error in
guard let results = request.results as? [VNClassificationObservation],
let firstResult = results.first else {
fatalError("No results found")
}
DispatchQueue.main.async {
self?.predictDisplay.text = "Accuracy: = \(Int(firstResult.confidence * 100))% \n\nラベル: \((firstResult.identifier))"
}
}
guard let ciImage = CIImage(image: image) else {
fatalError("Can't convert image.")
}
let imageHandler = VNImageRequestHandler(ciImage: ciImage)
DispatchQueue.global(qos: .userInteractive).async {
do {
try imageHandler.perform([request])
} catch {
print("Error")
}
}
}
実際にアプリを使ってみる
実際にアプリを起動して試してみようとしましたが、iOS13の時に作ったアプリでiOS14で動かそうとしたらバージョンの違いか起動しませんでしたOTL
前はできていたのに〜😭
coremltoolのバージョンの違いな気もするのでまたうまく行った段階で記事を更新できればと思います。

まとめ
iOSでアプリを作りましたがAndroidでも同様のアプリは作成可能です。Androidアプリの作成はまだしたことありませんがいつかチャレンジしてみたいと思います!!
- 画像データをバイナリファイルにして訓練データとテストデータに分ける
- CNNを使って学習し、モデルをh5ファイル保存する
- h5ファイルをiOSでも使えるようにmlmodelを作成する
- mlmodelを使ってXcodeでアプリを作る
今後もこのように作ったものや学習したものとかを紹介できればと考えています。