Adding images as arrays into a larger array using Numpy - python

I'm trying to create an array of images using Numpy to feed it into an image classification neural network. When I put the image into an array, it comes 3 dimensions,but when I use np.append to append it into my array of all of the images the shape is 631800003. Why is this happening and how do I fix this? Or should I be loading the images some other way?
Here is my code for the variable definition cell:
normal = np.array([])
normalSet = np.array([])
badSet = np.array([])
Labels = np.array([])
Training_data = np.array([])
validationSet = []
process_data = True
ramCheck = 0
And the image loading:
if process_data:
for image in os.listdir('train/NORMAL/'):
normal = imread('train/NORMAL/'+image)
normalSet = np.append(normal, normalSet)
Labels = np.append(Labels, 0)
validationSet.append(normal)
for image in os.listdir('train/PNEUMONIA/'):
bad = imread('train/PNEUMONIA/'+image)
badSet = np.append(badSet, bad)
Labels = np.append(Labels, 1)
validationSet.append(bad)
print("done!")
Training_Data = np.append(badSet, normalSet)
np.save("TrainingData.npy", Training_data)
np.save("TrainingLabels.npy", Labels)
else:
Training_data = np.load("TrainingData.npy")
Labels = np.load("TrainingLabels.npy")

You can append into a list easier than change the list to a numpy array which will have the correct dimensions you need to feed it to a neural network.
normalSet = []
labels = []
for image in os.listdir('train/NORMAL/'):
normal = imread('train/NORMAL/'+ image)
normalSet.append(normal)
validationSet.append(normal)
labels.append(0)
normalSet = np.array(normalSet)
labels = np.array(labels)

Related

Creating data batches [images, labels] for data preprocessing pipeline without ML frameworks

Well, I am curious to understand how to generate a function call which could return two arrays(images = [Batch of images in terms of .npy], labels =[ Image labels for a batch of images]), without using generator type or any other ML frameworks(TensorFlow -> flow from directory etc.).
Also, in case the batch size is unevenly dividable by a number of images, I would like the last batch to inherit the remaining set of images from the first batch. Is it possible ?, I am thinking in terms of Stack/ Queue but not sure if that's the required structure here
def next(self):
# Converting JSON to DICTIONARY
with open(label_path, 'r') as label_json:
label_dict = json.load(label_json)
number_of_images = len((os.listdir(file_path))) # Number of images = Length of the directory
images = os.listdir(file_path) # As a list
images_name = [each_image.strip(".npy") for each_image in images]
labels = label_path
number_of_batches = number_of_images / batch_size
# Sort the label dictionary
label_dict = dict(sorted(label_dict.items()))
# Match label and Image
batch_images = []
label_names = []
for i in images_name:
if i in label_dict.keys():
# batch_images.append(file_path + '/' + i + '.npy') #Image Location
img_array = np.load(file_path + '/' + i + '.npy') # Fetching file location
batch_images.append(img_array)
label_names.append(label_dict.get(i)) # Fetching Label name.
return batch_images, label_names

how to build TensorFlow input pipelines for images and their coresponding label

