在open cv2 python中使用Tensor flow 2.0对象的方法是啥,为啥这么迂回?

Posted

技术标签:

【中文标题】在open cv2 python中使用Tensor flow 2.0对象的方法是啥,为啥这么迂回?【英文标题】:What is the way to use Tensor flow 2.0 object in open cv2 python and why is it so circuitous?在open cv2 python中使用Tensor flow 2.0对象的方法是什么,为什么这么迂回? 【发布时间】:2019-09-23 00:20:16 【问题描述】:

我像这样使用张量流 api (2.0) 加载图像:

def load(image_file):
  image = tf.io.read_file(image_file)
  image = tf.image.decode_jpeg(image)

现在我有了这个对象,我想展示这个图像,我可以简单地使用 matplotlib.pyplot,这样就可以了。

plt.figure()
plt.imshow(re/255.0)
plt.show()

但是,使用 OpenCV2 进行此尝试从一开始就有问题,大多数示例来自 1.0,并带有基于 .eval() 会话的 numpy 转换建议。一种方法是首先将张量流对象转换为 numpy,这是 API 文档中执行此操作的函数:

TensorFlow
API r2.0
TensorFlow Core 2.0a
Python
tf.make_ndarray
Create a numpy ndarray from a tensor.

我不明白为什么这不起作用,我得到了一些错误,而我只想做一些简单的事情,然后使用一些开放的 cv2 函数,如重新映射、调整大小等:

文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\eager\def_function.py", 第 426 行,在 调用 self._initialize(args, kwds, add_initializers_to=initializer_map) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\eager\def_function.py", 第 370 行,在 _initialize *args, **kwds)) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\eager\function.py", 第 1313 行,在 _get_concrete_function_internal_garbage_collected graph_function, _, _ = self._maybe_define_function(args, kwargs) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\eager\function.py", 第 1580 行,在 _maybe_define_function graph_function = self._create_graph_function(args, kwargs) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\eager\function.py", 第 1512 行,在 _create_graph_function 中 capture_by_value=self._capture_by_value),文件“C:\Python\Python37\lib\site-packages\tensorflow\python\framework\func_graph.py”, 第 694 行,在 func_graph_from_py_func func_outputs = python_func(*func_args, **func_kwargs) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\eager\def_function.py", 第 317 行,在 Wrapped_fn 中 return weak_wrapped_fn().wrapped(*args, **kwds) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\framework\func_graph.py", 第 686 行,在包装器中 ), args, kwargs) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\autograph\impl\api.py", 第 392 行,在 convert_call 中 结果 = converted_f(*effective_args, **kwargs) 文件“C:\Users\syeda\AppData\Local\Temp\tmpnahp3og4.py”,第 32 行,在 tf__random_deform im2 = ag__.converted_call('make_ndarray', tf, ag__.ConversionOptions(recursive=True, verbose=0, strip_decorators=(tf.function, defun_9, ag__.convert, ag__.do_not_convert, ag__.converted_call), force_conversion=False, optional_features=(), internal_convert_user_code=True), (real_image,), ) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\autograph\impl\api.py", 第 267 行,在 convert_call 中 return _call_unconverted(f, args, kwargs) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\autograph\impl\api.py", 第 188 行,在 _call_unconverted 返回 f(*args, **kwargs) 文件 "C:\Python\Python37\lib\site-packages\tensorflow\python\framework\tensor_util.py", 第 596 行,在 MakeNdarray shape = [d.size for d in tensor.tensor_shape.dim] AttributeError: 'Tensor' object has no attribute 'tensor_shape'

2018 年 5 月 5 日更新: 搜索更多后,我发现这与 Tensorflow 图执行有关。 我有一个功能

def load_image_train(image_file):
  input_image, real_image = load(image_file)
 print(type(real_image))
  print(real_image.shape)
  some_image = Open CV operations like filtering, jitter etc performed on real_image
return some_image

当使用 .numpy() 属性急切调用时,这很有效,但是当像下面的代码那样调用时,以及当您尝试检查 real_image 是什么以及它的类型返回时

类'tensorflow.python.framework.ops.Tensor'(无,无,无)

请指教。

# Input pipeline
train_dataset = tf.data.Dataset.list_files(PATH+'train/*.jpg')
train_dataset = train_dataset.shuffle(BUFFER_SIZE)
train_dataset = train_dataset.map(load_image_train,
                               num_parallel_calls=tf.data.experimental.AUTOTUNE)
train_dataset = train_dataset.batch(1)

2018 年 5 月 5 日更新:我决定对数据进行预处理,这样我就不必担心在数据加载期间使用任何 opencv 功能。但是在训练期间,我仍然想做一些 openCV 操作。现在根据@giser_yugang 的建议,我尝试使用py_function,我将opencv 操作包装在py_function 中,并在包装​​器tf.function 中调用该函数。这个包装器 tf.function 我在训练步骤中调用。但是我从这个包装函数得到的输出是这样的:

