質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Q&A

解決済

2回答

970閲覧

keras 画像分類に使用した検証画像をクラス分類ごとに保存したい

lotta

総合スコア1

Keras

Kerasは、TheanoやTensorFlow/CNTK対応のラッパーライブラリです。DeepLearningの数学的部分を短いコードでネットワークとして表現することが可能。DeepLearningの最新手法を迅速に試すことができます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

0グッド

0クリップ

投稿2022/10/22 15:16

前提

機械学習初心者です。
vgg16の転移学習で二値分類を行っています。
ほぼコピペですが学習・検証まで行えました。
なんとかコンフュージョンマトリクスの作成までこぎつけました。
学習・検証のために画像をnumpy.ndarray型に変換しているのだとは思いますが、これは可逆的なものなのでしょうか?

実現したいこと

・検証に使用しTP・TN・FP・FNに振り分けられたそれぞれの画像を再度jpgの形式で保存したいです。できればフォルダごとに分けたいです。

該当のソースコード

Python

1import tensorflow as tf 2from tensorflow.keras.preprocessing import image_dataset_from_directory 3from sklearn.model_selection import train_test_split 4import matplotlib.pyplot as plt 5import numpy as np 6 7 8# 画像ディレクトリ 9IMG_DIR = "/content/drive/My Drive/images4" 10# バッチサイズ 11BATCH_SIZE = 32 12# VGG16を使用するため以下のサイズに設定 13IMAGE_SIZE = (224, 224) 14IMAGE_SHAPE = IMAGE_SIZE + (3, ) 15 16# 訓練、検証、テストの比率 17TRAIN_SIZE = 0.9 18VALIDATION_SIZE = 0.1 19 20# 実行毎に同一の結果が得られるようシード値を固定 21RANDOM_STATE = 123 22 23# 学習率 24LEARNING_RATE = 3e-5 25 26# エポック数 27INITIAL_EPOCHS = 10 28 29# ------------------------------------------------------------ 30# 1.画像とラベル取得と訓練・検証・テスト分割 31# ------------------------------------------------------------ 32# (1) 画像読み込み 33image_dataset = image_dataset_from_directory(IMG_DIR, 34 shuffle=False, 35 batch_size=BATCH_SIZE, 36 image_size=IMAGE_SIZE 37 ) 38 39# (2) 画像データセットをX:画像とY:クラス名で各々配列化 40image_class_names = image_dataset.class_names 41img_X = [] 42img_Y = [] 43for img_ds_batch in list(image_dataset.as_numpy_iterator()): 44 img_X.extend(img_ds_batch[0]) 45 img_Y.extend(img_ds_batch[1]) 46 47img_X = np.asarray(img_X) 48img_Y = np.asarray(img_Y) 49 50# (3) 画像データの標準化 51img_X = tf.keras.applications.vgg16.preprocess_input(img_X) 52 53# (4) データセットを訓練・検証・テストに分割 54# データセットを[train, (validation + test)]に分割 55img_X_train, img_X_valid, img_Y_train, img_Y_valid = train_test_split( 56 img_X, img_Y, 57 train_size=TRAIN_SIZE, 58 random_state=RANDOM_STATE, 59 stratify=img_Y) 60 61# ------------------------------------------------------------ 62# 2.モデル構築と学習 63# ------------------------------------------------------------ 64# (1) 転移学習のベースモデルとしてVGG16を宣言 65base_model = tf.keras.applications.vgg16.VGG16(include_top=False, 66 input_shape=IMAGE_SHAPE, 67 weights='imagenet') 68 69# (2) 畳み込みベースの凍結 70base_model.trainable = False 71 72# (3) モデル構築 73# Flatten(=平坦化層)追加 74x = tf.keras.layers.Flatten()(base_model.output) 75# FC1層追加 76x = tf.keras.layers.Dense(4096, activation='relu')(x) 77# FC2層追加 78x = tf.keras.layers.Dense(4096, activation='relu')(x) 79# 入力画像の形状 80transfer_learning_inputs = base_model.inputs 81# predictions層の追加 82# 今回分類するクラス数を指定 83image_class_num = len(image_class_names) 84transfer_learning_prediction = tf.keras.layers.Dense( 85 image_class_num, activation='softmax')(x) 86# 転移学習モデル構築 87transfer_learning_model = tf.keras.Model(inputs=transfer_learning_inputs, 88 outputs=transfer_learning_prediction) 89 90# (4) モデルのコンパイル 91transfer_learning_model.compile(optimizer= 92 tf.keras.optimizers.Adam(learning_rate=LEARNING_RATE), 93 loss='sparse_categorical_crossentropy', 94 metrics=['accuracy']) 95 96# (5) モデルの学習 97history = transfer_learning_model.fit(img_X_train, img_Y_train, 98 epochs=INITIAL_EPOCHS, 99 batch_size=BATCH_SIZE, 100 validation_data=(img_X_valid, img_Y_valid)) 101 102 103# (6) 最終的なValidationデータの評価 104from sklearn.metrics import confusion_matrix 105import itertools 106 107print(transfer_learning_model.evaluate(img_X_valid, img_Y_valid, verbose=0)) 108 109def plot_confusion_matrix(cm, classes, 110 normalize=False, 111 title='Confusion matrix', 112 cmap=plt.cm.Blues): 113 """ 114 This function prints and plots the confusion matrix. 115 Normalization can be applied by setting `normalize=True`. 116 """ 117 if normalize: 118 cm = cm.astype('float') / cm.sum(axis=1)[:, np.newaxis] 119 print("Normalized confusion matrix") 120 else: 121 print('Confusion matrix, without normalization') 122 123 print(cm) 124 125 plt.imshow(cm, interpolation='nearest', cmap=cmap) 126 plt.title(title) 127 plt.colorbar() 128 tick_marks = np.arange(len(classes)) 129 plt.xticks(tick_marks, classes, rotation=45) 130 plt.yticks(tick_marks, classes) 131 132 fmt = '.2f' if normalize else 'd' 133 thresh = cm.max() / 2. 134 for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): 135 plt.text(j, i, format(cm[i, j], fmt), 136 horizontalalignment="center", 137 color="white" if cm[i, j] > thresh else "black") 138 139 plt.tight_layout() 140 plt.ylabel('True label') 141 plt.xlabel('Predicted label') 142 143 144pred_y = transfer_learning_model.predict(img_X_valid) 145pred_y_classes = np.argmax(pred_y,axis = 1) 146confusion_mtx = confusion_matrix(img_Y_valid,pred_y_classes) 147plot_confusion_matrix(confusion_mtx, classes = range(2)) 148

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