I would like to create an image generator with their labels.
First, import data from csv and then map 43 classes using this code:
label_map = {v:i for i, v in enumerate(classes)}
The output will be something like this:
{'Danger': 4,
'Give Way': 5,
'Hump': 6,
'Left Bend': 7,
'Left Margin': 8,...}
Then will load images from directory using:
train_images = glob('/Desktop/dataset/resized_train/*')
Now I map the labels from csv file using:
train_labels = df['label'].map(label_map)
Now when I want to show each image with its corresponding label I cannot.
I used this code:
img = tf.io.read_file(image_path)
img = tf.image.decode_image(img, channels=3)
img.set_shape([None,None,3])
img = tf.image.resize(img, [image_w, image_h])
img = img/255.0
return img
def load_data(image_path, label):
image = read_img(image_path)
return image, label
def data_generator(features,labels):
dataset = tf.data.Dataset.from_tensor_slices((features,labels))
dataset = dataset.shuffle(buffer_size=100)
autotune = tf.data.experimental.AUTOTUNE
dataset = dataset.map(load_data, num_parallel_calls=autotune)
dataset = dataset.batch(batch_size=batch_size)
dataset = dataset.repeat()
dataset = dataset.prefetch(autotune)
return dataset
def show_img(dataset):
plt.figure(figsize=(15,15))
for i in range(8):
for val in dataset.take(1):
img = val[0][i]*255.0
plt.subplot(4,2,i+1)
plt.imshow(tf.cast(img,tf.uint8))
plt.title(val[1][i].numpy())
plt.subplots_adjust(hspace=1)
plt.show()
train_dataset = data_generator(train_images,train_labels)
val_dataset = data_generator(val_images,val_labels)
show_img(train_dataset)
When I run the show_img it shows images, but the labels are all 0.
Your code seems to be working fine. I thought initially that your code was not working correctly because you were passing train_labels as a pandas series to from_tensor_slices, but that does not seem to be a problem. I can only imagine that the buffer_size in dataset.shuffle is too small. For example, if I set the buffer_size to 1, I get the same samples every time I call dataset.take(1), because according to the docs:
[...] if your dataset contains 10,000 elements but buffer_size is set to 1,000, then shuffle will initially select a random element from only the first 1,000 elements in the buffer [...]
Maybe your first 100 elements have the label 0? Again, it's just a suggestion. I have managed to get your code to retrieve different labels each time by using a large buffer_size:
import pandas as pd
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
classes = ['Danger', 'Give Way', 'Hump']
label_map = {v:i for i, v in enumerate(classes)}
d = {'label': ['Danger', 'Give Way', 'Hump', 'Danger', 'Give Way', 'Hump', 'Danger', 'Give Way', 'Hump'],
'other': [1, 2, 3, 4, 5, 6, 7, 8, 9]}
df = pd.DataFrame(data=d)
train_labels = df['label'].map(label_map)
def load_data(image, label):
image /= 255.0
return image, label
features = tf.random.normal((9, 32, 32, 3))
dataset = tf.data.Dataset.from_tensor_slices((features, train_labels))
dataset = dataset.shuffle(buffer_size=9)
dataset = dataset.map(load_data, num_parallel_calls=tf.data.experimental.AUTOTUNE)
dataset = dataset.batch(batch_size=2)
dataset = dataset.repeat()
dataset = dataset.prefetch(tf.data.experimental.AUTOTUNE)
plt.figure(figsize=(5,5))
for i in range(2):
for val in dataset.take(1):
img = val[0][i]*255.0
plt.subplot(1,2,i+1)
plt.imshow(tf.cast(img,tf.uint8))
plt.title(val[1][i].numpy())
plt.subplots_adjust(hspace=1)
plt.show()

Creating Numpy array or variable length arrays

I want to create a Numpy array or arrays, where each sub array has the shape [128, audio_length, 1], so I can feed this np array into Keras.fit. However I cannot seem to figure out how to do this as np.array just throws cannot broadcast error
def prepare_data(df, config, data_dir, bands=128):
log_specgrams_2048 = []
for i, fname in enumerate(df.index):
file_path = data_dir + fname
data, _ = librosa.core.load(file_path, sr=config.sampling_rate, res_type="kaiser_fast")
melspec = librosa.feature.melspectrogram(data, sr=config.sampling_rate, n_mels=bands)
logspec = librosa.core.power_to_db(melspec) # shape would be [128, your_audio_length]
logspec = logspec[..., np.newaxis] # shape will be [128, your_audio_length, 1]
log_specgrams_2048.append(normalize_data(logspec))
return log_specgrams_2048
You have to group sequences by length and call Keras.fit multiple times.
You can do:
Bucketing
Zero-padding
Batch of size 1

Deep learning Udacity course: Prob 2 assignment 1 (notMNIST)

