CV2图像处理和tf.image处理之间的差异

txi*_*zle 11 python image image-processing tensorflow cv2

我最近使用cv2为Tensorflow的tf.image模块进行了图像处理.但是,我的验证准确率下降了大约10%.

我认为这个问题与此有关

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

虽然这些差异导致精度较差,但使用plt.imshow()时,图像似乎无法区分.例如,获取ImageNet验证数据集的图像#1:

CV2图像 在此输入图像描述

首要问题:

  • cv2.imread()接收一个字符串并输出一个BGR 3通道uint8矩阵
  • tf.image_decode_jpeg()接受一个字符串张量并输出RGB 3通道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]]```
Run Code Online (Sandbox Code Playgroud)

使用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]]```
Run Code Online (Sandbox Code Playgroud)

第二期:

  • 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]]```
Run Code Online (Sandbox Code Playgroud)

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]]```
Run Code Online (Sandbox Code Playgroud)

这是一个证明刚刚提到的行为的要点.它包含我处理图像的完整代码.

所以我的主要问题是:

  • 为什么cv2.imread()和tf.image.decode_jpeg()的输出不同?
  • 如果cv2.resize()和tf.image.resize_images()使用相同的插值方案,它们会有什么不同?

谢谢!

Fre*_*ert 7

正如vijay m正确指出的那样,通过将其更改dct_method为“ INTEGER_ACCURATE”,您将使用cv2或tf获得相同的uint8图像。问题的确似乎是调整大小的方法。我还尝试强制Tensorflow使用与cv2默认使用的插值方法相同的插值方法(双线性),但结果仍然不同。可能是这种情况,因为cv2对整数值进行插值,并且TensorFlow在插值之前转换为float。但这只是一个猜测。如果绘制通过TF和cv2调整大小的图像之间的逐像素差异,您将得到以下历史图:

像素差异的直方图

如您所见,这看起来很正常。(也令我感到惊讶的是像素间的差异)。您的准确性下降的问题可能就在这里。在本文中, Goodfellow等。描述对抗性示例和分类系统的效果。我认为这是一个类似的问题。如果您使用的原始权重是通过提供cv2函数结果的某些输入管道进行训练的,则TF输入管道中的图像就像是一个对抗性示例。

(有关示例,请参见顶部第3页上的图像...我不能发布两个以上的链接。)

因此,最后,我认为,如果要将原始网络权重用于他们训练网络时所用的相同数据,则应该使用类似/相同的输入管道。如果您使用权重对自己的数据进行网络微调,则不必担心,因为您需要重新训练分类层以使用新的输入图像(来自TF管道)。

和@ Ishant Mrinal:请看一下GIST中提供的OP的代码。他知道BGR(cv2)和RGB(TF)的区别,并将图像转换为相同的色彩空间。