iCrawlerとVGG16で画像分類


# はじめに
DCGANを勉強するにあたってスクレイピングの代わりにiCrawlerが簡単と聞いたのでその勉強としてやりました！
もっといいコードがあれば教えてください✨
参考記事っていうかほぼ下の記事と一緒です（笑）
ですが今回の記事は下の記事のエラーをすべて解消したものになります（笑）
何か間違いやもっと簡単なコードがありましたら教えてください:star:

https://qiita.com/Yu_unI1/items/cc992918c6f940d10699
# 実装
## 今回作ったもの
画像収集ではスクレイピングの代わりにicrawlerを利用しました。そしてりんご、ぶどう、みかんの３つの分類を行うようにVGG16を再学習させています。また実行環境は以下のとおりです。
```:モデルの訓練
Google Colab
```
```:flaskアプリ
python 3.10
Windows11 Home 
```

## icrawlerで画像収集
icrawlerで画像を収集します。
```:colab
!pip install icrawler
```

```python:colab
# ライブラリのインポート
from icrawler.builtin import BingImageCrawler
```
pipでライブラリをインストールしその後importまで済ませます。
今回画像を収集するフォルダを作成します。今回はimagesフォルダを作成しその中に`りんご` `みかん` `ぶどう`のフォルダを作成しそこに画像を収集します。
```:colab
!mkdir images
!cd images
```
画像を収集します。
```python:colab
labels =["りんご", "みかん", "ぶどう"]
for label in labels:
  path = "/content/images/" + label
  crawler = BingImageCrawler(storage = {'root_dir' : path})
  crawler.crawl(keyword = 'i', max_num = 150)
```
labelsというリストに今回収集したいラベルを入れ、その後のfor文中でそれぞれ150枚ずつ画像を収集しようとしています。
画像を収集する過程で、`ERROR:downloader:Response status code 403, file`のようなエラーが出力される場合がありますが、これは上手くファイルを取れなかった時に出るものなので無視してOKです。

実行が終わると、google colabのランタイムの中に画像が収集されてい事がわかります。colabの左端にファイルという場所がありますのでそこで確認してみてください:v:

## VGG
次にVGGに転移学習を施します。
ここからは参考記事とほぼ同様のため説明は割愛させていただきます。
まとめのコードは↓です:point_down_tone1:
```python:colab
import os
import cv2
import numpy as np
import keras
import glob as glob
from keras import utils

path = "/content/images"
n_classes = len(labels)
print(f"num of class = {n_classes} , classes = {labels}")

X = []
Y = []

for label,class_name in enumerate(classes):
  files = glob.glob(path + "/" +  class_name + "/*.jpg")
  for file in files:
    img = cv2.imread(file)
    img = cv2.resize(img,dsize=(224,224))
    X.append(img)
    Y.append(label)

X = np.array(X)
X = X.astype('float32')
X /= 255.0

Y = np.array(Y)
Y = utils.to_categorical(Y,n_classes)

from sklearn.model_selection import train_test_split
X_train,X_test,Y_train,Y_test = train_test_split(X,Y,test_size=0.1)

from keras.applications.vgg16 import VGG16
from keras.models import Sequential
from keras.models import model_from_json
from keras.models import Model
from keras.layers import Input, Activation, Dense, Flatten, Dropout
from tensorflow.keras.optimizers import Adam

input_tensor = Input(shape=(224,224,3))
base_model = VGG16(weights='imagenet', input_tensor=input_tensor,include_top=False)


top_model = Sequential()
top_model.add(Flatten(input_shape=base_model.output_shape[1:]))
top_model.add(Dense(n_classes, activation='softmax'))

model = Model(inputs=base_model.input, outputs=top_model(base_model.output))

for layer in model.layers[:15]:
  layer.trainable = False

model.compile(loss='categorical_crossentropy',optimizer='adam',metrics=['accuracy'])


model.summary()


model.fit(X_train, Y_train, epochs=12, batch_size=5)

score = model.evaluate(X_test, Y_test, batch_size=5)


img = cv2.imread('ここには画像のパスを入れる')
img = cv2.resize(img,dsize=(224,224))
img = img.astype('float32')
img /= 255.0
img = img[None, ...]
result = model.predict(img)

np.set_printoptions(precision=3, suppress=True)
pred = result.argmax()
labels[pred]
```

## ローカル環境でのモデルのロード
ここまではGoogle colabでモデルの訓練をしてきましたが、実際にローカル環境(anacondak環境)で保存したモデルを使ってみたいと思います。


```python:colab
# モデルを保存する
import pickle
pickle.dump(classes, open('classes.sav', 'wb'))
model.save('model.h5')
```
モデルを保存したらcolabのランタイム、もしくは、driveと接続している方であればdriveの方からclasses.savとmodel.h5をダウンロードしましょう。

```python:ローカル
from keras.models import load_model
import pickle
#モデルとクラス名の読み込み
model = load_model('model.h5')
classes = pickle.load(open('classes.sav', 'rb'))
```
kerasとpickleを用いてモデルをロードします。ここまでできればコラボ環境で動作させたのと同じようにmodelをローカル実行することができます。

# 最後に
ここまで読んでいただきありがとうございました。
コードは前回製作者の方と一緒に動作確認したのですが、もしコピペミスやタイポなどでうまく動作しない箇所がありましたら、コメントなどでご指摘いただけると嬉しいです
これからたくさんのことについて投稿していこうと思います。
これからよろしくお願いいたします:bow_tone1:

ありがとうございました:wave: