how to pad a set of numpy feature files to same shape? - numpy

I have a set of feature files in numpy format in a folder and would like to vstack them so i can add input_shape in my neural network, input_shape=(21,2048) . The numpy files as as in picture;
The size of the np files are different, example: (16, 2048)
, (8, 2048)
, (5, 2048)
. The maximum size is (21, 2048). I would like to pad them with zero to get size 21 and vstack them. How can i do this?
i tried:
#create a function and iterate files in folder
max_pad_len = 21
def padding(file):
pad_features = np.pad(file_name, pad_width=([(max_pad_len - file_name.shape[0]),0],[0,0]), mode='constant', constant_values=0)
return pad_features
visual_path = ("C:/Users/Data/9. Visual Feature/Input/")
visual_all = []
for file in os.listdir(visual_path):
if file.endswith('.npy'):
file_name = np.load(open(visual_path+file,"rb"))
data = padding(file_name)
visual_all.append(data)
vid_ft = np.vstack(visual_all)
vid_ft.shape
(23016, 2048)
it should be (6,21,2048). Where did it wrong?

Related

Load numpy array to a Tensorflow dataset

I am trying to do image colorization. I have 5000 images (256x256x3) and would like not to load all data in my program (for memory reason). I have found that it is possible to use ImageDataGenerator.flow_from_directory() but I use LAB images and I would like to feed my model with a numpy array of the L component (256, 256, 1). My targets are A and B components (256, 256, 2). To have my image I then merge the input and output to have a LAB image (256, 256, 3). The problem i that ImageDataGenerator.flow_from_directory() only works with image type files (so a 256x256x3 image) and I would like to know if there is a way to do the same thing with numpy arrays.
I tried using tf.data.Dataset.list_files(), I had all my files but I did not found how to load my numpy array to feed my model. I guess I need to use some sort of generator but I do not really understand how to use it. This is what I have for now :
HEIGHT = 256
WIDTH = HEIGHT
Batch_size = 50
dir_X_train = 'data/X_train_np/train_black_resized/*.npy'
dir_X_test = 'data/X_test/test_black_resized/*.npy'
dir_y_train = 'data/y_train_np/train_color_resized/*.npy'
dir_y_test = 'data/y_test/test_color_resized/*.npy'
X_train_dataset = tf.data.Dataset.list_files(dir_X_train, shuffle=False).batch(Batch_size)
y_train_dataset = tf.data.Dataset.list_files(dir_y_train, shuffle=False).batch(Batch_size)
def process_path(file_path):
return tf.io.read_file(file_path[0])
X_train_dataset = X_train_dataset.map(process_path)
y_train_dataset = y_train_dataset.map(process_path)
train_dataset = tf.data.Dataset.zip((X_train_dataset, y_train_dataset))
for image_black, image_color in train_dataset.take(1):
print(image_black.numpy()[:100])
print(type(image_black))
print(image_color.numpy()[:100])
print(type(image_color))
Output :
b"\x93NUMPY\x01\x00v\x00{'descr': '<f4', 'fortran_order': False, 'shape': (256, 256), } "
<class 'tensorflow.python.framework.ops.EagerTensor'>
b"\x93NUMPY\x01\x00v\x00{'descr': '<f4', 'fortran_order': False, 'shape': (256, 256, 2), } "
<class 'tensorflow.python.framework.ops.EagerTensor'>
The shape seems to be correct but I don't know how to have the numpy.array

Chunk tensorflow dataset records into multiple records

