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

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

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

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

Q&A

解決済

1回答

2550閲覧

kerasでのresizeとopencvでのresizeの手法が異なることから画像の特徴量が失われる

hashikunmaru

総合スコア6

Keras

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

OpenCV

OpenCV(オープンソースコンピュータービジョン)は、1999年にインテルが開発・公開したオープンソースのコンピュータビジョン向けのクロスプラットフォームライブラリです。

機械学習

機械学習は、データからパターンを自動的に発見し、そこから知能的な判断を下すためのコンピューターアルゴリズムを指します。人工知能における課題のひとつです。

0グッド

0クリップ

投稿2020/01/08 15:44

編集2020/01/09 15:03

やってること

ある画像A内にあるモノを検出し、それらがa,b,cいずれに該当するのかというアルゴリズムを作成しています。

kerasを用いて学習したモデルを実際に使用したいのですが、

keras:.flow_from_directoryでのリサイズ(入力は画像のパス)
opencv:cv2.resizeでのリサイズ(入力は画像)

のように、リサイズの手法を分けることになります。
手法が異なることにより、学習した特徴量(kerasでリサイズ)がモデルを使用するときの画像(opencvでリサイズ)に使えない状態になっています。

モデルを使用するときの方のコードを変更してうまくいく方法を探してます。

#学習時の一部 img_width, img_height = 100,100 from keras.preprocessing.image import ImageDataGenerator train_datagen = ImageDataGenerator(rescale=1.0 / 255, zoom_range=0.2, horizontal_flip=True) validation_datagen = ImageDataGenerator(rescale=1.0 / 255) train_generator = train_datagen.flow_from_directory( train_data_dir, target_size=(img_width, img_height), color_mode='rgb', classes=classes, class_mode='categorical', batch_size=16) validation_generator = validation_datagen.flow_from_directory( validation_data_dir, target_size=(img_width, img_height), color_mode='rgb', classes=classes, class_mode='categorical', batch_size=16)
#モデルの使用時の例 for i in range(1,56): path = ("./img_test/" + str(i) + ".jpeg") img2 = cv2.imread(path) img = cv2.resize(img2,dsize=(img_width,img_height), interpolation=cv2.INTER_NEAREST) x = img_to_array(img) x = np.expand_dims(x, axis=0) x = x / 255 pred = model.predict(x)[0]

ちなみに

img = load_img(img2, target_size=(img_width, img_height))

の形でリサイズすると上手くいくのですが、初めに言った通り画像Aの中からトリミングした画像をそのまま入力に使いたいので入力がパスであるload_imgが使えません

参考

cv2.resizeでリサイズしてPIL形式に変換した結果がこちらです

python

1import cv2 2from keras.preprocessing.image import load_img, save_img, img_to_array, array_to_img 3from PIL import Image 4import numpy as np 5 6img_width,img_height = 100,100 7 8img2 = cv2.imread("1.jpeg") 9 10img_orig = load_img("1.jpeg", target_size=(img_width, img_height)) 11img_nearest = load_img("1.jpeg", target_size=(img_width, img_height),interpolation="nearest") 12img_bilinear = load_img("1.jpeg", target_size=(img_width, img_height),interpolation="bilinear") 13img_bicubic = load_img("1.jpeg", target_size=(img_width, img_height),interpolation="bicubic") 14 15img_cv_NEAR = cv2.resize(img2,dsize=(img_width,img_height), interpolation=cv2.INTER_NEAREST) 16img_cv_LINEAR = cv2.resize(img2,dsize=(img_width,img_height), interpolation=cv2.INTER_LINEAR) 17img_cv_CUBIC = cv2.resize(img2,dsize=(img_width,img_height), interpolation=cv2.INTER_CUBIC) 18 19img_pN = Image.fromarray(np.uint8(img_cv_NEAR)) 20img_pL = Image.fromarray(np.uint8(img_cv_LINEAR)) 21img_pC = Image.fromarray(np.uint8(img_cv_CUBIC)) 22

イメージ説明

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

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

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

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

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

guest

回答1

0

ベストアンサー

追補

