Dimensional error while predicting - python

I have trained a convolutional3d model using code
Im trying to get the prediction as follows,
import cv2
from keras.models import Sequential, load_model
import numpy as np
#create an empty frame
frames = []
#defince row, col
img_rows,img_cols,img_depth=16,16,15
cap = cv2.VideoCapture('run.avi')
fps = cap.get(5)
#Use only first 15 frames for prediction
for k in range(15):
ret, frame = cap.read()
frame=cv2.resize(frame,(img_rows,img_cols),interpolation=cv2.INTER_AREA)
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
frames.append(gray)
#preprocess
input = np.array(frames)
ipt=np.rollaxis(np.rollaxis(input,2,0),2,0)
reshape_frames = np.expand_dims(ipt, axis=0)
#run prediction
model = load_model('current.h5')
preds = model.predict(reshape_frames)
print(preds)
but it fires the following error,
ValueError: Error when checking : expected conv3d_1_input to have 5
dimensions, but got array with shape (1, 16, 16, 15)
How can I be able to sort this out?

See in the docs for convolutional 3D layers:
Input shape
5D tensor with shape: (samples, channels, conv_dim1, conv_dim2, conv_dim3) if data_format='channels_first' or 5D tensor with shape: (samples, conv_dim1, conv_dim2, conv_dim3, channels) if data_format='channels_last'.
So what is bascially happening is that the input shape you provide to your first conv 3D layer does not fit to the expected input.
To solve this you could go as follows:
change the provided input, so that it matches the expected input (also take into account the data_format as noted above). As it looks in your code, you don't use the img_depth information at all. You basically provide a 2D image to a 3D conv net.
Use a 2D convnet and create a new model

Related

Predicting a single PNG image using a trained TensorFlow model

import tensorflow as tf
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape = (28,28)),
tf.keras.layers.Dense(128, activation = 'relu'),
tf.keras.layers.Dropout(0.2),
tf.keras.layers.Dense(10)
])
This is the code for the model, which I have trained using the mnist dataset. What I want to do is to then pass a 28x28 png image to the predict() method, which is not working. The code for the prediction is:
img = imageio.imread('image_0.png')
prediction = model.predict(img, batch_size = 1)
which produces the error
ValueError: Error when checking input: expected flatten_input to have shape (28, 28) but got array with shape (28, 3)
I have been stuck on this problem for a few days, but I can't find the correct way to pass an image into the predict method. Any help?
Predict function makes predictions over a batch of image. You should include batch dimension (first dimension) to your img, even to predict a single example.
You need something like this:
img = imageio.imread('image_0.png')
img = np.expand_dims(img, axis=0)
prediction = model.predict(img)
As #desertnaut says, seems you are using a RGB image, so your first layer should use input_shape = (28,28,3). Therefore, img parameter of predict function should have (1,28,28,3) shape.
In your case, img parameter of predict function has (28,28,3) shape, thus predict function took the first dimension as number of images, and could not match the other two dimensions to the input_shape of the first layer.

How to reshape an array of shape (150,150,3) to an array of shape (1,8192)