I have an unbatched tensorflow dataset that looks like this:
ds = ...
for record in ds.take(3):
print('data shape={}'.format(record['data'].shape))
-> data shape=(512, 512, 87)
-> data shape=(512, 512, 277)
-> data shape=(512, 512, 133)
I want to feed the data to my network in chunks of depth 5. In the example above, the tensor of shape (512, 512, 87) would be divided into 17 tensors of shape (512, 512, 5). The final 2 rows of the matrix (tensor[:,:, 85:87]) should be discarded.
For example:
chunked_ds = ...
for record in chunked_ds.take(1):
print('chunked data shape={}'.format(record['data'].shape))
-> chunked data shape=(512, 512, 5)
How can I get from ds to chunked_ds? tf.data.Dataset.window() looks like what I need but I cannot get this working.
This can be actually done using tf.data.Dataset-only operations:
data = tf.random.normal( shape=[ 10 , 512 , 512 , 87 ] )
ds = tf.data.Dataset.from_tensor_slices( ( data ) )
chunk_size = 5
chunked_ds = ds.flat_map(lambda x: tf.data.Dataset.from_tensor_slices(tf.transpose(x, perm=[2, 0, 1])).batch(chunk_size, drop_remainder=True)) \
.map(lambda rec: tf.transpose(rec, perm=[1, 2, 0]))
What is going on there:
First, we treat each each record as a separate Dataset and we permute it so that the last dimension becomes the batch dimension (flat_map will flatten our internal datasets to Tensors again)
.flat_map(lambda x: tf.data.Dataset.from_tensor_slices(tf.transpose(x, perm=[2, 0, 1])
Then we batch it by 5, but we do not care about remainder
.batch(chunk_size, drop_remainder=True))
Finally, re-permute tensors so that we have 512x512 at the beggining:
.map(lambda rec: tf.transpose(rec, perm=[1, 2, 0]))
In order to express my solution, I'll first create a dummy dataset, which 10 samples each of shape [ 512 , 512 , 87 ],
data = tf.random.normal( shape=[ 10 , 512 , 512 , 87 ] )
ds = tf.data.Dataset.from_tensor_slices( ( data ) )
On executing the below code,
for record in ds.take( 3 ):
print( record.shape )
We get the output,
(512, 512, 87)
(512, 512, 87)
(512, 512, 87)
For convenience, I have created a dataset in which the length of the last dimension is a constant i.e. 87 ( which contradicts your approach ). But the solution provided is independent of the length of the last dimension.
The solution,
# chunk/window size
chunk_depth = 5
# array to store the chunks
chunks = []
# Iterating through each sample in ds ( Note: ds.as_numpy_iterator() returns NumPy arrays )
for sample in ds.as_numpy_iterator():
# Length of the last dimension
feature_size = sample.shape[ 2 ]
# No. of chunks that can be produced
num_chunks = feature_size // chunk_depth
# Perform slicing along the last dimension, storing the "chunks" in the chunks array.
for i in range( 0 , num_chunks , chunk_depth ):
chunk = sample[ : , : , i : i + chunk_depth ]
chunks.append( chunk )
# Convert array -> tf.data.Dataset
chunked_ds = tf.data.Dataset.from_tensor_slices( ( chunks ) )
The output of the below code,
for sample in chunked_ds.take( 1 ):
print( sample.shape )
is as expected in the question,
(512, 512, 5)
The solution is available as a Colab notebook.

Converting DICOM image to numpy array of shape (s, 3, 256, 256)

I've got folders with MRI images in them and I'm trying to replicate the MRnet study with my own data. Their model works on 1 .npy file per subject, shape (s, 3, 256, 256), with s being number of slices for a given subject (varies between subjects).
I've looked at several different methods of solving this but none seems to work for me. Closest I have gotten was to at least convert the .dcm files to JPEG using:
import pydicom
import os
import numpy as np
import cv2
dicom_folder = 'C:/Users/GlaDOS/PythonProjects/dicomnpy/DICOMFILES/sub1/' # Set the folder of your dicom files that inclued images
jpg_folder = 'C:/Users/GlaDOS/PythonProjects/dicomnpy/DICOMFILES/jpg' # Set the folder of your output folder for jpg files
# Step 1. prepare your input(.dcm) and output(.jpg) filepath
dcm_jpg_map = {}
for dicom_f in os.listdir(dicom_folder):
dicom_filepath = os.path.join(dicom_folder, dicom_f)
jpg_f = dicom_f.replace('.dcm', '.jpg')
jpg_filepath = os.path.join(jpg_folder,jpg_f)
dcm_jpg_map[dicom_filepath] = jpg_filepath
# Now, dcm_jpg_map is key,value pair of input dcm filepath and output jpg filepath
# Step 2. process your image by input/output information
for dicom_filepath, jpg_filepath in dcm_jpg_map.items():
# convert dicom file into jpg file
dicom = pydicom.read_file(dicom_filepath)
np_pixel_array = dicom.pixel_array
cv2.imwrite(jpg_filepath, np_pixel_array)
I know that I can use pydicom to do this, but I can't find any information in their documentation on how to achieve this result.
I essentially want the information in np_pixel_array of the above code, which returns a shape of 256, 216, however I want every dcm file in the folder in that array so it would become (30, 256, 216) or however many slices each folder has.
Does anyone have experience with this and may be able to help?
you could modify this section of your code:
for dicom_filepath, jpg_filepath in dcm_jpg_map.items():
# convert dicom file into jpg file
dicom = pydicom.read_file(dicom_filepath)
np_pixel_array = dicom.pixel_array
cv2.imwrite(jpg_filepath, np_pixel_array)
to this:
unstacked_list = []
for dicom_filepath, jpg_filepath in dcm_jpg_map.items():
# convert dicom file into jpg file
dicom = pydicom.read_file(dicom_filepath)
np_pixel_array = dicom.pixel_array
unstacked_list.append(np_pixel_array)
cv2.imwrite(jpg_filepath, np_pixel_array)
final_array = np.array(unstacked_list)
an example of how this works is below with a simpler scenario, imagine arrays a, b and c are the np_pixel_array arrays and final_array is the format you wanted
import numpy as np
unstacked_list = []
a = np.array([[1,2], [3,4]])
b = np.array([[5,6], [7,8]])
c = np.array([[9,10], [11,12]])
for i in [a, b, c]:
unstacked_list.append(i)
final_array = np.array(unstacked_list)
print(final_array.shape)
print(f'shape of final_array is {shape}')
print('')
print(f'final array is{final_array}')
output is
shape of final_array is (3, 2, 2)
final array is
[[[ 1 2]
[ 3 4]]
[[ 5 6]
[ 7 8]]
[[ 9 10]
[11 12]]]

Read Image and Mask (for segmentation problem) in Tensorflow-2.0 using tf.data

I am trying to read the image dataset for the segmentation problem (1-class) by following this link. My main folder contains two folders i.e. (a) img (b) mask. img contains image samples and mask contains corresponding masks. My approach was, generate the path for image and then change the string path (i.e. img->mask). I modified the code provided here which now looks as:
def process_path(file_path):
file_path_str = str(file_path)
file_path_mask = file_path_str.replace('img', 'mask')
# load the raw data from the file as a string
img = tf.io.read_file(file_path)
img = decode_img(img)
mask = tf.io.read_file(str(file_path_mask))
mask = decode_mask(mask)
return img, mask
However, when I am trying to see the size of my samples using:
for image, mask in labeled_ds.take(1):
print("Image shape: ", image.numpy().shape)
print("Mask shape: ", mask.numpy().shape)
I am getting the following error:
InvalidArgumentError: NewRandomAccessFile failed to Create/Open: Tensor("arg0:0", shape=(), dtype=string) : The filename, directory name, or volume label syntax is incorrect.
; Unknown error
[[{{node ReadFile_1}}]] [Op:IteratorGetNextSync]
Question: Any suggestion on how to read image and mask both from a given folder without above error?
We can use tf.regex.replace to rename string. So, in place of python string replacement, use:file_path_mask = tf.regex_replace(file_path, "img", "mask"). For TF 2.0, use tf.strings.regex_replace.
Alternative workaround for a similar problem. I have 200 (nb_of_images = 200) grayscale images of shape (512, 512) loaded as np.array and 200 binary masks also of shape (512, 512) and loaded as np.array. Within a for loop, I take all the images, convert them to EagerTensor (with tf.convert_to_tensor), cast them to tf.float32 through the dtype arg, add one dimension with:
img = img[:, :, tf.newaxis]
so that my images are now EagerTensors of shape (512, 512, 1), and finally I append them to an external list called images.
Within the same loop, I do the exact same operations for the masks and in the end I append them to an external list called masks.
Once the for loop is finished, I basically have two lists of EagerTensors, with
len(images) == len(masks) == nb_of_images
Lastly, I re-convert the two lists to tf.Tensor with:
images_tf = tf.convert_to_tensor(images) # convert list back to tf.Tensor
masks_tf = tf.convert_to_tensor(masks) # convert list back to tf.Tensor
and finally I create the tf.data.Dataset with:
dataset = tf.data.Dataset.from_tensor_slices((images_tf, masks_tf)) # create tf.data.Dataset

Can we visualize the embedding with multiple sprite images in tensorflow?

What I mean is, can I, for example, construct 2 different sprite images and be able to choose one of them while viewing embeddings in 2D/3D space using TSNE/PCA?
In other words, when using the following code:
embedding.sprite.image_path = "Path/to/the/sprite_image.jpg"
Is there a way to add another sprite image?
So, when training a Conv Net to distinguish between MNIST digits, I not only need to view the 1,2,..9, and 0 in the 3D/2D space, instead, I would like to see where are the ones gathering in that space. Same for 2s, 3s and so on. so I need a unique color for the 1s, another one for the 2s and so on... I need to view this as in the following image:
source
Any help is much appreciated!
There is an easier way to do this with filtering. You can just select the labels with a regex syntax:
If this is not what you are looking for, you could create a sprite image that assigns the same plain color image to each of your labels!
This functionality should come out of the box (without additional sprite images). See 'colour by' in the left sidepanel. You can toggle the A to switch sprite images on and off.
This run was produced with the example on the front page of the tensorboardX projector GitHub repo. https://github.com/lanpa/tensorboardX
You can also see a live demo with MNIST dataset (images and colours) at http://projector.tensorflow.org/
import torchvision.utils as vutils
import numpy as np
import torchvision.models as models
from torchvision import datasets
from tensorboardX import SummaryWriter
resnet18 = models.resnet18(False)
writer = SummaryWriter()
sample_rate = 44100
freqs = [262, 294, 330, 349, 392, 440, 440, 440, 440, 440, 440]
for n_iter in range(100):
dummy_s1 = torch.rand(1)
dummy_s2 = torch.rand(1)
# data grouping by `slash`
writer.add_scalar('data/scalar1', dummy_s1[0], n_iter)
writer.add_scalar('data/scalar2', dummy_s2[0], n_iter)
writer.add_scalars('data/scalar_group', {'xsinx': n_iter * np.sin(n_iter),
'xcosx': n_iter * np.cos(n_iter),
'arctanx': np.arctan(n_iter)}, n_iter)
dummy_img = torch.rand(32, 3, 64, 64) # output from network
if n_iter % 10 == 0:
x = vutils.make_grid(dummy_img, normalize=True, scale_each=True)
writer.add_image('Image', x, n_iter)
dummy_audio = torch.zeros(sample_rate * 2)
for i in range(x.size(0)):
# amplitude of sound should in [-1, 1]
dummy_audio[i] = np.cos(freqs[n_iter // 10] * np.pi * float(i) / float(sample_rate))
writer.add_audio('myAudio', dummy_audio, n_iter, sample_rate=sample_rate)
writer.add_text('Text', 'text logged at step:' + str(n_iter), n_iter)
for name, param in resnet18.named_parameters():
writer.add_histogram(name, param.clone().cpu().data.numpy(), n_iter)
# needs tensorboard 0.4RC or later
writer.add_pr_curve('xoxo', np.random.randint(2, size=100), np.random.rand(100), n_iter)
dataset = datasets.MNIST('mnist', train=False, download=True)
images = dataset.test_data[:100].float()
label = dataset.test_labels[:100]
features = images.view(100, 784)
writer.add_embedding(features, metadata=label, label_img=images.unsqueeze(1))
# export scalar data to JSON for external processing
writer.export_scalars_to_json("./all_scalars.json")
writer.close()
There are some threads mentioning that this currently fails beyond a threshold number of datapoints. https://github.com/lanpa/tensorboardX