CV2图像处理与tf.image处理的区别
Differences between CV2 image processing and tf.image processing
我最近不再使用 cv2 作为 Tensorflow 的 tf.image 图像处理模块。但是,我的验证准确率下降了大约 10%。
我认为这个问题与
有关
- cv2.imread() 对比 tf.image.decode_jpeg()
- cv2.resize() 对比 tf.image.resize_images()
虽然这些差异会导致更差的准确性,但使用 plt.imshow() 时,图像似乎无法由人类区分。例如,使用 ImageNet 验证数据集的图像 #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() 有何不同?
谢谢!
正如 vijay m 正确指出的那样,通过将 dct_method
更改为 "INTEGER_ACCURATE",您将使用 cv2 或 tf 获得相同的 uint8 图像。问题确实似乎是调整大小的方法。我还尝试强制 Tensorflow 使用与 cv2 默认使用的相同插值方法(双线性),但结果仍然不同。可能是这种情况,因为 cv2 对整数值进行插值,而 TensorFlow 在插值之前转换为浮点数。但这只是一个猜测。如果您通过 TF 和 cv2 绘制调整大小的图像之间的像素差异,您将获得以下直方图:
Histrogramm of pixel-wise difference
如您所见,这看起来很正态分布。 (我也很惊讶像素方面的差异)。您的准确性下降的问题可能就在这里。在 this paper Goodfellow 等人中。描述对抗性示例和分类系统的效果。我认为这里的这个问题与此类似。如果您用于网络的原始权重是使用一些提供 cv2 函数结果的输入管道进行训练的,则来自 TF 输入管道的图像类似于对抗性示例。
(有关示例,请参见第 3 页顶部的图片...我不能 post 两个以上的链接。)
所以最后我认为如果你想对他们训练网络的相同数据使用原始网络权重,你应该使用 similar/same 输入管道。如果您使用权重根据自己的数据微调网络,这应该不是什么大问题,因为您重新训练了分类层以使用新的输入图像(来自 TF 管道)。
以及@Ishant Mrinal:请查看 OP 在 GIST 中提供的代码。他知道 BGR (cv2) 和 RGB (TF) 的区别,并将图像转换为相同的颜色 space。
我最近不再使用 cv2 作为 Tensorflow 的 tf.image 图像处理模块。但是,我的验证准确率下降了大约 10%。
我认为这个问题与
有关- cv2.imread() 对比 tf.image.decode_jpeg()
- cv2.resize() 对比 tf.image.resize_images()
虽然这些差异会导致更差的准确性,但使用 plt.imshow() 时,图像似乎无法由人类区分。例如,使用 ImageNet 验证数据集的图像 #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() 有何不同?
谢谢!
正如 vijay m 正确指出的那样,通过将 dct_method
更改为 "INTEGER_ACCURATE",您将使用 cv2 或 tf 获得相同的 uint8 图像。问题确实似乎是调整大小的方法。我还尝试强制 Tensorflow 使用与 cv2 默认使用的相同插值方法(双线性),但结果仍然不同。可能是这种情况,因为 cv2 对整数值进行插值,而 TensorFlow 在插值之前转换为浮点数。但这只是一个猜测。如果您通过 TF 和 cv2 绘制调整大小的图像之间的像素差异,您将获得以下直方图:
Histrogramm of pixel-wise difference
如您所见,这看起来很正态分布。 (我也很惊讶像素方面的差异)。您的准确性下降的问题可能就在这里。在 this paper Goodfellow 等人中。描述对抗性示例和分类系统的效果。我认为这里的这个问题与此类似。如果您用于网络的原始权重是使用一些提供 cv2 函数结果的输入管道进行训练的,则来自 TF 输入管道的图像类似于对抗性示例。
(有关示例,请参见第 3 页顶部的图片...我不能 post 两个以上的链接。)
所以最后我认为如果你想对他们训练网络的相同数据使用原始网络权重,你应该使用 similar/same 输入管道。如果您使用权重根据自己的数据微调网络,这应该不是什么大问题,因为您重新训练了分类层以使用新的输入图像(来自 TF 管道)。
以及@Ishant Mrinal:请查看 OP 在 GIST 中提供的代码。他知道 BGR (cv2) 和 RGB (TF) 的区别,并将图像转换为相同的颜色 space。