这是我的代码,
img_path = tf.read_file(testqueue[0])
my_img = tf.image.decode_jpeg(img_path)
sess.run(my_img)
print my_img.get_shape()
结果是,
(?, ?, ?)
为什么我得到这个结果?
答案 0 :(得分:1)
回答这个问题并提供一些细节。
tensor_name.shape
返回图形编译时可用的形状信息。它依赖于tensor- 属性。
tf.decode_jpeg
已注册here。在创建图形期间,TensorFlow在InferenceContext
下运行形状传播。给定输入张量中已知的形状属性,每个操作都提供其输出张量的外观提示。
例如,“rgb2gray”操作只会复制输入张量的形状(比如[b',h',w',c']并将输出设置为[b',h',w', 1]。它不需要知道b',h',w'的确切值,因为它可以只复制这些先前的值。
查看具体的implementation for tf.decode_jpeg
,此操作显然可以处理channels
属性:
// read the attribute "channels from "tf.image.decode_jpeg(..., channels)"
TF_RETURN_IF_ERROR(c->GetAttr("channels", &channels));
// ....
// set the tensor information "my_img.get_shape()" will have
c->set_output(0, c->MakeShape({InferenceContext::kUnknownDim,
InferenceContext::kUnknownDim, channels_dim}));
前两个维度设置为InferenceContext::kUnknownDim
,因为操作只知道高度和宽度,但具体值可以变化。它可以最好地猜测通道轴的外观。如果您指定属性tf.decode_jpeg(..., channels=3)
,则可以并将设置最后一个
这导致形状(?,?,?),因为if-branch channels ==0
变为活跃here。
另一方面,tf.shape
定义here结束here。这会检查实际的张量 - 内容 here:
// get actual tensor-shape from the value itself
TensorShape shape;
OP_REQUIRES_OK(ctx, shape_op_helpers::GetRegularOrVariantShape(ctx, 0, &shape));
const int rank = shape.dims();
// write the tensor result from "tf.shape(...)"
for (int i = 0; i < rank; ++i) {
int64 dim_size = shape.dim_size(i);
// ...
vec(i) = static_cast<OutType>(dim_size); // the actual size for dim "i"
}
就像tf.shape
对之前的操作说的那样:
几分钟前你可以告诉我你得出的结论。我不在乎你在这一点上是多么聪明,也不在乎你对形状的猜测。看,我只看一下现在有内容的具体张量,我就完成了。
这有一些重要的后果:
tf.shape
是张量,而tensorname.shape
不是tf.shape
tensorname.shape
tf.reshape(img, [128, 128, 3]
您可能也感兴趣tf.image.extract_jpeg_shape
已实施here。