google colab上でtensorflow・keras

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

jbpb0

2022/10/24 02:19 編集

> 画像をnumpy.ndarray型に変換しているのだとは思いますが、これは可逆的なものなのでしょうか? > 再度jpgの形式で保存したい の「可逆的」の意味が、pythonで画像ファイルを読み込んだnumpy配列を画像ファイルに保存したら、元の画像ファイルと同じものが保存できるか? という意味ならば、画像ファイルがjpgの場合は元の画像ファイルと同じものは保存できないので、「可逆的」ではありません たとえば、下記を例にします Aがもともとの画像ファイル、αがkerasでの学習に使われたデータです jpg画像A ↓ pythonで読み込む numpy配列α ↓ jpg画像ファイルに保存 jpg画像B ↓ pythonで読み込む numpy配列β 「可逆的」の意味が、上記例でもし ・AとBが全く同じになる または ・αとβが全く同じになる という意味なら、画像ファイルがjpgの場合はどちらもムリなので、「可逆的」ではありません > 検証に使用しTP・TN・FP・FNに振り分けられたそれぞれの画像を再度jpgの形式で保存したいです。できればフォルダごとに分けたいです。 質問内容が、もし ・AIの分類結果に基づき、もともとの「画像ファイル」を、分類ラベル別のディレクトリに「ファイルのコピー」をする と、 ・AIの分類結果に基づき、もともとの「画像ファイルを読み込んだデータ」を、分類ラベル別のディレクトリに「画像ファイルとして保存」する が、結果同じになるのか? というものなら、画像ファイルがjpgの場合は同じにはなりません 質問の意味を勘違いしてたら、ごめんなさい
jbpb0