class 'tensorflow.python.framework.ops.Tensor'
unknown

然后,如果我尝试在下一个 train step 操作中消耗这个张量,我会得到一个

incompatible with the layer: its rank is undefined, but the layer requires a defined rank.

如果我不在我的训练步骤中使用这个 py_function 包装器并直接使用 opencv 尝试 numpy 操作,我会得到另一个错误

AttributeError: 'Tensor' object has no attribute 'numpy'

我猜这两种方式你都赢不了!

【问题讨论】:

我尝试了 np.array(tensor) 转换,但它也没有用,因为张量类型仍然存在。 你试过 tensor.numpy()。这应该是 TF 2.0a 中的方法。您可能会遇到很多问题,因为您已经在使用 TF 2 而不是很多人,很多资源对您来说已经过时了。使用 TF 1.13 获得更好的支持。 我试过 image.numpy() 我之前得到了错误,在这里记录:AttributeError: 'Tensor' object has no attribute 'numpy'。 opencv也直接兼容numpy数组(不需要转换成cv2.UMat) img = cv2.imread('Image0.png') X = img[:,:,1] print(X.shape) print (type(X)) 得到这个输出 (1080, 1920) 我做了一些搜索,我发现我可以使用 .numpy() 当它的渴望张量而不是当它只是张量时, .nu​​mpy() 方法将张量显式转换为 numpy 数组 float32 float32 float32 float32 我觉得你需要Applying arbitrary Python logic with tf.py_func()。 【参考方案1】:

使用 OpenCV + Tensorflow 2.0 很简单。

假设我们在当前目录中有图像“wink.jpg”(见附件中的眨眼图像),那么可以使用Tensorflow 2.0读取JPEG图像并得到tf.Tensor,dtype=uint8,得到从中获取一个 numpy 数组并使用 OpenCV 对其进行可视化(根据 OpenCV 的需要,采用 BGR 格式)。

import tensorflow as tf
import cv2


def load(image_file):
    image = tf.io.read_file(image_file)
    image = tf.image.decode_jpeg(image)
    return image


wink = load("wink.jpg")
print(wink.shape, wink.dtype)

# Get a Numpy BGR image from a RGB tf.Tensor
image = cv2.cvtColor(wink.numpy(), cv2.COLOR_RGB2BGR)

cv2.imshow("image", image)
cv2.waitKey()

如果您遇到与 Graph 架构相关的问题,可能是因为您:

或者使用tf.function将代码转换成图形(在这种情况下只需删除注释) 或者在 tf.data.Dataset 方法中使用 OpenCV(在这种情况下,不要使用 OpenCV 或在需要 OpenCV 的地方使用 tf.py_func) 或者使用错误版本的 Tensorflow,不是 2,默认情况下启用了 Eager 模式(通过运行 pip list |grep tfpip list | grep tensor 检查一切是否正常,如果你看到一些奇怪的东西,比如安装了超过 1 个 TF 版本,我建议删除环境重新安装)。

【讨论】:

我认为这里的问题被误解了。我已经将 opencv 与张量对象一起使用,因为两者都与 numpy 数组兼容,请参阅更新部分“当使用 .numpy() 属性热切调用时效果很好,......”但是在训练步骤或其他涉及的操作中我无法使用相同的函数,因为现在 numpy 属性将丢失,调试它不会产生任何形状,[None, none, none] 作为 W x H x C 数组。 那是因为你已经用 tf.function 注释了 train 函数,我猜。如果您以纯粹的渴望运行训练循环,它应该会继续工作。顺便说一句,您应该发布所有重现您的问题的代码,否则,仅通过猜测会发生什么来提供帮助是很困难的 使用这里的代码,tensorflow.org/alpha/tutorials/generative/pix2pix,如果你能告诉我如何做一个 opencv 操作,比如让我们说 cv::remap、cv::gaussian 等到其中的一个图像train_step 我将接受并关闭它。感谢您的回复。 不能在输入数据管道中使用opencv,每个操作都应该是tensorflow操作。您可以尝试在map 方法中使用tf.py_func,但我不保证它会起作用 我已经尝试过 tf.py_func ,请参阅我的更新 5/5/2018 它不起作用。

以上是关于在open cv2 python中使用Tensor flow 2.0对象的方法是啥,为啥这么迂回?的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV基本功 之 图像的掩模运算 & 合并专题 -小啾带学Python-Open_CV系列

Python - 如何使用Open-cv或PIL将24位PNG图像转换为32位

在jupyter笔记本电脑中使用opencv时出错:

cv2.imread()与PIL中Image.open()

PIL Image.open 和 cv2.imdecode 的区别

PIL.Image.open 与 cv2.imread 读取的图片在像素点上不一致