【问题标题】:Differences between CV2 image processing and tf.image processingCV2图像处理和tf.image处理的区别
【发布时间】:2018-01-12 23:39:49
【问题描述】:

我最近将 cv2 用于 Tensorflow 的 tf.image 模块进行图像处理。然而,我的验证准确率下降了大约 10%。

我认为这个问题与

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

虽然这些差异会导致更差的准确性,但使用 plt.imshow() 时,图像似乎与人类无法区分。例如,以 ImageNet 验证数据集的 Image #1 为例:

第一期:

  • 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]]```

使用 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]]```

第二期:

  • 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]]```

这是一个 gist 演示刚才提到的行为。它包括我如何处理图像的完整代码。

所以我的主要问题是:

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

谢谢!

【问题讨论】:

  • 我认为 BGR 格式不应该是这样的。而不是那样,我希望将 3 个值元组(嗯,数组)放在一个二维数组中(一旦将所有数组放在一起,就做一个 3D 数组)。您可以尝试再次打印数组及其形状,为每个函数,并向我们展示结果吗?
  • tf.image.decode_jpeg 有两个解码选项:更快更准确。 Faster 不符合 jpeg 规范。因此,在dct_mode 中设置为“INTEGER_ACCURATE”应该使两者相同。我认为没有为图像插值方案定义任何标准,所以每个人都有自己的方法。
  • 你有没有想过为什么cv2tf有不同的双线性interp结果?
  • 你有没有办法让cv的输出匹配tensorflow的输出?
  • 很遗憾没有。修复代码中的其他错误后,我能够处理 cv2 和 tf 输出之间的细微差别。

标签: python image image-processing tensorflow cv2


【解决方案1】:

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

Histrogramm of pixel-wise difference

如您所见,这看起来很正态分布。 (我也很惊讶像素级的差异)。您的准确性下降的问题可能就在这里。在this paperGoodfellow 等人。描述对抗性示例和分类系统的影响。我认为这里的问题与此类似。如果您用于网络的原始权重是使用一些输入管道训练的,该管道给出了 cv2 函数的结果,那么来自 TF 输入管道的图像就像一个对抗性示例。

(示例请参见第 3 页顶部的图片...我不能发布超过两个链接。)

所以最后我认为,如果您想将原始网络权重用于他们训练网络的相同数据,您应该使用相似/相同的输入管道。如果您使用权重在您自己的数据上微调网络,这应该不是什么大问题,因为您重新训练分类层以处理新的输入图像(来自 TF 管道)。

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

【讨论】:

    猜你喜欢
    • 2017-01-27
    • 2020-04-26
    • 2017-06-04
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-25
    相关资源
    最近更新 更多