2022/10/24 02:14

上記コメントに私が書いた > 画像ファイルがjpgの場合は元の画像ファイルと同じものは保存できない は、 import numpy as np import cv2 aaa = cv2.imread("元のjpg画像ファイルのパス") cv2.imwrite("bbb.jpg", aaa, [cv2.IMWRITE_JPEG_QUALITY, 100]) bbb = cv2.imread("bbb.jpg") abdiff = aaa.astype("float") - bbb.astype("float") print(np.max(abdiff)) print(np.min(abdiff)) を実行したら分かります numpy配列「aaa」と「bbb」は、コードの最後の二行の表示結果から同じではないことが分かります それはすなわち、「元のjpg画像ファイル」と「bbb.jpg」が同じではないということです もしかすると、「元のjpg画像ファイル」によっては(画素値変化が画像全体で非常に滑らかで少ない等)、numpy配列「aaa」と「bbb」が同じになる場合もあるかもしれませんが、それは非常に稀なケースです 一般的な画像で上記コードを実行したら、numpy配列「aaa」と「bbb」は同じにはなりません
lotta

2022/10/24 05:09

ありがとうございます。 全く同じ画像にならないということがおぼろげながら理解できました。 下記のコードでなんとか保存ができました。 しかし色などがおかしくなってしまっています。 極力もとの画像に近づけることはできないでしょうか。 from PIL import Image im = Image.fromarray(((img_X_valid[1])*255).astype(np.uint8)) im.save("TP.jpeg") ご教授頂けると幸いです。
jbpb0

2022/10/24 05:54

コメントに私が書いた > 画像ファイルがjpgの場合は元の画像ファイルと同じものは保存できない は、画素値を数値として比較したら分かるけど、画像を見比べてもすぐにはなかなか分からないくらいのレベルの話なので、 > 色などがおかしくなってしまっています。 は、原因が違います > # (3) 画像データの標準化 img_X = tf.keras.applications.vgg16.preprocess_input(img_X) で、 https://snowman-88888.hatenablog.com/entry/2017/04/01/043624 の「特徴」に書かれてるように、RGBからBGRに変更するとか、各色の平均値(?)「103.939, 116.779, 123.68」を引くとかしてるので、その逆をしないといけません https://tensorflow.classcat.com/2022/07/02/keras-2-examples-generative-neural-style-transfer/ の「画像前処理 / deprocessing ユティリティ」の「def deprocess_image(x):」を参考にしてみてください
lotta

2022/10/24 22:40

勉強になりました。 tf.keras.applications.vgg16.preprocess_input のところでVGG16に適した形に変換されているということですね。 戻すのなかなか大変なプロセスのように感じました。 参考にします。 別のアプローチになりますが、 検証用の画像にどのpred_y_classesが割り当てられたか特定することできますか? 例えばpred_y_classesをすべて表示させて、〇番目が0とか… もとのファイル名をわかりやすく1.jpg 2.jpg 3.jpg.... という感じにすれば特定できるのではないかと考えました。
jbpb0

2022/10/25 02:12 編集

