How to resize elements in a ragged tensor in TensorFlow - tensorflow

I would like to resize every element in a ragged tensor. For example, if I have a ragged tensor of various sized images, how can I resize each one so that the dimensions are the same?
For example,
digits = tf.ragged.constant([np.zeros((1,60,60,1)), np.zeros((1,46,75,1))])
resize_lambda = lambda x: tf.image.resize(x, (60,60))
res = tf.ragged.map_flat_values(resize_lambda, digits)
I wish res to be a tensor of shape (2,60,60,1). How can I achieve this?
To clarify, this would be useful if within a custom layer we wanted to slice or crop sections from a single image to batch for inference in the next layer. In my case, I am attempting to combine two models (a model to segment an image into multiple cropped images of varying size and a classifier to predict each sub-image). I am also using tf 2.0

You should be able to do the following.
import tensorflow as tf
import numpy as np
digits = tf.ragged.constant([np.zeros((1,60,60,1)), np.zeros((1,46,75,1))])
res = tf.concat(
[tf.image.resize(digits[i].to_tensor(), (60,60)) for i in tf.range(digits.nrows())],
axis=0)

Related

How to dilate y_true inside a custom metric in keras/tensorflow?

I am trying to code a custom metric for U-net model implemented using keras/tensorflow. In the metric, I need to use the opencv function, 'cv2.dilate' on the ground truth. When I tried to use it, it gave the error as y_true is a tensor and cv2.dilate expects a numpy array.
Any idea on how to implement this?
I tried to convert tensor to numpy array but it is not working.
I searched for the tensorflow implementation of cv2.dilate but couldnt find one.
One possibility, if you are using a simple rectangular kernel in your dilation, is to use tf.nn.max_pool2d as a replacement.
import numpy as np
import tensorflow as tf
import cv2
image = np.random.random((28,28))
kernel_size = 3
# OpenCV dilation works with grayscale image, with H,W dimensions
dilated_cv = cv2.dilate(image, np.ones((kernel_size, kernel_size), np.uint8))
# TensorFlow maxpooling works with batch and channels: B,H,W,C dimenssions
image_w_batch_and_channels = image[None,...,None]
dilated_tf = tf.nn.max_pool2d(image_w_batch_and_channels, kernel_size, 1, "SAME")
# checking that the results are equal
np.allclose(dilated_cv, dilated_tf[0,...,0])
However, given that you mention that you are applying dilation on the ground truth, this dilation does not need to be differentiable. In that case, you can wrap your dilation in a tf.numpy_function
from functools import partial
# be sure to put the correct output type, tf.float64 is working in that specific case because numpy defaults to float64, but it might be different in your case
dilated_tf_npfunc = tf.numpy_function(
partial(cv2.dilate, kernel=np.ones((kernel_size, kernel_size), np.uint8)), [image]
)

tensor slicing in tensorflow

I want to do the same numpy operation as follow to make a custom layer
img=cv2.imread('img.jpg') # img.shape =>(600,600,3)
mask=np.random.randint(0,2,size=img.shape[:2],dtype='bool')
img2=np.expand_dims(img,axis=0) #img.shape => (1,600,600,3)
img2[:,mask,:].shape # => (1, 204030, 3)
this is my first attemp but I failed. I can't do the same operation for for tensorflow tensors
class Sampling_layer(keras.layers.Layer):
def __init__(self,sampling_matrix):
super(Sampling_layer,self).__init__()
self.sampling_matrix=sampling_matrix
def call(self,input_img):
return input_img[:,self.sampling_matrix,:]
More Explanations:
I want to define a keras layer so that given a batch of images it use a sampling matrix and give me a batch of sampled vectors for the images.The sampling matrix is a random boolean matrix the same size as the image. The slicing operation I used is straight forward for numpy arrays and works perfectly. but I can't get it done with tensors in tensorflow. I tried to use loops to perform the operation I want manually but I failed.
You can do the following.
import numpy as np
import tensorflow as tf
# Batch of images
img=np.random.normal(size=[2,600,600,3]) # img.shape =>(600,600,3)
# You'll need to match the first 3 dimensions of mask with the img
# for that we'll repeat the first axis twice
mask=np.random.randint(0,2,size=img.shape[1:3],dtype='bool')
mask = np.repeat(np.expand_dims(mask, axis=0), 2, axis=0)
# Defining input layers
inp1 = tf.keras.layers.Input(shape=(600,600,3))
mask_inp = tf.keras.layers.Input(shape=(600,600))
# The layer you're looking for
out = tf.keras.layers.Lambda(lambda x: tf.boolean_mask(x[0], x[1]) )([inp1, mask])
model = tf.keras.models.Model([inp1, mask_inp], out)
# Predict on sample data
toy_out = model.predict([img, mask])
Note that both your images and mask needs to have the same batch size. I couldn't find a solution to make this work without repeating the mask on batch axis to match the batch size of images. This is the only possible solution that came to my mind, (assuming that your mask changes for every batch of data).