After reading this and taking the courses, I am struggling to solve the second problem in assignment 1 (notMnist):
Let's verify that the data still looks good. Displaying a sample of the labels and images from the ndarray. Hint: you can use matplotlib.pyplot.
Here is what I tried:
import random
rand_smpl = [ train_datasets[i] for i in sorted(random.sample(xrange(len(train_datasets)), 1)) ]
print(rand_smpl)
filename = rand_smpl[0]
import pickle
loaded_pickle = pickle.load( open( filename, "r" ) )
image_size = 28 # Pixel width and height.
import numpy as np
dataset = np.ndarray(shape=(len(loaded_pickle), image_size, image_size),
dtype=np.float32)
import matplotlib.pyplot as plt
plt.plot(dataset[2])
plt.ylabel('some numbers')
plt.show()
but this is what I get:
which doesn't make much sense. To be honest my code may too, since I am not really sure how to tackle that problem!
The pickles are created like this:
image_size = 28 # Pixel width and height.
pixel_depth = 255.0 # Number of levels per pixel.
def load_letter(folder, min_num_images):
"""Load the data for a single letter label."""
image_files = os.listdir(folder)
dataset = np.ndarray(shape=(len(image_files), image_size, image_size),
dtype=np.float32)
print(folder)
num_images = 0
for image in image_files:
image_file = os.path.join(folder, image)
try:
image_data = (ndimage.imread(image_file).astype(float) -
pixel_depth / 2) / pixel_depth
if image_data.shape != (image_size, image_size):
raise Exception('Unexpected image shape: %s' % str(image_data.shape))
dataset[num_images, :, :] = image_data
num_images = num_images + 1
except IOError as e:
print('Could not read:', image_file, ':', e, '- it\'s ok, skipping.')
dataset = dataset[0:num_images, :, :]
if num_images < min_num_images:
raise Exception('Many fewer images than expected: %d < %d' %
(num_images, min_num_images))
print('Full dataset tensor:', dataset.shape)
print('Mean:', np.mean(dataset))
print('Standard deviation:', np.std(dataset))
return dataset
where that function is called like this:
dataset = load_letter(folder, min_num_images_per_class)
try:
with open(set_filename, 'wb') as f:
pickle.dump(dataset, f, pickle.HIGHEST_PROTOCOL)
The idea here is:
Now let's load the data in a more manageable format. Since, depending on your computer setup you might not be able to fit it all in memory, we'll load each class into a separate dataset, store them on disk and curate them independently. Later we'll merge them into a single dataset of manageable size.
We'll convert the entire dataset into a 3D array (image index, x, y) of floating point values, normalized to have approximately zero mean and standard deviation ~0.5 to make training easier down the road.
Do this as below:
#define a function to conver label to letter
def letter(i):
return 'abcdefghij'[i]
# you need a matplotlib inline to be able to show images in python notebook
%matplotlib inline
#some random number in range 0 - length of dataset
sample_idx = np.random.randint(0, len(train_dataset))
#now we show it
plt.imshow(train_dataset[sample_idx])
plt.title("Char " + letter(train_labels[sample_idx]))
Your code changed the type of dataset actually, it is not an ndarray of size (220000, 28,28)
In general, pickle is a file which holds some objects, not the array itself. You should use the object from pickle directly to get your train dataset (using the notation from your code snippet):
#will give you train_dataset and labels
train_dataset = loaded_pickle['train_dataset']
train_labels = loaded_pickle['train_labels']
UPDATED:
Per request from #gsarmas the link to my solution for whole Assignment1 lies here.
The code is commented and mostly self-explanatory, but in case of any questions feel free to contact via any way you prefer on github
Please check with this code
pickle_file = train_datasets[0]
with open(pickle_file, 'rb') as f:
# unpickle
letter_set = pickle.load(f)
# pick a random image index
sample_idx = np.random.randint(len(letter_set))
# extract a 2D slice
sample_image = letter_set[sample_idx, :, :]
plt.figure()
# display it
plt.imshow(sample_image)
Use this code:
#random select a letter
i = np.random.randint( len(train_datasets) )
plt.title( "abcdefghij"[i] )
#read the file of selected letter
f = open( train_datasets[i], "rb" )
f = pickle.load(f)
#random select an image in the file
j = np.random.randint( len(f) )
#show image
plt.axis('off')
img = plt.imshow( f[ j, :, : ] )
enter image description here

