web-dev-qa-db-ja.com

cv2.imreadをkeras image.img_load出力に一致させる方法

私はディープラーニングを勉強しています。画像分類アルゴリズムを訓練しました。ただし、問題は、使用したイメージをトレーニングすることです。

test_image = image.load_img('some.png', target_size = (64, 64))
test_image = image.img_to_array(test_image)

実際のアプリケーションでは次を使用します:

test_image = cv2.imread('trick.png')
test_image = cv2.resize(test_image, (64, 64))

しかし、それらは異なるndarray(異なるデータ)を与えることがわかりました。

Load_imageの最後のエントリ:

  [ 64.  71.  66.]
  [ 64.  71.  66.]
  [ 62.  69.  67.]]]

Cv2.imreadの最後のエントリ:

  [ 15  23  27]
  [ 16  24  28]
  [ 14  24  28]]]

、システムが機能していません。ある結果を別の結果と一致させる方法はありますか?

11
wasd

OpenCVは画像をBGR形式で読み取りますが、ケラスではRGBで表されます。 OpenCVバージョンを期待する順序(RGB)に対応させるには、単にチャンネルを逆にします:

test_image = cv2.imread('trick.png')
test_image = cv2.resize(test_image, (64, 64))
test_image = test_image[...,::-1] # Added

最後の行は、RGB順になるようにチャンネルを反転します。これをkerasモデルにフィードできます。

追加したいもう1つの点は、cv2.imreadは通常uint8の精度で画像を読み込むということです。 kerasで読み込んだ画像の出力を調べると、データが浮動小数点精度であることがわかります。したがって、float32などの浮動小数点表現に変換することもできます。

import numpy as np
# ...
# ...
test_image = test_image[...,::-1].astype(np.float32)

最後のポイントとして、モデルのトレーニング方法に応じて、通常、画像ピクセル値を[0,1]範囲に正規化するのが一般的です。 Kerasモデルでこれを行った場合は、OpenCVを介して読み込まれた画像の値を255で除算してください。

import numpy as np
# ...
# ...
test_image = (test_image[...,::-1].astype(np.float32)) / 255.0
10
rayryeng

BGR形式を使用するCV2とRGB形式を使用するKeras(バックエンドとしてPILを使用)に加えて、同じパラメーターを使用するCV2とPILのサイズ変更方法にも大きな違いがあります。

インターネットには複数のリファレンスがありますが、一般的な考え方は、2つのサイズ変更アルゴリズムで使用されるピクセル座標系に微妙な違いがあり、補間アルゴリズムの中間ステップとしてフロートにキャストするさまざまな方法で潜在的な問題があることです。最終結果は視覚的に類似した画像ですが、バージョン間でわずかにシフト/動揺した画像です。

入力のわずかな違いにも関わらず、精度に大きな違いを引き起こす可能性がある敵対攻撃の完璧な例。

5
Kyle Vrooman

最近、同じ問題に出会いました。 OpenCVでカラーチャンネルを変換し、画像のサイズを変更しようとしました。ただし、PILとOpenCVでは、画像のサイズ変更の方法がまったく異なります。この問題の正確な解決策を次に示します。

これは、イメージファイルパスを取り、ターゲットサイズに変換し、Kerasモデルを準備する関数です-

import cv2
import keras
import numpy as np
from keras.preprocessing import image
from PIL import Image

def prepare_image (file):
    im_resized = image.load_img(file, target_size = (224,224))
    img_array = image.img_to_array(im_resized)
    image_array_expanded = np.expand_dims(img_array, axis = 0)
    return keras.applications.mobilenet.preprocess_input(image_array_expanded)

# execute the function
PIL_image = prepare_image ("lena.png")

OpenCVイメージがある場合、関数は次のようになります-

def prepare_image2 (img):
    # convert the color from BGR to RGB then convert to PIL array
    cvt_image =  cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    im_pil = Image.fromarray(cvt_image)

    # resize the array (image) then PIL image
    im_resized = im_pil.resize((224, 224))
    img_array = image.img_to_array(im_resized)
    image_array_expanded = np.expand_dims(img_array, axis = 0)
    return keras.applications.mobilenet.preprocess_input(image_array_expanded)

# execute the function
img = cv2.imread("lena.png")
cv2_image = prepare_image2 (img)

# finally check if it is working  
np.array_equal(PIL_image, cv2_image)
>> True
1
Sourav