web-dev-qa-db-ja.com

CV2画像処理とtf.image処理の違い

最近、画像処理用のTensorflowの tf.image モジュールにcv2を使用するように切り替えました。しかし、私の検証精度は約10%低下しました。

この問題はに関連していると思います

  1. cv2.imread()とtf.image.decode_jpeg()
  2. cv2.resize()とtf.image.resize_images()

これらの違いにより精度が低下しますが、plt.imshow()を使用すると、画像は人間が区別できないように見えます。たとえば、ImageNet検証データセットの画像#1を取り上げます。

CV2 Imageenter image description here

創刊:

  • cv2.imread()は文字列を受け取り、BGR3チャネルuint8行列を出力します
  • tf.image_decode_jpeg()は、文字列テンソルを取り込んで、RGB3チャネルuint8テンソルを出力します。

ただし、tfテンソルをBGR形式に変換した後、画像の多くのピクセルで非常にわずかな違いがあります。

Tf.image.decode_jpegを使用してからBGRに変換する

[[ 26  41  24 ...,  57  48  46]
 [ 36  39  36 ...,  24  24  29]
 [ 41  26  34 ...,  11  17  27]
 ..., 
 [ 71  67  61 ..., 106 105 100]
 [ 66  63  59 ..., 106 105 101]
 [ 64  66  58 ..., 106 105 101]]```

Cv.imreadの使用

[[ 26  42  24 ...,  57  48  48]
 [ 38  40  38 ...,  26  27  31]
 [ 41  28  36 ...,  14  20  31]
 ..., 
 [ 72  67  60 ..., 108 105 102]
 [ 65  63  58 ..., 107 107 103]
 [ 65  67  60 ..., 108 106 102]]```

2番目の問題:

  • tf.image.resize_images()は、uint8テンソルをfloat32テンソルに自動的に変換し、ピクセル値の違いを悪化させるようです。
  • Tf.image.resize_images()とcv2.resize()はどちらも

tf.image.resize_images

[[  26.           25.41850281   35.73127747 ...,   81.85855103
    59.45834351   49.82373047]
 [  38.33480072   32.90485001   50.90826797 ...,   86.28446198
    74.88543701   20.16353798]
 [  51.27312469   26.86172867   39.52401352 ...,   66.86851501
    81.12111664   33.37636185]
 ..., 
 [  70.59472656   75.78851318 
 45.48100662 ...,   70.18637085
    88.56777191   97.19295502]
 [  70.66964722   59.77249908   48.16699219 ...,   74.25527954
    97.58244324  105.20263672]
 [  64.93395996   59.72298431   55.17600632 ...,   77.28720856
    98.95108032  105.20263672]]```

cv2.resize

[[ 36  30  34 ..., 102  59  43]
 [ 35  28  51 ...,  85  61  26]
 [ 28  39  50 ...,  59  62  52]
 ..., 
 [ 75  67  34 ...,  74  98 101]
 [ 67  59  43 ...,  86 102 104]
 [ 66  65  48 ...,  86 103 105]]```

これが 要点 今述べた振る舞いを示しています。これには、画像の処理方法の完全なコードが含まれています。

だから私の主な質問は:

  • cv2.imread()とtf.image.decode_jpeg()の出力が異なるのはなぜですか?
  • 同じ補間スキームを使用する場合、cv2.resize()とtf.image.resize_images()はどのように異なりますか?

ありがとうございました!

12
txizzle

vijay mが正しく指摘しているように、dct_methodから "INTEGER_ACCURATE"に、cv2またはtfを使用して同じuint8イメージを取得します。問題は確かにサイズ変更方法にあるようです。また、Tensorflowにcv2がデフォルトで使用するのと同じ補間方法(双一次)を使用するように強制しようとしましたが、結果はまだ異なります。これは、cv2が整数値の補間を行い、TensorFlowが補間する前にfloatに変換するためです。しかし、これは単なる推測です。サイズ変更された画像をTFとcv2でピクセル単位でプロットすると、次のヒストグラムが得られます。

ピクセル単位の差のヒストグラム

ご覧のとおり、これはかなり正規分布に見えます。 (また、ピクセルごとの違いの量にも驚いていました)。精度低下の問題はまさにここにある可能性があります。 この論文 Goodfellow etal。敵対的な例と分類システムの影響を説明します。ここでのこの問題は私が思うに似たようなものです。ネットワークに使用する元の重みが、cv2関数の結果を提供する入力パイプラインを使用してトレーニングされた場合、TF入力パイプラインからの画像は敵対的な例のようなものです。

(例については、上部の3ページの画像を参照してください... 2つ以上のリンクを投稿することはできません。)

したがって、最終的には、ネットワークをトレーニングしたのと同じデータに元のネットワークの重みを使用する場合は、同様の/同じ入力パイプラインを使用する必要があると思います。重みを使用して独自のデータでネットワークを微調整する場合、(TFパイプラインからの)新しい入力画像を処理するように分類レイヤーを再トレーニングするため、これは大きな問題にはなりません。

そして@Ishant Mrinal:要点で提供されているOPのコードを見てください。彼はBGR(cv2)とRGB(TF)の違いを認識しており、画像を同じ色空間に変換しています。

6