将Python OpenCV中的Mat图像转换为TensorFlow图像数据

12

我想用Python和OpenCV从视频中捕获帧,然后用Tensorflow对捕获的Mat图像进行分类。问题是我不知道如何将Mat格式转换为3D Tensor变量。这是我目前使用Tensorflow(从文件加载图像)的方式:

image_data = tf.gfile.FastGFile(imagePath, 'rb').read()
with tf.Session() as sess:
    softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
    predictions = sess.run(softmax_tensor,
                           {'DecodeJpeg/contents:0': image_data})

我将非常感激任何帮助,提前致谢。


可能是将mat格式的张量导入tensorflow的重复问题。 - thesonyman101
5个回答

15

使用imread加载OpenCV图像,然后将其转换为numpy数组。

为了输入到Inception v3模型中,您需要使用Mult:0张量作为入口点,它期望一个4维张量,其布局为:[批索引,宽度,高度,通道] 后三个维度对于cv::Mat来说没有问题,第一个维度只需要是0,因为您不想输入一批图像,而是单个图像。 代码如下:

#Loading the file
img2 = cv2.imread(file)
#Format for the Mul:0 Tensor
img2= cv2.resize(img2,dsize=(299,299), interpolation = cv2.INTER_CUBIC)
#Numpy array
np_image_data = np.asarray(img2)
#maybe insert float convertion here - see edit remark!
np_final = np.expand_dims(np_image_data,axis=0)

#now feeding it into the session:
#[... initialization of session and loading of graph etc]
predictions = sess.run(softmax_tensor,
                           {'Mul:0': np_final})
#fin! 

此致敬礼,

Chris

编辑:我刚刚注意到,Inception网络希望将强度值归一化为[-0.5,0.5]的浮点数,因此请在构建RGB图像之前使用以下代码进行转换:

np_image_data=cv2.normalize(np_image_data.astype('float'), None, -0.5, .5, cv2.NORM_MINMAX)

这个代码即使在视频帧中也能完美运行。我使用以下代码来分析OpenCV + Tensorflow的视频文件。`ret, frame = cap.read() ` `image = cv2.resize(frame,dsize=(299,299), interpolation = cv2.INTER_CUBIC)` `np_image_data = np.asarray(image)` `image = np.expand_dims(image, axis=0)` `image = preprocess(image)` `preds = model.predict(image)` - Prabath

8
使用Tensorflow 2.0和OpenCV 4.2.0,您可以通过以下方式进行转换:
import numpy as np
import tensorflow as tf
import cv2 as cv

width = 32
height = 32

#Load image by OpenCV
img = cv.imread('img.jpg')

#Resize to respect the input_shape
inp = cv.resize(img, (width , height ))

#Convert img to RGB
rgb = cv.cvtColor(inp, cv.COLOR_BGR2RGB)

#Is optional but i recommend (float convertion and convert img to tensor image)
rgb_tensor = tf.convert_to_tensor(rgb, dtype=tf.float32)

#Add dims to rgb_tensor
rgb_tensor = tf.expand_dims(rgb_tensor , 0)

#Now you can use rgb_tensor to predict label for exemple :

#Load pretrain model, made from: https://www.tensorflow.org/tutorials/images/cnn
model = tf.keras.models.load_model('cifar10_model.h5')

#Create probability model 
probability_model = tf.keras.Sequential([model, 
                                     tf.keras.layers.Softmax()])
#Predict label
predictions = probability_model.predict(rgb_tensor, steps=1)

5
看起来您正在使用预训练和预定义的Inception模型,其中有一个名为DecodeJpeg/contents:0的张量。如果是这样,那么该张量希望包含一个标量字符串,其中包含JPEG图像的字节。
您有几个选择,其中之一是在网络中进一步查找将JPEG转换为矩阵的节点。我不确定MAT格式是什么,但这将是一个[height, width, colour_depth]表示。如果您可以以该格式获取您的图像,则可以将DecodeJpeg...字符串替换为要输入的节点的名称。
另一个选择是将您的图像简单地转换为JPEG并直接输入。

谢谢Mark,我解决了这个问题,将OpenCV Mat图像保存到临时文件中,然后在发布时加载。虽然不是最干净的解决方案,但它可以工作。 - Txeif

1
你应该能够将OpenCV的mat格式转换为NumPy数组,如下所示:
np_image_data = np.asarray(image_data)

一旦您将数据转换为numpy数组,您可以通过喂养机制将其传递给TensorFlow,就像@thesonyman101引用的链接中所示:
feed_dict = {some_tf_input:np_image_data}
predictions = sess.run(some_tf_output, feed_dict=feed_dict)

0
在我的情况下,我需要从文件中读取图像,进行一些处理,然后注入到Inception中以获取来自特征层(称为最后一层)的返回值。我的解决方案简短而有效。
        img = cv2.imread(file)
        ... do some processing 
        img_as_string = cv2.imencode('.jpg', img)[1].tostring()
        features = sess.run(last_layer, {'DecodeJpeg/contents:0': img_as_string})

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接