補完方法にどれだけ差があるか試したことがなかったため、KERASの方法を正としてOpenCV、PILの方法を比較しました。
イメージ説明
結果: 補完方法による「差はない」は言い過ぎですが、データ増強の変化量と比べればないも同然程度の差しかありませんでした。
イメージ説明

Python3

1from PIL import Image 2import cv2 3import os 4import numpy as np 5 6from keras.preprocessing.image import ImageDataGenerator,img_to_array 7 8path = ".\lenna.png" 9size = (256,256) 10 11def PIL2OpenCV(img): 12 img = np.asarray(img) 13 if len(img.shape)==3: 14 # RGB --> BGR 15 img = cv2.cvtColor(img,cv2.COLOR_RGB2BGR) 16 return img 17 18def pure_PIL(path,size): 19 img_PIL = Image.open(path) 20 img_PIL = img_PIL.resize(size) 21 22 return PIL2OpenCV(img_PIL) 23 24def pure_OpenCV(path,size,flag): 25 img_OpenCV = cv2.imread(path) 26 img_OpenCV = cv2.resize(img_OpenCV,size,interpolation=flag) 27 return img_OpenCV 28 29def by_keras(path,size): 30 img_by_keras = ImageDataGenerator.flow_from_directory(path,target_size=size) 31 print(img_by_keras) 32 return img_by_keras 33 34if __name__=="__main__": 35 36 img_by_keras = pure_OpenCV(path,size,cv2.INTER_LANCZOS4) 37 # cv2.imshow("KERAS",cv2.absdiff(img_by_keras,img_by_keras)) 38 39 img_PIL = pure_PIL(path,size) 40 # cv2.imshow("PIL",cv2.absdiff(img_by_keras,img_PIL)) 41 42 img_nearest = pure_OpenCV(path,size,cv2.INTER_NEAREST) 43 # cv2.imshow("OpenCV (NEAREST)",cv2.absdiff(img_by_keras,img_nearest)) 44 45 img_linear = pure_OpenCV(path,size,cv2.INTER_LINEAR) 46 # cv2.imshow("OpenCV (LINEAR)",cv2.absdiff(img_by_keras,img_linear)) 47 48 img_cubic = pure_OpenCV(path,size,cv2.INTER_CUBIC) 49 # cv2.imshow("OpenCV (CUBIC)",cv2.absdiff(img_by_keras,img_cubic)) 50 51 img_area = pure_OpenCV(path,size,cv2.INTER_AREA) 52 # cv2.imshow("OpenCV (AREA)",cv2.absdiff(img_by_keras,img_area)) 53 54 img_lanczos = pure_OpenCV(path,size,cv2.INTER_LANCZOS4) 55 # cv2.imshow("OpenCV (LANCZOS4)",cv2.absdiff(img_by_keras,img_lanczos)) 56 57 # img_strange = img_to_array(img_nearest) 58 # cv2.imshow("STRANGE CODE",img_strange) 59 60 img_stacked = np.hstack((cv2.absdiff(img_by_keras,img_by_keras), 61 cv2.absdiff(img_by_keras,img_PIL), 62 cv2.absdiff(img_by_keras,img_nearest), 63 cv2.absdiff(img_by_keras,img_linear), 64 cv2.absdiff(img_by_keras,img_cubic), 65 cv2.absdiff(img_by_keras,img_area), 66 cv2.absdiff(img_by_keras,img_lanczos) 67 )) 68 cv2.imwrite("./stacked.png",img_stacked) 69 cv2.imshow("KERAS/PIL/NEAREST/LINEAR/CUBIC/AREA/LANCZOS/STRANGE",img_stacked) 70 71 cv2.waitKey(0)

また、

学習した特徴量(kerasでリサイズ)がモデルを使用するときの画像(opencvでリサイズ)に使えない状態

これについて検証するため、掲載のコードを手元のWindowsで動くように若干修正したのが以下のコードです。
結果: OpenCVではBGRに対して、PILではRGBでデータが格納されています。この違いにより、PIL経由でデータを表示させたものは異常な色になりました。これが学習がうまくいかなかった原因と思われます。
これを防ぐには、上記のPIL2OpenCVをかませる等で対応してください。

イメージ説明

Python3