Moments as feature and KNN classifier using OpenCV and Python - Knearest doesn't classify

I have a set of twelve shapes and I'm trying to determine the shape of a query image with the my database
For convinience I have done all the preprocessing in MATLAB and have stored the shape contours,
as binary image separately for training and testing prupose
I have done the Feature extraction and Implementation phase in Python
In the training phase, I read the binary image, extract HU MOMETS (7 Vector)
as features for all the train images(285 in total)
So my samples (train samples) dimension is [285, 7]
My responses dimension is [285]
Now I follow a similar strategy for testing as well. Test images consititue 541 in total
Read image -> extract hu moments -> feed it to knn.find_nearest
Dimension of the test moments is [1, 7]
The problem that I'm facing here is, irrespective of the test image that I give, I'm getting a
return value in the knn.find_nearest as 76. It is consistently giving the same value for every image
What have I done to debug
Checked with code to ensure if the dimens that I'm providing to KNN is correct
Checked the Hu-moments values in matlab as well, and found nearly similar with opencv
Also made sure that hu-moments for test image are computing properly
Tested with changing the k value (when k=1 retval is 76, when k=3 retval is 75)
I don't know what I have done wrong here. please help
import os
import sys
import numpy
import cv2
import cv2.cv as cv
import xlwt
def main():
pth = sys.argv[1]
lsfolds = os.listdir(pth)
files_path = []
all_moments = numpy.empty((0,7))
train_samples = []
responses = []
cnt=0
for di in lsfolds:
img_path = os.path.join(pth,di)
lsfiles = os.listdir(img_path)
for ls in lsfiles:
comp_path = os.path.join(img_path,ls)
files_path.append(comp_path)
if (comp_path[-4:] == 's.db'):
continue
img_bin = cv2.imread(comp_path,-1)
#cv2.imshow('Image', img_bin)
#cv2.waitKey()
#################### Moments as Feature ###############################
moments = cv2.moments(img_bin,1)
hu_moments = cv2.HuMoments(moments)
hu_moments = hu_moments.reshape((1,7))
all_moments = numpy.append(all_moments,hu_moments,0)
train_samples.append(comp_path)
responses.append(int(cnt))
########################################################################
cnt += 1
responses = numpy.float32(responses)
all_moments = numpy.float32(all_moments)
################## KNN #####################################
knn_train_eng = cv2.KNearest()
knn_train_eng.train(all_moments,responses)
#######################################Testing######################################
timg_pth = sys.argv[2]
tfolds = os.listdir(timg_pth)
wb = xlwt.Workbook()
ws = wb.add_sheet('Test Results')
c=0
for tdi in tfolds:
timg_dir = os.path.join(timg_pth,tdi)
tfiles = os.listdir(timg_dir)
for fl in tfiles:
timg_path = os.path.join(timg_dir,fl)
if (timg_path[-4:] == 's.db'):
continue
timg = cv2.imread(timg_path,-1)
timg_bin = timg;
#cv2.imshow('test_bin',timg_bin)
tmoments = cv2.moments(timg_bin)
thu_moments = cv2.HuMoments(tmoments)
thu_moments = thu_moments.reshape((1,7))
thu_moments = numpy.float32(thu_moments)
retval, results, neigh_resp, dists = knn_train_eng.find_nearest(thu_moments,1) # Predict using KNN
res,dist = int(results[0][0]),dists[0][0]
op_answ = str(int((results[0][0])))
print op_answ
print train_samples[int(op_answ)]
op = cv2.imread(train_samples[int(op_answ)])
c+=1
cv2.destroyAllWindows()
##############################################################################
cv2.destroyAllWindows()
if __name__ == '__main__':
main()

Categories

Resources