Tensorflow Pipeline for images and numpy files - python

I am working with tensorflow 2.0.0 and am trying to setup an efficient pipeline for feeding in ~90,000 png images of size (256, 256, 3) and their labels which are numpy arrays of size (256,256) for an image segmentation problem. These images and labels won't load fully into memory.
The data are stored in a directory like this:
'C:/Users/user/Documents/data/ims/' #png images
'C:/Users/user/Documents/data/masks/' #img labels/masks
The file names are the same save the extension so for example "test1.png" and "test1.npy" are an image/label pair.
The data are not split into training, validation, and test subsets yet.
I need to get to a point in which I have both the images and labels split into train, validation, and testing subsets, and also have a means to feed the data into a model for training.
I was following this guide here but could not figure out how to deal with the numpy files within the get_label function.
I thought I could write a function that splits the data into subsets via file names alone and then on the fly load the batches via the file names provided, but I can't figure out how to do this efficiently.
I'm currently doing this which either doesn't work because the files are too big or too slow because there are some many files to load into memory, either of which isn't a viable solution.
import tensorflow as tf
import numpy as np
import glob2 as glob
from imageio import imread
base = '/mnt/projects/CNN_Data/clean_data/'
image_path = sorted(glob.glob(base + 'ims/*.png'))
label_path = sorted(glob.glob(base + 'masks/*.npy'))
images = [imread(img).astype(np.float32)/255.0 for img in image_path]
labels = [np.load(path) for path in label_path]
Edit to add:
Here was my attempt following the tensorflow example that I linked above. It runs, but I can't get get_label to what I want.
import tensorflow as tf
import numpy as np
import os
AUTOTUNE = tf.data.experimental.AUTOTUNE
base = '/mnt/projects/CNN_Data/clean_data/'
list_ds = tf.data.Dataset.list_files(base + 'ims/*')
def get_label(file_path):
parts = tf.strings.split(file_path, os.path.sep)
parts[-2] == 'masks'
fname = tf.strings.split(parts[-1], '.')[0]
fname = tf.strings.join([fname, '.npy'])
parts[-1] == fname
return parts
def decode_img(img):
img = tf.image.decode_png(img, channels = 3)
img = tf.image.convert_image_dtype(img, tf.float32)
return img
def process_path(file_path):
label = get_label(file_path)
img = tf.io.read_file(file_path)
img = decode_img(img)
return img, label
labeled_ds = list_ds.map(process_path, num_parallel_calls=AUTOTUNE)

Related

How to properly use pre-trained CNN for image prediction on a folder of images