https://qiita.com/haru1977/items/7aaf1eaeb0747fe613be に書かれてるようにすれば、 > # (4) データセットを訓練・検証・テストに分割 # データセットを[train, (validation + test)]に分割 img_X_train, img_X_valid, img_Y_train, img_Y_valid = train_test_split(... で分割する前の「img_X」内での順番を知ることはできると思いますが、それを利用するには、 > # (1) 画像読み込み image_dataset = image_dataset_from_directory(IMG_DIR,... と > # (2) 画像データセットをX:画像とY:クラス名で各々配列化 image_class_names = image_dataset.class_names で作成された「img_X」に、もともとの各画像ファイルがどのような順番で格納されてるのか、を把握しておく必要があります 「image_dataset_from_directory()」に「shuffle=False」を付けて実行してるので、おそらくファイル名順等の規則的な順番だろうとは思いますが、よく知りません 仮にファイル名順で格納されてるとしても、「30.jpg」と「5.jpg」のどちらが先になるのか、みたいな話もありますし 【追記】 https://stackoverflow.com/questions/62166588/how-to-obtain-filenames-during-prediction-while-using-tf-keras-preprocessing-ima に、「image_dataset_from_directory()」で読み込んだ画像ファイルのパス(の並び)を取得する方法が書かれてました https://qiita.com/haru1977/items/7aaf1eaeb0747fe613be に書かれてる方法で、画像ファイルのパス(の並び)も「train_test_split()」で一緒に分割させることができるかも
lotta

2022/10/27 23:40

ありがとうございます。 参考になりました。 画像の並びを確認して評価に使用することを試みます。
guest

回答2

0

検証に使用しTP・TN・FP・FNに振り分けられたそれぞれの画像を再度jpgの形式で保存したいです。できればフォルダごとに分けたいです。

質問内容が、もし
・AIの分類結果に基づき、もともとの「画像ファイル」を、分類ラベル別のディレクトリに「ファイルのコピー」をする
と、
・AIの分類結果に基づき、もともとの「画像ファイルを読み込んだデータ」を、分類ラベル別のディレクトリに「画像ファイルとして保存」する
が、結果同じになるのか?
というものなら、画像ファイルがjpgの場合は同じにはなりません

 

画像をnumpy.ndarray型に変換しているのだとは思いますが、これは可逆的なものなのでしょうか?

再度jpgの形式で保存したい

の「可逆的」の意味が、pythonで画像ファイルを読み込んだnumpy配列を画像ファイルに保存したら、元の画像ファイルと同じものが保存できるか?
という意味ならば、画像ファイルがjpgの場合は元の画像ファイルと同じものは保存できないので、「可逆的」ではありません

python

1import numpy as np 2import cv2 3 4aaa = cv2.imread("元のjpg画像ファイルのパス") 5cv2.imwrite("bbb.jpg", aaa, [cv2.IMWRITE_JPEG_QUALITY, 100]) 6bbb = cv2.imread("bbb.jpg") 7 8abdiff = aaa.astype("float") - bbb.astype("float") 9print(np.max(abdiff)) 10print(np.min(abdiff))

を実行したら、numpy配列「aaa」と「bbb」は、コードの最後の二行の表示結果から同じではないことが分かります
それはすなわち、「元のjpg画像ファイル」と「bbb.jpg」が同じではないということです

 
もしかすると、「元のjpg画像ファイル」によっては(画素値変化が画像全体で非常に滑らかで少ない等)、numpy配列「aaa」と「bbb」が同じになる場合もあるかもしれませんが、それは非常に稀なケースです
一般的な画像で上記コードを実行したら、numpy配列「aaa」と「bbb」は同じにはなりません

投稿2022/11/03 03:07

jbpb0

総合スコア7651

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

検証に使用しTP・TN・FP・FNに振り分けられたそれぞれの画像を再度jpgの形式で保存したい

img_Y_valid,pred_y_classesを使ってTP,TN,FP,FNを求め,img_X_validを振り分けると良いでしょう.

画像をnumpy.ndarray型に変換しているのだとは思いますが、これは可逆的なものなのでしょうか?

Stack Overflow - Saving a Numpy array as an image

可逆的です.

Python

1from PIL import Image 2im = Image.fromarray(img_X_valid[0]) 3im.save("your_file.jpeg")

として画像1枚を指定すると良いでしょう.

投稿2022/10/22 16:25

PondVillege

総合スコア1579

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

lotta

2022/10/23 08:23

ありがとうございます。 画像の変換に関してイメージがわきました。 なんとか試みてみようと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問