Processing an Image using Tensorflow - python

I've a 15 images which are stored locally. How do I transform these images to a array using tensorflow for a CNN type of Classification?

Convert the image to numpy array format
import cv2
im = cv2.imread("some_image.tiff")
Reshape them to an arbitrary, but identical, size
def reshape(image_array):
return np.reshape(image_array, [128, 128, 3])
Put them all in a list and then standardize them so they all have standardized pixel values using:
def per_image_standardization(arrays):
sess = tf.InteractiveSession()
standardized_tensors = tf.map_fn(lambda array:
tf.image.per_image_standardization(array),
arrays)
standardized_images = standardized_tensors.eval()
return standardized_images

Related

Convert tf.Tensor to numpy array and than save it as image in without eager_execution

My OC is big sur for apple M1, therefore my tensorflow version is 2.4 which has been installed from official apple github repo(https://github.com/apple/tensorflow_macos). When i use code bellow, i get tensor(<tf.Tensor 'StatefulPartitionedCall:0' shape=(1, 2880, 4320, 3) dtype=float32>)
import tensorflow as tf
import tensorflow_hub as hub
from PIL import Image
import numpy as np
from tensorflow.python.compiler.mlcompute import mlcompute
from tensorflow.python.framework.ops import disable_eager_execution
disable_eager_execution()
mlcompute.set_mlc_device(device_name='gpu') # Available options are 'cpu', 'gpu', and 'any'.
tf.config.run_functions_eagerly(False)
print(tf.executing_eagerly())
image = np.asarray(Image.open('/Users/alex26/Downloads/face.jpg'))
image = tf.cast(image, tf.float32)
image = tf.expand_dims(image, 0)
model = hub.load("https://tfhub.dev/captain-pool/esrgan-tf2/1")
sr = model(image) #<tf.Tensor 'StatefulPartitionedCall:0' shape=(1, 2880, 4320, 3)dtype=float32>
How to get image from sr Tensor?
If you execute eagerly it works:
import tensorflow as tf
import numpy as np
import tensorflow_hub as hub
model = hub.load("https://tfhub.dev/captain-pool/esrgan-tf2/1")
x = np.random.rand(1, 224, 224, 3).astype(np.float32)
image = model(x)
Then you can use tf.keras.preprocessing.image.save_img to save the resulting image. You may have to multiply the result by 255 and convert to np.uint8 for that function to work, I'm not sure.
To create an numpy array from a tensorflow tensor you can use `make_ndarray' : https://www.tensorflow.org/api_docs/python/tf/make_ndarray
make_ndarray takes proto tensor as argument so you have to convert the tensor into a proto tensor first
proto_tensor = tf.make_tensor_proto(a) # convert tensor a to a proto tensor
( https://www.geeksforgeeks.org/tensorflow-how-to-create-a-tensorproto/ )
Convert a tensor to numpy array in Tensorflow?
the tensor has to be if shape (img_height, img_width, 3), the 3 if you want to generate an RGB image (3 channels), see the following code to convert an numpy aaray to an image using PIL
To generate an image from the numpy array then you can use PIL (Python Imaging Library) : How do I convert a numpy array to (and display) an image?
from PIL import Image
import numpy as np
img_w, img_h = 200, 200
data = np.zeros((img_h, img_w, 3), dtype=np.uint8) <- zero np_array depth 3 for RGB
data[100, 100] = [255, 0, 0] <- fille array with 255,0,0 in RGB
img = Image.fromarray(data, 'RGB') <- array to image (all black then)
img.save('test.png')
img.show()
source : https://www.w3resource.com/python-exercises/numpy/python-numpy-exercise-109.php
Is this the old fashioned way that you are looking after?
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(sr)

Get intermediate output from Keras/Tensorflow during prediction and modify the value before passing to next layer

I want to modify the values of each layers during prediction process. I have one convolution layer, dense layer and output layer (softmax).
I want to modify the result of convolution layer's output before passing it to hidden layers during prediction time.
import tensorflow as tf
from keras import backend as K
from keras.utils import to_categorical
# make a prediction for a new image.
from keras.preprocessing.image import load_img
from keras.preprocessing.image import img_to_array
from keras.models import load_model
import numpy as np
import pandas as pd# load and prepare the image
def load_image(img):#
# load the image
#img = load_img(filename, grayscale=True, target_size=(28, 28))
# convert to array
#img = img_to_array(img)
# reshape into a single sample with 1 channel
img = img.reshape(1, 28, 28, 1)
# prepare pixel data
img = img.astype('uint8')
img = img #/ 255
return img
data_test = pd.read_csv('mnistdata/mnist_testE.csv')
X_test = np.array(data_test.iloc[:, 1:])
y_test = to_categorical(np.array(data_test.iloc[:, 0]))
# load an image and predict the class
#X_test = X_test.reshape(X_test.shape[0], 28, 28, 1)#def run_example():
# load the image
img = load_image(X_test[1])
# load model
model = load_model('final_modelv4.h5')
digit = model.predict_classes(img)
print(digit)
Can anyone guide me how to modify this code to change the values of each layer's results?
Providing the solution here (Answer Section), even though it is present in the Comments Section, for the benefit of the community.
You can Convert a TensorFlow model into a compressed flat buffer with the TensorFlow Lite Converter. Quantize by converting 32-bit floats to more efficient 8-bit integers or run on GPU.
You can find details about tensroflow lite here.
This page will be most relevant for your query - Get started with TensorFlow Lite

Tensorflow Datasets Reshape Images

I want to build a data pipeline using tensorflow dataset. Because each data has different shapes, I can't build a data pipeline.
import tensorflow_datasets as tfds
import tensorflow as tf
dataset_builder = tfds.builder("oxford_flowers102")
dataset_builder.download_and_prepare()
train_data = dataset_builder.as_dataset(split=tfds.Split.TRAIN)
train_data = train_data.repeat().batch(32)
train_data = train_data.prefetch(tf.data.experimental.AUTOTUNE)
train_iterator = train_data.make_one_shot_iterator()
train_next_element = train_iterator.get_next()
with tf.Session() as sess:
train_batch = sess.run(train_next_element)
Above code gives me the error:
"tensorflow.python.framework.errors_impl.InvalidArgumentError: Cannot batch tensors with different shapes in component 1. First element had shape [500,666,3] and element 1 had shape [752,500,3]."
I want all images to be in the shape of [224,224,3]. How can I reshape images in the existing tensorflow dataset?
You can dynamically resize the images like:
train_data = train_data.map(lambda image: tf.image.resize_image_with_crop_or_pad(image, 224, 224))
right before doing train_data = train_data.repeat().batch(32). Also, using the tf.data.Dataset.map(...) method you can apply a variety of transformations on your images before batching them.

RuntimeError: size mismatch, m1: [28 x 28], m2: [784 x 128]

After training my model, I tried to plot graph of the softmax output, but it resulted in the runtime error mentioned in the title.
Here is the following code snippet:
%matplotlib inline
%config InlineBackend.figure_format = 'retina'
import helper
# Test out your network!
dataiter = iter(testloader)
images, labels = dataiter.next()
img = images[1]
# TODO: Calculate the class probabilities (softmax) for img
ps = torch.exp(model(img))
# Plot the image and probabilities
helper.view_classify(img, ps, version='Fashion')
The problem is with this part (I guess).
img = images[1]
# TODO: Calculate the class probabilities (softmax) for img
ps = torch.exp(model(img))
Problem: image you are loading is of dimension 28x28, however, the first index in input to the model is generally batch size. Since there is 1 image only, so you have to make the first dimension to be of size 1. To do that do img = img.view( (-1,) + img.shape) or img=img.unsqueeze(dim=0). Also, it seems that the first layer weight is 784 x 128. i.e the image should be converted to vector and fed to model. For that we do img=img.view(1, -1).
So, in total, you need to do
img = images[1]
img = img.unsqueeze(dim=0)
img=img.view(1, -1)
# TODO: Calculate the class probabilities (softmax) for img
ps = torch.exp(model(img))
or you can just use one command instead of two (unsqueeze is unnecessary)
img = images[1]
img=img.view(1, -1)

Display extracted feature vector from trained layer of the model as an image

I am using Transfer learning for recognizing objects. I used trained VGG16 model as the base model and added my classifier on top of it using Keras. I then trained the model on my data, the model works well. I want to see the feature generated by the intermediate layers of the model for the given data. I used the following code for this purpose:
def ModeloutputAtthisLayer(model, layernme, imgnme, width, height):
layer_name = layernme
intermediate_layer_model = Model(inputs=model.input,
outputs=model.get_layer(layer_name).output)
img = image.load_img(imgnme, target_size=(width, height))
imageArray = image.img_to_array(img)
image_batch = np.expand_dims(imageArray, axis=0)
processed_image = preprocess_input(image_batch.copy())
intermediate_output = intermediate_layer_model.predict(processed_image)
print("outshape of ", layernme, "is ", intermediate_output.shape)
In the code, I used np.expand_dims to add one extra dimension for the batch as the input matrix to the network should be of the form (batchsize, height, width, channels). This code works fine. The shape of the feature vector is 1, 224, 224, 64.
Now I wish to display this as image, for this I understand there is an additional dimension added as batch so I should remove it. Following this I used the following lines of the code:
imge = np.squeeze(intermediate_output, axis=0)
plt.imshow(imge)
However it throws an error:
"Invalid dimensions for image data"
I wonder how can I display the extracted feature vector as an image. Any suggestion please.
Your feature shape is (1,224,224,64), you cannot directly plot a 64 channel image. What you can do is plot the individual channels independently like following
imge = np.squeeze(intermediate_output, axis=0)
filters = imge.shape[2]
plt.figure(1, figsize=(32, 32)) # plot image of size (32x32)
n_columns = 8
n_rows = math.ceil(filters / n_columns) + 1
for i in range(filters):
plt.subplot(n_rows, n_columns, i+1)
plt.title('Filter ' + str(i))
plt.imshow(imge[:,:,i], interpolation="nearest", cmap="gray")
This will plot 64 images in 8 rows and 8 columns.
A possible way to go consists in combining the 64 channels into a single-channel image through a weighted sum like this:
weighted_imge = np.sum(imge*weights, axis=-1)
where weights is an array with 64 weighting coefficients.
If you wish to give all the channels the same weight you could simply compute the average:
weighted_imge = np.mean(imge, axis=-1)
Demo
import numpy as np
import matplotlib.pyplot as plt
intermediate_output = np.random.randint(size=(1, 224, 224, 64),
low=0, high=2**8, dtype=np.uint8)
imge = np.squeeze(intermediate_output, axis=0)
weights = np.random.random(size=(imge.shape[-1],))
weighted_imge = np.sum(imge*weights, axis=-1)
plt.imshow(weighted_imge)
plt.colorbar()
In [33]: intermediate_output.shape
Out[33]: (1, 224, 224, 64)
In [34]: imge.shape
Out[34]: (224, 224, 64)
In [35]: weights.shape
Out[35]: (64,)
In [36]: weighted_imge.shape
Out[36]: (224, 224)

Categories

Resources