I am trying to build a CNN model and use it on 2833 images to see if it can predict a selection (of my own choice) of three features and the popularity score from a tabular dataset. So far my code looks like this:
import os
import cv2
import argparse
import numpy as np
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image as image_utils
from keras.applications.imagenet_utils import preprocess_input, decode_predictions
# Construct argument parser and parse the arguments
argument_parser = argparse.ArgumentParser()
# First two arguments specifies our only argument "image" with both short-/longhand versions where either
# can be used
# This is a required argument, noted by required=True, the help gives additional info in the terminal
# if needed
argument_parser.add_argument("-i", "--image", required=True, help="path to the input image")
# Set path to files
img_path = "images/"
files = os.listdir(img_path)
print("[INFO] loading and processing images...")
# Loop through images
for filename in files:
# Load original via OpenCV, so we can draw on it and display it on our screen
original = cv2.imread(filename)
# Load image while resizing to 224x224 pixels, then convert to a NumPy array because load_img returns
# Pillow format
image = image_utils.load_img(filename, target_size=(224, 224))
image = image_utils.img_to_array(image)
"""
PRE-PROCESS
The image is now a NumPy array of shape (224, 224, 3). 224 pixels tall, 224 pixels wide, 3 channels =
Red, Green, Blue. We need to expand to (1, 3, 224, 224) because when classifying images using Deep
Learning and Convolutional Neural Networks, we often send several images (instead of one) through
the network in “batches” for efficiency. We also subtract the mean RGB pixel intensity from the
ImageNet dataset.
"""
image = np.expand_dims(image, axis=0)
image = preprocess_input(image)
# Load Keras and classify the image
print("[INFO] loading network...")
model = VGG16(weights="imagenet") # Load the VGG16 network pre-trained on the ImageNet dataset
print("[INFO] classifying image...")
predictions = model.predict(image) # Classify the image (NumPy array with 1000 entries)
P = decode_predictions(predictions) # Get the ImageNet Unique ID of the label, along with human-readable label
print(P)
# Loop over the predictions and display the rank-5 (5 epochs) predictions + probabilities to our terminal
for (i, (imagenetID, label, prob)) in enumerate(P[0]):
print("{}. {}: {:.2f}%".format(i + 1, label, prob * 100))
# Load the image via OpenCV, draw the top prediction on the image, and display the
image to our screen
original = cv2.imread(filename)
(imagenetID, label, prob) = P[0][0]
cv2.putText(original, "Label: {}, {:.2f}%".format(label, prob * 100), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
cv2.imshow("Classification", original)
cv2.waitKey(0)
I followed this article on how to do it, and it worked on one image. But when I tried to put the code inside a loop, I get this error message:
[ WARN:0#44.040] global D:\a\opencv-python\opencv-python\opencv\modules\imgcodecs\src\loadsave.cpp (239) cv::findDecoder imread_('100.png'): can't open/read file: check file path/integrity
Traceback (most recent call last):
File "C:\PATH\test_imagenet.py", line 28, in <module>
image = image_utils.load_img(filename, target_size=(224, 224))
File "C:\PATH\AppData\Local\Programs\Python\Python39\lib\site-packages\keras\preprocessing\image.py", line 313, in load_img
return image.load_img(path, grayscale=grayscale, color_mode=color_mode,
File "C:\PATH\AppData\Local\Programs\Python\Python39\lib\site-packages\keras_preprocessing\image\utils.py", line 113, in load_img
with open(path, 'rb') as f:
FileNotFoundError: [Errno 2] No such file or directory: '100.png'
As you can see, I have the file in the project, so I don't know why it doesn't find it. How do I do this correctly for a file of images, instead of for one image only?
Please find the working code below;
import os
import cv2
import argparse
import numpy as np
from keras.applications.vgg16 import VGG16
from keras.preprocessing import image as image_utils
from keras.applications.imagenet_utils import preprocess_input, decode_predictions
# Construct argument parser and parse the arguments
argument_parser = argparse.ArgumentParser()
# First two arguments specifies our only argument "image" with both short-/longhand versions where either
# can be used
# This is a required argument, noted by required=True, the help gives additional info in the terminal
# if needed
argument_parser.add_argument("-i", "--image", required=True, help="path to the input image")
# Set path to files
img_path = "/content/train/"
files = os.listdir(img_path)
print("[INFO] loading and processing images...")
for filename in files:
# Passing the entire path of the image file
file= os.path.join(img_path, filename)
# Load original via OpenCV, so we can draw on it and display it on our screen
original = cv2.imread(file)
image = image_utils.load_img(file, target_size=(224, 224))
image = image_utils.img_to_array(image)
image = np.expand_dims(image, axis=0)
image = preprocess_input(image)
print("[INFO] loading network...")
model = VGG16(weights="imagenet") # Load the VGG16 network pre-trained on the ImageNet dataset
print("[INFO] classifying image...")
predictions = model.predict(image) # Classify the image (NumPy array with 1000 entries)
P = decode_predictions(predictions) # Get the ImageNet Unique ID of the label, along with human-readable label
print(P)
# Loop over the predictions and display the rank-5 (5 epochs) predictions + probabilities to our terminal
for (i, (imagenetID, label, prob)) in enumerate(P[0]):
print("{}. {}: {:.2f}%".format(i + 1, label, prob * 100))
original = cv2.imread(file)
(imagenetID, label, prob) = P[0][0]
cv2.putText(original, "Label: {}, {:.2f}%".format(label, prob * 100), (10, 30),
cv2.FONT_HERSHEY_SIMPLEX, 0.8, (0, 255, 0), 2)
cv2.imshow(original)
cv2.waitKey(0)
Output is as follows:
Let us know if the issue still persists. Thanks!

Setting up data for keras using pandas

How do I read data from a CSV file and turn into my training data and labels?
TRAIN_DATA = "C:\\Users\jackt\Desktop\machine_learning_coursework\MY_TRAIN.csv"
TEST_DATA = "C:\\Users\jackt\Desktop\machine_learning_coursework\MY_LABELS.csv"
train_file_path = tf.keras.utils.get_file("MY_TRAIN.csv", TRAIN_DATA)
test_file_path = tf.keras.utils.get_file("MY_LABELS.csv", TEST_DATA)
np.set_printoptions(precision=3, suppress=True)
MY output error is.
Exception: URL fetch failure on C:\Users\jackt\Desktop\machine_learning_coursework\MY_TRAIN.csv: None -- unknown url type: c
Read csv file, create two empty list, append the image and labels data to respective list, convert it into numpy arrays and save it.
At the time of training, load it using scikit package and shuffle it. There are numerous tutorials for that.
import pandas as pd
from os.path import join
import cv2
import numpy as np
from keras.utils import to_categorical
train_df = pd.read_csv('train.csv')
# Read columns (multiple ways to do it)
images = train_df["images"]
labels = train_df["labels"]
train_data = []
train_label = []
for (image, label) in zip(images, labels):
img = cv2.imread(join("train_dir", image))
img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
# if you want to resize images to a particular shape
img = cv2.resize(img, (160, 160), interpolation=cv2.INTER_AREA)
# Append images and labels
train_data.append(img)
train_label.append(label)
train_data = np.array(train_data)
train_label = np.array(train_label)
train_label = to_categorical(train_label)
np.save("train_data.npy", train_data)
np.save("train_label.npy", train_label)

What is solution for this error "ValueError: If evaluating from data tensors, you should specify the `steps` argument"?

I am testing my Deep learning model, I wrote this code
from keras.models import load_model
classifier = load_model('Trained_model.h5')
classifier.evaluate()
Prediction of single image
import numpy as np
from keras.preprocessing import image
img_name = input('Enter Image Name: ')
image_path = './predicting_data/test_set/{}'.format(img_name)
print('')
after running, I am getting this error
ValueError: If evaluating from data tensors, you should specify the `steps` argument.
NOTE :- ./predicting_data/test_Set is the path of my test dataset which has sub folders like A b...c ...to z containing images
The working code to Predict the Class of an Image, by Loading the Saved Model is shown below:
import os
import tensorflow as tf
from tensorflow.keras.preprocessing import image
Test_Dir = '/Dogs_Vs_Cats_Small/test/cats'
New_Model = tf.keras.models.load_model('Dogs_Vs_Cats.h5')
New_Model.summary()
Image_Path = os.path.join(Test_Dir, 'cat.1500.jpg')
Img = image.load_img(Image_Path, target_size = (150,150))
Img_Array = image.img_to_array(Img)
Img_Array = Img_Array/255.0
Img_Array = tf.reshape(Img_Array, (-1,150,150,3))
Predictions = New_Model.predict(Img_Array)
Label = tf.argmax(Predictions)
Label.numpy()[0]
Final line gives the respective Class for our Image.

valueerror: can't reshape array of size 315 into shape (32,32)

I'm trying to use the code in this page: https://medium.com/#muskulpesent/create-numpy-array-of-images-fecb4e514c4b
import cv2
import glob
import numpy as np
#Train data
train = []
train_labels = []
files = glob.glob (r"C:\Users\Downloads\All_Codes\image\0\*.png") # your image path
for myFile in files:
image = cv2.imread (myFile ,cv2.IMREAD_GRAYSCALE)
input_img_resize=cv2.resize(image,(64,64))
train.append (input_img_resize)
train_labels.append([0])
print(train)
print(len(train))
files = glob.glob (r"C:\Users\Downloads\All_Codes\image\1\*.png")
for myFile in files:
image = cv2.imread (myFile,cv2.IMREAD_GRAYSCALE)
print(image)
#input_img_resize=cv2.resize(image,(64,64))
train.append (image)
train_labels.append([1])
print(len(train_labels))
print(train_labels)
train = np.array(train,dtype=object) #as mnist
train_labels = np.array(train_labels,dtype=object) #as mnist
# convert (number of images x height x width x number of channels) to (number of images x (height * width *3))
# for example (120 * 40 * 40 * 3)-> (120 * 4800)
train = np.reshape(train,(train.shape[0],64,64))
# save numpy array as .npy formats
np.save('train',train)
np.save('train_labels',train_labels)
But I had some errors. The problem is that I get the same error every time I attempt to read my images and reshaping them using np.reshape. I searched a lot and used so many codes. They are all the same. That I can't shape (the number of images in my dataset) to (32, 32) which is the shape I want to insert to my CNN model. The only thing I know for sure is the images in my dataset are of different shapes. Is this why I'm having a diffculty in reshaping them? then what's the point of using "resize" and "reshape"?
the first error is:
ValueError: cannot reshape array of size 315 into shape (315,32,32)
for this line:
train = np.reshape(train,[train.shape[0],32,32])
So, I solved the problem.
import cv2
import glob
import numpy as np
import PIL.Image
#Train data
train = []
train_labels = []
files = glob.glob (r"\train\0\*.png") # your image path
for myFile in files:
image = cv2.imread (myFile ,cv2.IMREAD_GRAYSCALE)
input_img_resize=cv2.resize(image,(64,64))
train.append (input_img_resize)
train_labels.append([0])
#print(train)
#print(len(train))
files = glob.glob (r"\train\1\*.png")
for myFile in files:
image = cv2.imread (myFile,cv2.IMREAD_GRAYSCALE)
input_img_resize=cv2.resize(image,(64,64))
#print(input_img_resize)
train.append (input_img_resize)
train_labels.append([1])
print(len(train))
print(len(train_labels))
train = np.array(train,dtype="float32") #as mnist
train_labels = np.array(train_labels,dtype="float32") #as mnist
train = np.reshape(train,(-1,64,64,1))
I resized my images using cv2.resize (inside the loop)
Then did a reshape using np.reshape.
If I relied on one of them, it dose not work. I have to add them both.
The output is:
315 #len for x and y
315
(315, 64, 64) #after cv2.resize
(315, 1)
(315, 64, 64, 1) #after np.reshape
(315, 1)

Loading images and eval() in tensorflow are super slow

X = []
filelist = gfile.ListDirectory(path_imgs)
for filename in filelist:
path_filename = path_imgs + filename
image_file = file_io.FileIO(path_filename,'rb')
image_raw = image_file.read()
img = tf.image.decode_image(image_raw)
img = tf.image.convert_image_dtype(img, tf.float32)
img = tf.image.resize_image_with_pad(img, img_size, img_size, method=1).eval(session=tf.Session())
X.append(img)
imgs = np.array(X)
Tried some things with session, but didn't work. Probably it should be handled differently, but I don't know how to do it. Any ideas?
EDIT:
Yes, I want to train ANN to segment objects in images.
There are folders with images and their masks. Size is 1000s, and could be 10s of 1000s.
I need single numpy array of images, which will be saved, and used later as dataset for model training.
def getImageData(fileNameList):
imageData=[]
for fn in fileNameList:
testImage = Image.open(fn)
testImage.show()
imageData.append(np.array(testImage))
return np.array(imageData,dtype=np.float32)
imageFn=("dog.png",)
imageData=getImageData(imageFn)
you must import something:
import tensorflow as tf
from PIL import Image
import numpy as np

Categories

Resources