About tf.gfile.FastGFile and cv2 mat - tensorflow

This is the code for reading an image from disk:
image_data = tf.gfile.FastGFile(imagePath, 'rb').read()
with tf.Session() as sess:
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor,
{'DecodeJpeg/contents:0': image_data})
But now I want to capture frames from videos using Python and opencv, and then classify captured mat images using this model.
I tried :
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
print(image_data)
imgRGB = cv2.imread(image_path)
r, buf = cv2.imencode(".jpg", imgRGB)
bytes_image = Image.fromarray(np.uint8(buf)).tobytes()
print(bytes_image)
and I got two similar result,but it is not the same.
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00\x00\x00\x00\xff\xe1\x00"Exif\x00\x00MM\x00*\x00\x00\x00........
b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x00\x00\x01\x00\x01\x00\x00\xff\xdb\x00C\x00\x02.......
And when I called "sess.run",I found that the final result is not the same.How can I solve this?

Related

Images and masks visualisation - Colab

Hei everyone.
I have set up an image and mask visual check in Colab using matplotlib, NumPy and Random and it was expected to print the same image number for both (image and mask), but unfortunately, it's not.
For whatever reason, the images don't correspond. Both images have the same size and number/name.
Does anyone have some hints on how to fix this? Thank you in advance!
import random
import numpy as np
image_number = random.randint(0,len(image_dataset))
plt.figure(figsize=(12,6))
plt.subplot(121)
plt.imshow(np.reshape(image_dataset[image_number], (patch_size,patch_size,3)))
plt.subplot(122)
plt.imshow(np.reshape(mask_dataset[image_number], (patch_size,patch_size,3)))
plt.show()
image printed using the code above
This is how I'm importing the training images. (doing the same for masks)
images_dataset = [] #TRAIN IMAGES
for path, subdirs, files in os.walk(root_directory):
dirname = path.split(os.path.sep)[-1]
if dirname =="images":
images = os.listdir(path)
for i, image_name in enumerate(images):
if image_name.endswith('.png'):
image = cv2.imread(path + "/" + image_name, 1)
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
SIZE_X = (image.shape[1]//patch_size)*patch_size
SIZE_Y = (image.shape[0]//patch_size)*patch_size
image = Image.fromarray(image)
image = image.crop((0,0,SIZE_X, SIZE_Y))
image = np.array(image)
try to sort out the data.
images = sorted(os.listdir(path))

Label map provided by landmarks module on Tensorflow Hub does not match model output

I am trying to use landmark models on tensorflow hub provided at https://tfhub.dev/google/on_device_vision/classifier/landmarks_classifier_asia_V1/1
It says that the output is "prediction:logits: A vector of 99543 similarity scores". However, my out put shape is (1, 98960).
The label map file has 99543 lines which is aligned with the instruction, but the output size does not match the map file.
The predict result is far from accurate, claims an image of Oriental Tower as The Israel Museum with 0.76 score.
My input image is preprocessed to be [321, 321, 3], scaled to [0, 1] per instruction.
What could be wrong? Is it the model/labelmap issue or there is something wrong with my attempting?
import tensorflow.compat.v2 as tf
import tensorflow_hub as hub
import pandas as pd
IMAGE_HEIGHT = 321
IMAGE_WIDTH = 321
def load_img(path):
img = tf.io.read_file(path)
img = tf.image.decode_jpeg(img, channels=3)
img = tf.image.resize(img, [IMAGE_HEIGHT, IMAGE_WIDTH])
img = tf.keras.preprocessing.image.img_to_array(img) / 255.0
img = tf.expand_dims(img, 0)
return img
module_handle = "https://tfhub.dev/google/on_device_vision/classifier/landmarks_classifier_asia_V1/1"
detector = hub.KerasLayer(module_handle, output_key='predictions:logits')
image_path = 'xxx'
img = load_img(image_path)
output_tensor = detector(img)
output_tensor.shape
Which gives the result:
(1, 98960)
Thanks in advance!
As of 2021-03-18, the inconsistencies in the labelmaps have been fixed and an update for the model documentation (i.e. that the length of the output vector should actually be 98960 instead of 99543) is on the way. You can already re-download the labelmap files, which are referenced on the model pages on tfhub.dev. Sorry for the inconvenience!

How to convert numpy.ndarray to tfrecord?

I have a large dataset ,The dataset has two feature,first feature is data,the second feature is label,the dataset size is about 6GB,when I run the code as follows:
#data_from_dataset represent data from 4G dataset, data_from_dataset
#type is ndarray,The data_from_dataset shape is two dimension like (a
#very large num,15)
#label_from_dataset represent label from 4G dataset,,label_from_dataset type
#is ndarray also ndarray
#label_from_dataset #shape is two dimension like (a very large num,15)
data_from_dataset, label_from_dataset = load_train_data()
#calc total batch count
num_batch = len(data_from_dataset) // hp.batch_size
# Convert to tensor
X = tf.convert_to_tensor(data_from_dataset, tf.int32)
Y = tf.convert_to_tensor(label_from_dataset, tf.int32)
# Create Queues
input_queues = tf.train.slice_input_producer([X, Y])
# create batch queues
x, y = tf.train.shuffle_batch(input_queues,
num_threads=20,
batch_size=hp.batch_size,
capacity=hp.batch_size*64,
min_after_dequeue=hp.batch_size*32,
allow_smaller_final_batch=False)
it runs very slowly after wating a long time ,the console hints the error as follows:
Error:cannot create a tensor larger than 2GB
it seems problem in these code line:
# Convert to tensor
X = tf.convert_to_tensor(data_from_dataset, tf.int32)
Y = tf.convert_to_tensor(label_from_dataset, tf.int32)
I MODIFY THE CODE CONVERT NUMPY to TFRECORD AS FOLLOWS:
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
def save_tfrecords(data_from_dataset, label_from_dataset, desfile):
with tf.python_io.TFRecordWriter(desfile) as writer:
for i in range(len(data_from_dataset)):
features = tf.train.Features(
feature = {
"data": _int64_feature(data[i]),
"label": _int64_feature(label[i])
}
)
example = tf.train.Example(features = features)
serialized = example.SerializeToString()
writer.write(serialized)
def read_and_decode(filename_queue):
reader = tf.TFRecordReader()
_, serialized_example = reader.read(filename_queue)
features = tf.parse_single_example(
serialized_example,
features={
'data': tf.FixedLenFeature([], tf.string),
'label': tf.FixedLenFeature([], tf.string),
})
sent = features['data']
tag = features['label']
sent_decode=tf.decode_raw(sent,tf.int32)
sent_decode=tf.decode_raw(tag,tf.int32)
return sent, tag
fname_out="out.tfrecord"
save_tfrecords(data_from_dataset, label_from_dataset, fname_out)
filename_queue = tf.train.string_input_producer(fname_out, shuffle=True)
example, label = read_and_decode(filename_queue, 2)
x, y = tf.train.shuffle_batch([example, label],
num_threads=20,
batch_size=hp.batch_size,
capacity=hp.batch_size*64,
min_after_dequeue=hp.batch_size*32,
allow_smaller_final_batch=False)
it hints the error on code line as follows:
def _int64_feature(value):
return tf.train.Feature(int64_list=tf.train.Int64List(value=[value]))
Error:only length-1 arrays can be converted to python scalars
How to convert numpy to tfrecord ?is there any other method?
Function tf.train.Int64List is not for arrays.
You need to use tf.train.BytesList instead
data = np.random.rand(15,)
writer = tf.python_io.TFRecordWriter('file.tfrecords')
str = data.tostring()
example = tf.train.Example(features=tf.train.Features(feature={'1': _bytes_feature(str)}))
writer.write(example.SerializeToString())
writer.close()
You can then decode it with tf.decode_raw of you can inspect tfrecord file with
for str_rec in tf.python_io.tf_record_iterator('file.tfrecords'):
example = tf.train.Example()
example.ParseFromString(str_rec)
str = (example.features.feature['1'].bytes_list.value[0])
your_data = np.fromstring(str, dtype)

How to load pickle files by tensorflow's tf.data API

I have my data in multiple pickle files stored on disk. I want to use tensorflow's tf.data.Dataset to load my data into training pipeline. My code goes:
def _parse_file(path):
image, label = *load pickle file*
return image, label
paths = glob.glob('*.pkl')
print(len(paths))
dataset = tf.data.Dataset.from_tensor_slices(paths)
dataset = dataset.map(_parse_file)
iterator = dataset.make_one_shot_iterator()
Problem is I don't know how to implement the _parse_file fuction. The argument to this function, path, is of tensor type. I tried
def _parse_file(path):
with tf.Session() as s:
p = s.run(path)
image, label = pickle.load(open(p, 'rb'))
return image, label
and got error message:
InvalidArgumentError (see above for traceback): You must feed a value for placeholder tensor 'arg0' with dtype string
[[Node: arg0 = Placeholder[dtype=DT_STRING, shape=<unknown>, _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]
After some search on the Internet I still have no idea how to do it. I will be grateful to anyone providing me a hint.
I have solved this myself. I should use tf.py_func as in this doc.
This is how I solved this issue. I didn't use the tf.py_func; check out function "load_encoding()" below, which is what's doing the pickle reading. The FACELIB_DIR contains directories of pickled vggface2 encodings, each directory named for the person of those face encodings.
import tensorflow as tf
import pickle
import os
FACELIB_DIR='/var/noggin/FaceEncodings'
# Get list of all classes & build a quick int-lookup dictionary
labelNames = sorted([x for x in os.listdir(FACELIB_DIR) if os.path.isdir(os.path.join(FACELIB_DIR,x)) and not x.startswith('.')])
labelStrToInt = dict([(x,i) for i,x in enumerate(labelNames)])
# Function load_encoding - Loads Encoding data from enc2048 file in filepath
# This reads an encoding from disk, and through the file path gets the label oneHot value, returns both
def load_encoding(file_path):
with open(os.path.join(FACELIB_DIR,file_path),'rb') as fin:
A,_ = pickle.loads(fin.read()) # encodings, source_image_name
label_str = tf.strings.split(file_path, os.path.sep)[-2]
return (A, labelStrToInt[label_str])
# Build the dataset of every enc2048 file in our data library
encpaths = []
for D in sorted([x for x in os.listdir(FACELIB_DIR) if os.path.isdir(os.path.join(FACELIB_DIR,x)) and not x.startswith('.')]):
# All the encoding files
encfiles = sorted(filter((lambda x: x.endswith('.enc2048')), os.listdir(os.path.join(FACELIB_DIR, D))))
encpaths += [os.path.join(D,x) for x in encfiles]
dataset = tf.data.Dataset.from_tensor_slices(encpaths)
# Shuffle and speed improvements on the dataset
BATCH_SIZE = 64
from tensorflow.data import AUTOTUNE
dataset = (dataset
.shuffle(1024)
.cache()
.repeat()
.batch(BATCH_SIZE)
.prefetch(AUTOTUNE)
)
# Benchmark our tf.data pipeline
import time
datasetGen = iter(dataset)
NUM_STEPS = 10000
start_time = time.time()
for i in range(0, NUM_STEPS):
X = next(datasetGen)
totalTime = time.time() - start_time
print('==> tf.data generated {} tensors in {:.2f} seconds'.format(BATCH_SIZE * NUM_STEPS, totalTime))
tf.py_func
This function is used to solved that problem and also as menstion in doc.

How to use the Inception v3 model to calculate the feature vector of PNG images in the transfer learning

I'm using transfer learning in TensorFlow.I need to use Inception V3 model to calculate the feature vector of a picture.My code in the calculation of JPG format pictures no problem, but the calculation of the PNG format will be wrong.
# read model
with gfile.FastGFile(os.path.join(MODEL_DIR, MODEL_FILE), 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
bottleneck_tensor, jpeg_data_tensor = tf.import_graph_def(graph_def, return_elements=[BOTTLENECK_TENSOR_NAME, JPEG_DATA_TENSOR_NAME])
......
# get imagepath
image_path = get_image_path(image_lists, INPUT_DATA, index, category)
# read image
image_data = gfile.FastGFile(image_path, 'rb').read()
# calculate the feature vector
# **This statement is wrong when png images**
bottleneck_values = sess.run(bottleneck_tensor, {jpeg_data_tensor: image_data})
Console error includes:
......
Not a JPEG file: starts with 0x89 0x50
......
InvalidArgumentError (see above for traceback): Invalid JPEG data, size 19839
[[Node: import/DecodeJpeg = DecodeJpeg[acceptable_fraction=1, channels=3, dct_method="", fancy_upscaling=true, ratio=1, try_recover_truncated=false, _device="/job:localhost/replica:0/task:0/cpu:0"](_recv_import/DecodeJpeg/contents_0)]]
I guess the wrong key is to read the picture of the code, but I don't know how to modify it to support the PNG format, can someone help me?
Thanks
Can you download some other images and see if they work? The problem is really your image loading I think...
Otherwise, try reading an image with pyplot:
import matplotlib.pyplot as plt
image = plt.imread('image.jpg')
I've found a solution.
Although I can't modify it to support the PNG format, but I can read the PNG image and convert it to JPEG format.
Add code as follows:
import io
......
# get imagepath
image_path = get_image_path(image_lists, INPUT_DATA, index, category)
# read image
data = open(image_path,'rb').read()
ifile = io.BytesIO(data)
im = Image.open(ifile).convert('RGB')
ofile = io.BytesIO()
im.save(ofile, 'JPEG')
image_data = ofile.getvalue()
# calculate the feature vector
bottleneck_values = sess.run(bottleneck_tensor, {jpeg_data_tensor: image_data})
This method does not generate new images in the disk,that's OK!