I have trained a deep learning model as follows, its a classifier base for VGG16.
model = tf.keras.models.Sequential([
tf.keras.layers.Dense(256, activation='relu', input_dim=4 * 4 * 512),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(1, activation='sigmoid')
1-My model accepts tensors of shape (1,8192) for predictions.
2-I have test images of shape (150,150,3) which are converted to arrays.
3-Now I want a method to convert my (150,150,3) images to tensors of shape (1,8192).
The input dimension seems very arbitrary and not suitable to the task. If you are very stubborn to proceed, you could simply cast it to 1d array and resample like this:
import numpy as np
from scipy import signal
image = np.random.rand(150,150,3)
image_8192 = signal.resample(image.ravel(), 8192)
... but it's a very bad idea. Somewhat smarter would be to more intelligently downsample the image, first by converting it to grayscale and then downsample:
from skimage.color import rgb2gray
from skimage.transform import resize
grayscale = rgb2gray(image)
grayscale_91pix = resize(image, (91, 91)) # size 8291
image_8192 = signal.resample(grayscale_91pix.ravel(), 8192)
It's still not great, but better than the naive approach.

TensorFlow Keras dimension error for input layer

I've searched through all the solutions related to this, and I still can't figure out how to shape my training data so Tensorflow accepts it.
My training data is a numpy array of shape (21005, 48, 48), where the 21005 is number of elements and the 48,48 is a 48x48 grayscale image.
model.add(tf.keras.layers.Conv2D(64, kernel_size=3,activation='relu',input_shape=(48,48,1)))
model.add(tf.keras.layers.Conv2D(32, kernel_size=3,activation='relu'))
model.add(tf.keras.layers.Flatten())
model.add(tf.keras.layers.Dense(7, activation='softmax'))
model.compile(optimizer='adam',
loss = 'sparse_categorical_crossentropy',
metrics=['accuracy'])
model.fit(image_train, emotion_train,batch_size=BATCH_SIZE,epochs=EPOCHS, verbose=1)
When I run the fit function, however, it returns an error stating:
ValueError: Error when checking input: expected conv2d_input to have 4 dimensions, but got array with shape (21005, 48, 48)
This leads me to think I'm formatting the input data incorrectly, or missing something regarding how Keras and TF actually pass the input image into the input layer. I've tried adding the extra dimension to the input shape to allow for a channel in a 2d Conv layer, as well as reshaping the images themselves to no avail. Any advice?
Reshape your training data to have 4-dimensions before calling model.fit() such as:
image_train = np.reshape(image_train, (21005, 48, 48, 1))
This is needed because the first Conv2D layer expects an image to have an input_shape of (48,48,1)
When you made your preprocessing, you might have read the image in grayscale mode with a library OpenCV/PIL.
When you read them, your library considers a grayscale image of size (48,48), not a (48,48,1), hence the issue that you have.
Solve the issue as soon as possible, not before feeding to your model; in your code, wherever you read those images, before appending to your list/arrays, ensure the right shape of the array is picked. You can see down below an OpenCV example:
image = cv2.imread(filepath, 0)
#Before this np_expand_dims, image has shape (48,48)
image = np.expand_dims(image , axis=2)
#After this step, image has shape (48,48,1)

Numpy array of images wrong dimension Python and Keras

I'm building an image classifier and trying to compute the features for a dataset using keras but my array dimension is not on the right format. I'm getting
ValueError: Error when checking : expected input_1 to have 4 dimensions, but got array with shape (324398, 1)
My code is this:
import glob
from keras.applications.resnet50 import ResNet50
def extract_resnet(X):
# X : images numpy array
resnet_model = ResNet50(input_shape=(image_h, image_w, 3),
weights='imagenet', include_top=False) # Since top layer is the fc layer used for predictions
features_array = resnet_model.predict(X)
return features_array
filelist = glob.glob('dataset/*.jpg')
myarray = np.array([np.array(Image.open(fname)) for fname in filelist])
print(extract_resnet(myarray))
So it looks like for some reason the images array is only two dimensional when it should be 4 dimensional. How can I convert myarray so that it is able to work with the feature extractor?
First up, make sure that all of the images in dataset directory have the same size (image_h, image_w, 3):
print([np.array(Image.open(fname)).shape for fname in filelist])
If they are not, you won't be able to make a mini-batch, so you'll need to select only the subset of suitable images. If the size is right, you can then reshape the array manually:
myarray = myarray.reshape([-1, image_h, image_w, 3])
... to match ResNet specification exactly.

How to apply a previously unseen image to a previously saved model?

I wanted to know how to apply a previously unseen image to a previously saved CNN model and see how it classifies it ?
Code (My attempt)
from keras.models import load_model
from keras.preprocessing import image
import numpy as np
img_path = '/Users/eoind/code/1.jpg'
model = load_model('food.h5')
model.summary()
img = image.load_img(img_path, target_size=(100,100))
image = image.img_to_array(img)
image = np.expand_dims(image, axis=0)
print(image.shape)
images = np.vstack([image])
print("classifying images..")
image_class = model.predict_classes(images)
print(image_class)
iPython Console Error
ValueError: Error when checking : expected dense_1_input to have 2 dimensions, but got array with shape (1, 100, 100, 3)
The error says that the input shape of your network does not match the shape of your image. It seems like the first layer of your network is a dense layer, which is a fully-connected layer and it expects the input to be of shape (batch_size, num_of_neurons_in_the_bottom), but your are giving it an image with shape (batch_size, height, width, channels). Here is a checklist for troubleshooting your problem:
Has the model at least loaded? If the above error happens during loading, then your model is broken (perhaps not properly saved). If not, continue through the checklist...
In programming, always output the values of your variables for debugging! What is the value of model.summary()? Are you sure that the input shape of your network is (100, 100, 3)? Is the first layer a convolutional one?
If the first layer is dense (which is fully-connected), check the training code on how you feed images to the model - maybe your image should be re-shaped or somehow pre-processed?

Categories