I have this simple function below, which takes in a tensorflow string tensor (filename
) and retrieves an image.
def get_image(filename):
filename = filename.numpy()
img = tf.io.read_file(f'images/{filename}')
return img
But I get AttributeError: 'Tensor' object has no attribute 'numpy'
I looked here for a solution but nobody had a good solution for this. A lot of people gave suggestions on how to enable eager execution, but none of it worked. Is it really that hard to retrieve data from a tensor...?
Or is there another way to do what I want in this scenario, without converting to numpy?
CodePudding user response:
I'm assuming you likely have a Tensorflow Dataset and are using .map()
to load each image from disk or something similar. This is possible if you wrap the get_image
function with tf.py_function
but this has some downsides in that it becomes single-threaded essentially. There are some other tradeoffs that are detailed here.
s = tf.constant(["test", "test1"])
dataset = tf.data.Dataset.from_tensor_slices(s)
dataset = dataset.map(lambda x: tf.py_function(get_image, [x], [tf.string]))
If you're able to entertain a different approach, you might want to look into using tf.keras.utils.image_dataset_from_directory
which will give you a Dataset with all your images loaded without restricting you to a single thread.
image_height = 256
image_width = 256
batch_size = 20
train_ds = tf.keras.utils.image_dataset_from_directory("images/*",
validation_split=0.2,
subset="training",
seed=123,
image_size=(img_height, img_width),
batch_size=batch_size)
CodePudding user response:
TL;DR First of all, Maybe the below example helps you then you can read a solution for solving and reading images from the path.
Example for generating error (We can not access to numpy in this type of function)
# With @tf.function
@tf.function
def func(tns):
tf.print(tns.numpy())
func(tf.random.uniform(shape=(2,)))
# -> AttributeError: 'Tensor' object has no attribute 'numpy'
# Without @tf.function
def func(tns):
tf.print(tns.numpy())
func(tf.random.uniform(shape=(2,)))
# -> array([0.86797523, 0.10352373], dtype=float32)
Solution: For reading images from your path you need to consider:
- Create a list of paths with
os.path.join
that you want to read images from it. - After reading images make sure to use
tf.image.decode_png
.
import tensorflow as tf
import os
path = 'images'
path_images = [os.path.join(path, img) for img in os.listdir(path)]
img_dataset = tf.data.Dataset.from_tensor_slices(path_images)
def get_image(filename):
img = tf.io.read_file(filename)
img = tf.image.decode_png(img, channels=3)
return img
img_dataset = img_dataset.map(get_image, num_parallel_calls=tf.data.AUTOTUNE)
for img in img_dataset.take(1):
print(img.shape)
# (100, 100, 3)
Creating random images in path /images/
:
from PIL import Image
import numpy as np
for i in range(10):
imarray = np.random.rand(100,100,3) * 255
im = Image.fromarray(imarray.astype('uint8')).convert('RGB')
im.save(f'images/image_{i}.png')