How to make image cube for 3d convolution with file path

Recently, I am studying 3d convolution for video image processing with tensorflow.
I make model with tutorial blog. But i want to make my custom dataset. My input image's shape is (128,128,3) and i want to make image cube(128,128,100,3). I use tensorflow.data.dataset and I tried to create a map function by recalling my memories I used for 2d convolution. I want to image cube using path that consist of (Number of image cube, 100) with tf.data.dataset map function because of running out of memory when using NumPy.
I tried to use code like the following
def load_image(path):
images = []
for i, p in enumerate(path):
image_string = tf.io.read_file(p)
image = tf.io.decode_jpeg(p, channels=3)
image = tf.reshape(image, [128,128,1,3])
image = image / 255
images.append(image)
image_block = tf.concat(images, axis=2)
return image_block
train_data = tf.data.Dataset.from_tensor_slices(total_files) # shape (1077,100)
train_data = train_data.map(load_images, num_parallel_calls=tf.data.experimental.AUTOTUNE)
But have error that tensor's shape changes. And i also use tf.Variable using .assign but have similar error.
How to make 3d convolution's input image cube with path??? I use tensorflow 2.0.
So you cannnot iterate over tensor like for x in tensor. In that case you can for example iterate over range and get value by index like
for x in range(tf.shape(tensor)[0]):
y = tensor[x]

Tensorflow taking input in the same order as input

I am using tensorflow to test my trained model on test images. I am feeding the images to tensorflow as below:
image_ab, image_aba = sess.run(fetches, feed_dict={self.image_a: image_a,
self.is_train: False})
I printed the image_a and image_ab and observed that image_a is not in the same order as the input images i give.
For some reasons i want the output also to be in the same order as input images.
Does tensorflow usually takes input in the same order as the input given?
I assume you mean image_ab is not in the same order. Because image_a is the input that you feed to tensorflow. If this input is not ordered correctly, it will be your preprocessing, not tensorflow.
Tensorflow usually works on batches of data. For images, the convention for batch dimensions is:
[batch, x, y, colors]
The operations that tensorflow performs are parallelized along the batch. If you simply plug convolutional layers together, the order of the batch should be preserved.
However, it is surely possible to reorder things in tensorflow:
import numpy as np
import tensorflow as tf
x = tf.placeholder(shape=(2,1), dtype="float32")
y = tf.concat([x[1], x[0]], axis=0)
sess = tf.Session()
sess.run([x,y], feed_dict={x:np.random.rand(2,1)})
This code will read in x, change the order of its entries and produce y.
So tensorflow can reorder your images. You could search your code for a pattern like the one in my example.

`decode_predictions` expects a batch of predictions (i.e. a 2D array of shape (samples, 1000)). Found array with shape: (1, 5)

A retrained the inception_v3 model for my own test data. (Backstory: im just trying to understand how the whole process works before im trying it on my 130 class "problem")
Now i got the .h5.
I tryed to import it and predict some image. But i only get the following error messages.
ValueError: `decode_predictions` expects a batch of predictions (i.e. a 2D array of shape (samples, 1000)). Found array with shape: (1, 5)
May some can tell me what im doing horrible wrong?
my thoughts:
I read something that i need a vector of 1000 probabilitys (for 1000 classes) but i dont have them.
How do i create such vector and set all 1000-my_num_of_classes(in my case 5) to like 0?
I guess i have to preshape a 2d array of a size of 1000. But it dont get it what "samples" or in my case the "1" represent.
Or do i have to write some matching for my array of [1.0592173e-07 8.3998479e-09 9.9305904e-01 4.8276172e-05 6.8924953e-03] (in my case). Where i interprete that the 3 (id 2) class(which got trained) have the highest probability?
So maybe like a file where i have all the trained classes in order like trained? to match the highest with the correspoding row (label)?
Would be awesome :)
That would be my code for predicition
# Testing Inceptionv3
#from keras.applications.imagenet_utils import decode_predictions
import numpy as np
from keras.applications.inception_v3 import decode_predictions
import matplotlib.pyplot as plt
import os
from keras.models import load_model
from PIL import Image
my_model = load_model('my_model.h5')
#images = transform_img_fn([os.path.join('data','rose.jpg')])
img = Image.open('./data/rose.jpg')
img = img.resize((150,150))
img = np.array(img)
img = img / 255.0
img = img.reshape(1,150,150,3)
#base_model = inc_net.InceptionV3(weights='imagenet', include_top=False)
preds = my_model.predict(img)
for x in decode_predictions(preds)[0]:
print(x)
The decode_predictions utility converts the class predictions of a pretrained ImageNet model into the corresponding human-readable ImageNet classes.
Using "decode_predictions" only makes sense if your model outputs the ImageNet classes (1000-dimensional). Your model (my_model) appears to return predictions over 5 classes. It's not an ImageNet model.