How to use TensorFlow lite on a raspberry pi 4 without keras? - tensorflow

Basically I want to convert this code snippet to code that opens a tflite model and does not use keras. I can not install keras on my raspberry pi 4 as it needs Tensorflow 2+.
model = keras.models.load_model( saved_model_path )
image_url = tf.keras.utils.get_file('Court', origin='https://squashvideo.site/share/court3.jpg' )
img = tf.keras.preprocessing.image.load_img(image_url, target_size=( 224, 224 ) )
os.remove(image_url) # Remove the cached file
img_array = tf.keras.preprocessing.image.img_to_array(img)
prediction_scores = model.predict(np.expand_dims(img_array, axis=0)/255)
score = tf.nn.softmax(prediction_scores[0])
print(
"This image most likely belongs to {} with a {:.2f} percent confidence."
.format(class_names[np.argmax(score)], 100 * np.max(score))
)
Here's what I have tried which gives the error below:
from PIL import Image
def classify_image(interpreter, image, top_k=1):
tensor_index = interpreter.get_input_details()[0]['index']
input_tensor = interpreter.tensor(tensor_index)()[0]
input_tensor[:, :] = image
interpreter.invoke()
output_details = interpreter.get_output_details()[0]
output = np.squeeze(interpreter.get_tensor(output_details['index']))
scale, zero_point = output_details['quantization']
output = scale * (output - zero_point)
ordered = np.argpartition(-output, top_k)
return [(i, output[i]) for i in ordered[:top_k]][0]
interpreter = Interpreter('/var/www/html/share/AI/court.tflite')
interpreter.allocate_tensors()
_, height, width, _ = interpreter.get_input_details()[0]['shape']
print("Image Shape (", width, ",", height, ")")
data_folder = "/var/www/html/share/"
image = Image.open(data_folder + "court1.jpg").convert('RGB').resize((width, height))
label_id, prob = classify_image(interpreter, image)
Running gives the error:
squash#court1:/var/www/html/share/AI $ python3 test.py
Image Shape ( 224 , 224 )
Traceback (most recent call last):
File "test.py", line 44, in <module>
label_id, prob = classify_image(interpreter, image)
File "test.py", line 22, in classify_image
interpreter.invoke()
File "/home/squash/.local/lib/python3.7/site-packages/tflite_runtime/interpreter.py", line 539, in invoke
self._ensure_safe()
File "/home/squash/.local/lib/python3.7/site-packages/tflite_runtime/interpreter.py", line 287, in _ensure_safe
data access.""")
RuntimeError: There is at least 1 reference to internal data
in the interpreter in the form of a numpy array or slice. Be sure to
only hold the function returned from tensor() if you are using raw
data access.

The error is in the way you are feeding data to the tflite Interpreter here:
input_tensor = interpreter.tensor(tensor_index)()[0]
input_tensor[:, :] = image
The Image.open function return an Image object. You need to convert it into binary data before feeding it to a tensor. An you should use:
interpreter.set_tensor(0, image_data)
to set the data instead of above assignment.

Think I fixed it by doing this:
img = Image.open( image_url ).convert('RGB').resize((224, 224))
img_array = np.array ( img, dtype=np.float32 )
probs_lite = lite_model( np.expand_dims(img_array, axis=0)/255 )[0]
print ( probs_lite )
print (np.argmax(probs_lite))
score = tf.nn.softmax(probs_lite)
print(
"This image most likely belongs to {} with a {:.2f} percent confidence."
.format(class_names[np.argmax(score)], 100 * np.max(score))
)

Related

TF Dataset with CSV file where image is stored in another directory

I'm trying to create an input dataset into my TF model using a CSV dataset that I have. The dataset has the following scheme:
image_name, label
XXXXXXX.png, some_integer_value
XXXXXXX.png, some_integer_value
I did a bit of research and found that the tf.data.Dataset API seems to be optimized for this task. I am trying to use tf.data.experimental.make_csv_dataset in order to do this task. My issue that I'm facing is that I'm not sure how to load in the images into my dataset. I currently have the following setup:
csv_dataset = tf.data.experimental.make_csv_dataset(
PATH_TO_DATA_CSV,
batch_size = 5,
select_columns = ['image_name', 'label'],
label_name = 'label',
num_epochs = 1,
ignore_errors = True
)
My original idea was to use a map on the dataset in order to read the file, doing something like
def process_data(image_name, label):
image_name = image_name.numpy().decode('utf-8')
img = tf.io.read_file(DATA_PATH + '/' + image_name)
img = decode_img(img)
return img, label
csv_dataset = csv_dataset.map(process_data)
But this seems to be throwing the error
`File "", line 4, in process_data *
image_name = image_name.numpy().decode('utf-8')
AttributeError: 'collections.OrderedDict' object has no attribute 'numpy'`
Should I be approaching the problem this way (and if so, how can I fix my error)? If not, what is the most optimal way to approach this.
Can use
tf.data.Dataset.from_tensor_slices in conjunction with Pandas (for all_image_paths and all_image_labels) for something like
def load_and_preprocess_image(path):
image_string = tf.compat.as_str_any(path)
image_string = tf.io.read_file(path)
img = tf.io.decode_png(image_string, channels=3)
return tf.image.resize(img, [1000, 1000])
def load_and_preprocess_from_path_labels(path, label):
return load_and_preprocess_image(path), label
ds = tf.data.Dataset.from_tensor_slices((all_image_paths, all_image_labels))
csv_dataset = ds.map(load_and_preprocess_from_path_labels, num_parallel_calls=tf.data.AUTOTUNE)

Tensorflow Lite gives me 0% accuracy for any image

Here is my Colab notebook which anyone should be able to run in 5 seconds. The predictions are always 0. I suspect the problem is in these two lines. Or perhaps my tflite model is corrupt or wrong?
label_id, prob = classify_image(interpreter, np.expand_dims(img_array, axis=0)/255 )
#label_id, prob = classify_image(interpreter, img )
Think I figured it out. Basically the output from the classify_image() function needs furthur processing to be useable. So I need to do this on the output:
label_index= np.argmax(probs_lite)
score = tf.nn.softmax(probs_lite)
print(
"This image most likely belongs to {} with a {:.2f} percent confidence."
.format(class_names[label_index], 100 * np.max(score))
)
And here's my full script in case anyone has similiar issue in the future:
import itertools, time, os, numpy as np,sys
from PIL import Image
import tensorflow as tf
def lite_model(images):
interpreter.allocate_tensors()
interpreter.set_tensor(interpreter.get_input_details()[0]['index'], images)
interpreter.invoke()
return interpreter.get_tensor(interpreter.get_output_details()[0]['index'])
class_names = ['empty_court', 'occupied_court' ]
path_to_tflite = tf.keras.utils.get_file(
"court.tflite",
"https://mysite.site/AI/court.tflite",
untar=False)
interpreter = tf.lite.Interpreter( path_to_tflite )
interpreter.allocate_tensors()
_, height, width, _ = interpreter.get_input_details()[0]['shape']
print("Image Shape (", width, ",", height, ")")
image_url = tf.keras.utils.get_file('Court', origin='https://mysite.site/share/court4.jpg' )
img = tf.keras.preprocessing.image.load_img(image_url, target_size=( width, height ) )
os.remove(image_url) # Remove the cached file
img_array = tf.keras.preprocessing.image.img_to_array(img)
probs_lite = lite_model( np.expand_dims(img_array, axis=0)/255 )[0]
print ( probs_lite )
label_index= np.argmax(probs_lite)
score = tf.nn.softmax(probs_lite)
print(
"This image most likely belongs to {} with a {:.2f} percent confidence."
.format(class_names[label_index], 100 * np.max(score))
)

How to feed tensorflow an image from a url?

The five lines commented out below should work but do not . The prediction score is not anywhere close to what I would expect and when I do plt.imshow(img) it shows the wrong image. Here is the link to my notebook in Colab.
x, y = next(valid_generator)
image = x[0, :, :, :]
true_index = np.argmax(y[0])
plt.imshow(image)
image_url = 'https://mysite_example/share/court3.jpg'
image_url = tf.keras.utils.get_file('Court', origin=image_url )
#img = keras.preprocessing.image.load_img( image_url, target_size=( 224, 224 ) )
#img_array = keras.preprocessing.image.img_to_array(img)
#img_array = tf.expand_dims(img_array, 0)
#prediction_scores = model.predict(np.expand_dims(img_array, axis=0))
#plt.imshow(img)
# Expand the validation image to (1, 224, 224, 3) before predicting the label
prediction_scores = model.predict(np.expand_dims(image, axis=0))
predicted_index = np.argmax(prediction_scores)
print("True label: " + get_class_string_from_index(true_index))
print("Predicted label: " + get_class_string_from_index(predicted_index)
The method tf.keras.utils.get_file downloads the file from url to local cache only if the file is not already cached. So if you are using the same cache name for all the urls ("Court" in your code ?) the you will see only the first file.
Also while training you have a preprocess step of normalizing all the pixels by dividing them with 255. You have to apply the same preprocessing step during inference also.
Working Code:
_, axis = plt.subplots(1,3)
for i, image_url in enumerate(['https://squashvideo.site/share/court3.jpg',
'https://i.pinimg.com/originals/0f/c2/9b/0fc29b35532f8e2fb998f5605212ab27.jpg',
'https://thumbs.dreamstime.com/b/squash-court-photo-empty-30346175.jpg']):
image_url = tf.keras.utils.get_file('Court', origin=image_url )
img = tf.keras.preprocessing.image.load_img(image_url, target_size=( 224, 224 ) )
os.remove(image_url) # Remove the cached file
axis[i].imshow(img)
img_array = keras.preprocessing.image.img_to_array(img)
prediction_scores = model.predict(np.expand_dims(img_array, axis=0)/255)
axis[i].title.set_text(np.argmax(prediction_scores, axis=1))
Output:
As you can see, the predictions are perfect, the last image belong to class 0 (empty squash court) and the second image belong to class 1 (players playing in squash court)

Error while converting fasttext model to tensorflow-hub

I am trying to convert facebooks' fast-text model to tensorflow-hub format. I have attached two main files for the purpose.
def _compute_ngrams(word, min_n=1, max_n=3):
BOW, EOW = ('<', '>') # Used by FastText to attach to all words as prefix and suffix
ngrams = [] # batch_size, n_words, maxlen
shape = word.shape # batch_size, n_sentenes, n_words
maxlen = 0
for b in range(shape[0]): # batch
ngram_b = []
for w in word[b]:
ngram = []
extended_word = BOW + "".join( chr(x) for x in bytearray(w)) + EOW
if w.decode("utf-8") not in global_vocab:
for ngram_length in range(min_n, min(len(extended_word), max_n) + 1):
for i in range(0, len(extended_word) - ngram_length + 1):
ngram.append(extended_word[i:i + ngram_length])
else:
ngram.append(w.decode("utf-8") )
ngram_b.append(ngram)
maxlen = max(maxlen, len(ngram))
ngrams.append(ngram_b)
for batches in ngrams:
for words in batches:
temp = maxlen
r = []
while temp > len(words):
r.append("UNK")
temp = temp - 1
words.extend(r)
return ngrams
def make_module_spec(vocabulary_file, vocab_size, embeddings_dim=300,
num_oov_buckets=1):
def module_fn():
"""Spec function for a token embedding module."""
words = tf.placeholder(shape=[None, None], dtype=tf.string, name="tokens")
tokens = tf.py_func(_compute_ngrams, [words], tf.string)
embeddings_var = tf.get_variable(
initializer=tf.zeros([vocab_size + num_oov_buckets, embeddings_dim]),
name=EMBEDDINGS_VAR_NAME,
dtype=tf.float32
)
lookup_table = tf.contrib.lookup.index_table_from_file(
vocabulary_file=vocabulary_file,
num_oov_buckets=num_oov_buckets,
)
ids = lookup_table.lookup(tokens)
#combined_embedding = tf.reduce_mean(tf.nn.embedding_lookup(params=embeddings_var, ids=ids), axis=2)
combined_embedding = tf.nn.embedding_lookup(params=embeddings_var, ids=ids)
hub.add_signature("default", {"tokens": words},
{"default": combined_embedding})
return hub.create_module_spec(module_fn)
The model is created as expected with tf-hub format.
But when I try to use the above created model, I get this error.
The sample testing code to use tf-hub model created above is attached below.
with tf.Graph().as_default():
module_url = "/home/sahil_wadhwa/tf-hub/tf_sent"
embed = hub.Module(module_url)
embeddings = embed([["Indian", "American"], ["Hello", "World"]])
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
sess.run(tf.tables_initializer())
result = sess.run(embeddings)
print(result)
print(result.shape)
The error I get is here.
Traceback (most recent call last):
File "/home/sahil_wadhwa/.local/lib/python3.6/site-packages/tensorflow/python/ops/script_ops.py", line 195, in __call__
raise ValueError("callback %s is not found" % token)
ValueError: callback pyfunc_0 is not found
[[{{node module_apply_default/PyFunc}} = PyFunc[Tin=[DT_STRING], Tout=[DT_STRING], token="pyfunc_0", _device="/job:localhost/replica:0/task:0/device:CPU:0"](Const)]]
Been stuck with this for a long time, any help here would be useful.
Thanks in advance.
Answered on https://github.com/tensorflow/hub/issues/222:
Hi Sahil,
the issue here is that tf.py_func cannot be serialized. Serializing
arbitrary Python functions is not supported (for multiple reasons).
I see you are creating ngrams from a token if not present in the vocabulary
(btw, are the ngrams actually in the FastText vocabulary to be looked up or
does it contain only full words?).
One way of solving this could be to rewrite your _compute_ngrams function
in TensorFlow (maybe you could use this directly or at least get some
inspiration:
https://www.tensorflow.org/tfx/transform/api_docs/python/tft/ngrams).

How to prepare my own data for tensorflow?

I install Tensorflow on ubuntu 14.04. I completed MNIST For ML Beginners tutorial. I understood it.
Nor, I try to use my own data. I have train datas as T[1000][10]. Labels are L[2], 1 or 0.
How can I access my data mnist.train.images ?
In input_data.py, these two functions do the main job.
1. Download
def maybe_download(filename, work_directory):
"""Download the data from Yann's website, unless it's already here."""
if not os.path.exists(work_directory):
os.mkdir(work_directory)
filepath = os.path.join(work_directory, filename)
if not os.path.exists(filepath):
filepath, _ = urlretrieve(SOURCE_URL + filename, filepath)
statinfo = os.stat(filepath)
print('Succesfully downloaded', filename, statinfo.st_size, 'bytes.')
return filepath
2 Image to nparray
def extract_images(filename):
"""Extract the images into a 4D uint8 numpy array [index, y, x, depth]."""
print('Extracting', filename)
with gzip.open(filename) as bytestream:
magic = _read32(bytestream)
if magic != 2051:
raise ValueError(
'Invalid magic number %d in MNIST image file: %s' %
(magic, filename))
num_images = _read32(bytestream)
rows = _read32(bytestream)
cols = _read32(bytestream)
buf = bytestream.read(rows * cols * num_images)
data = numpy.frombuffer(buf, dtype=numpy.uint8)
data = data.reshape(num_images, rows, cols, 1)
return data
Based on your dataset and location, you can call:
local_file = maybe_download(TRAIN_IMAGES, train_dir)
train_images = extract_images(local_file)
See the full source code at https://github.com/nlintz/TensorFlow-Tutorials/blob/master/input_data.py.