1from PIL import Image 2import cv2 3import os 4import numpy as np 5 6from keras.preprocessing.image import ImageDataGenerator,img_to_array 7 8path = ".\lenna.png" 9size = (256,256) 10 11def PIL2OpenCV(img): 12 img = np.asarray(img) 13 if len(img.shape)==3: 14 # RGB --> BGR 15 img = cv2.cvtColor(img,cv2.COLOR_RGB2BGR) 16 return img 17 18def pure_PIL(path,size): 19 img_PIL = Image.open(path) 20 img_PIL = img_PIL.resize(size) 21 22 return PIL2OpenCV(img_PIL) 23 24def pure_OpenCV(path,size,flag): 25 img_OpenCV = cv2.imread(path) 26 img_OpenCV = cv2.resize(img_OpenCV,size,interpolation=flag) 27 return img_OpenCV 28 29def by_keras(path,size): 30 img_by_keras = ImageDataGenerator.flow_from_directory(path,target_size=size) 31 print(img_by_keras) 32 return img_by_keras 33 34if __name__=="__main__": 35 36 img_by_keras = pure_OpenCV(path,size,cv2.INTER_LANCZOS4) 37 cv2.imshow("KERAS",cv2.absdiff(img_by_keras,img_by_keras)) 38 img_PIL = pure_PIL(path,size) 39 cv2.imshow("PIL",cv2.absdiff(img_by_keras,img_PIL)) 40 41 img_OpenCV = pure_OpenCV(path,size,cv2.INTER_NEAREST) 42 cv2.imshow("OpenCV (NEAREST)",cv2.absdiff(img_by_keras,img_OpenCV)) 43 44 img_OpenCV = pure_OpenCV(path,size,cv2.INTER_LINEAR) 45 cv2.imshow("OpenCV (LINEAR)",cv2.absdiff(img_by_keras,img_OpenCV)) 46 47 img_OpenCV = pure_OpenCV(path,size,cv2.INTER_CUBIC) 48 cv2.imshow("OpenCV (CUBIC)",cv2.absdiff(img_by_keras,img_OpenCV)) 49 50 img_OpenCV = pure_OpenCV(path,size,cv2.INTER_AREA) 51 cv2.imshow("OpenCV (AREA)",cv2.absdiff(img_by_keras,img_OpenCV)) 52 53 img_OpenCV = pure_OpenCV(path,size,cv2.INTER_LANCZOS4) 54 cv2.imshow("OpenCV (LANCZOS4)",cv2.absdiff(img_by_keras,img_OpenCV)) 55 56 img_OpenCV = img_to_array(img_OpenCV) 57 cv2.imshow("STRANGE CODE",img_OpenCV) 58 59 cv2.waitKey(0)

■リファレンスの情報

つまり、
PIL_IMG = load_img(PATH, target_size=(img_width, img_height))

■掲載のコード
エラー等の情報なく、とりあえずうまくいかないとのことですのでコードを確認すると、

コード
リファレンスの要求NUMPY_IMG = img_to_array(PIL_IMG)
掲載のコードNUMPY_IMG = img_to_array(NUMPY_IMG)

のように入力しているデータの形式が異なっていることが分かります。
実際に動かしていないのですが、一番怪しいのはこのように形式の相違と思われます。

■対策
「OpenCVで読み込み・リサイズした画像をPIL形式に直してからimg_to_arrayする」か、エラーが出ないようであれば「OpenCVで読み込み・リサイズした画像をそのままnp.expand_dims()につっこむ」でよいのではないでしょうか?
ただし、cv2.imread経由の値はnp.uint8形式ですが、img_to_array経由での値は同じ値をfloatで(例えば、5を5.のように)返すそうですので、必要であればここに注意して動作確認をしてください。

投稿2020/01/08 21:55

編集2020/01/10 12:34
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

hashikunmaru

2020/01/09 15:14

ご回答ありがとうございます。 まず、PIL形式に変換してからimg_to_arrayの方法はやはり補間法によってそれぞれことなる画像の情報になってしまうようです(質問文の参考に結果を追加しました) また、そのままnp.expand_dimsに突っ込む方法もエラーは出ませんでしたが、クラス分類はうまくいきませんでした(やはり、画像の情報が変更されている?) 他に何かあれば教えていただければと思います。 よろしくお願いいたします。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問