Home > Software design >  Resizing image to 28x28 for my Tensorflow model to work
Resizing image to 28x28 for my Tensorflow model to work

Time:10-25

I'm working with TensorFlow, Numpy, and MatPlotLib. I'm a real beginner to all this so I'm following the docs and using the Fashion MNIST dataset as the docs are.

So here's my code:

# See tensorflow version and import other helper modules
import tensorflow as tf
from tensorflow.keras.preprocessing import image
import numpy as np
import matplotlib.pyplot as plt
print(tensorflow.__version__)

# Load the MNIST Fashion dataset
fashion_mnist = tf.keras.datasets.fashion_mnist
print(fashion_mnist)

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat', 'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']

# Show first image in training set (with MatPlotLib)
plt.figure()
plt.imshow(train_images[0]) # Shows first image in training set
plt.colorbar() # Shows colorbar at the right (a sort of legend on the scale of 0 to 255, which is the scale of colors on the image)
plt.show()

# Scale down values from '0 to 255' to '0 to 1'
train_images, test_images = train_images / 255.0, test_images / 255.0
test_img_path = '/content/test.jpg' # I'm getting my custom image here
test_img = image.load_img(test_img_path, target_size=(28, 28))
test_img_array = image.img_to_array(test_img)
plt.imshow(test_img)
plt.show()

plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i 1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

# Create the neural network with Sequential()
model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=(28, 28)), # Flattens 2D array to 1D array, nothing else
    tf.keras.layers.Dense(1024, activation="relu"), # 128 neurons with the reLU activation function
    tf.keras.layers.Dense(10)
])

# Compile the model with model.compile()
model.compile(
    optimizer="adam", # Adam optimizer
    loss = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True), # Use SparseCategoricalCrossentropy loss function
    metrics = ['accuracy']
)

# Fit the model to the training data using model.fit()
model.fit(train_images, train_labels, epochs=10)

# Evaluate model with model.evaluate()
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)

# Create probality model
probability_model = tf.keras.Sequential([model, tf.keras.layers.Softmax()])

# Get the predictions out of the probability model
predictions = probability_model.predict(test_images)

# Use Numpy's argmax() function to see which clothing does the model think the first test image represents
np.argmax(predictions[0])

def plot_image(i, predictions_array, true_label, img):
  true_label, img = true_label[i], img[i]
  plt.grid(False)
  plt.xticks([])
  plt.yticks([])

  plt.imshow(img, cmap=plt.cm.binary)

  predicted_label = np.argmax(predictions_array)
  if predicted_label == true_label:
    color = 'blue'
  else:
    color = 'red'

  plt.xlabel("{} {:2.0f}% ({})".format(class_names[predicted_label],
                                100*np.max(predictions_array),
                                class_names[true_label]),
                                color=color)

def plot_value_array(i, predictions_array, true_label):
  true_label = true_label[i]
  plt.grid(False)
  plt.xticks(range(10))
  plt.yticks([])
  thisplot = plt.bar(range(10), predictions_array, color="#777777")
  plt.ylim([0, 1])
  predicted_label = np.argmax(predictions_array)

  thisplot[predicted_label].set_color('red')
  thisplot[true_label].set_color('blue')

i = 0
plt.figure(figsize=(6,3))
plt.subplot(1,2,1)
plot_image(i, predictions[i], test_labels, test_images)
plt.subplot(1,2,2)
plot_value_array(i, predictions[i],  test_labels)
plt.show()

img = test_img_array
print(img.shape)
# I get (28, 28, 3)

# Add the image to a batch where it's the only member.
img = (np.expand_dims(img,0))

print(img.shape)

predictions_single = probability_model.predict(img)

plt.imshow(test_img)
plt.show()

plot_value_array(1, predictions_single[0], test_labels)
_ = plt.xticks(range(10), class_names, rotation=45)
plt.show()

(Don't mind the comments, I just wanted this Colab Notebook to be a kind of cheatsheet if I forgot how to do something later on)

When I printed the shape of test_img_array, I got (28, 28, 3). But when I printed the shape of an image in the test set, I get (28, 28). How do I remove that? I saw many other questions on this, but none of them actually solved my problem (or I'm too dumb to get it to work).

When I try to predict what my custom image is (I didn't want to use the test set for this app) using predictions_single = probability_model.predict(img), I get this weird error:

    ValueError: Input 0 of layer dense_6 is incompatible with the layer: expected axis -1 of input shape to have value 784 but received input with shape (None, 2352)

Full traceback / stacktrace with whatever else that appeared in the output:

WARNING:tensorflow:Model was constructed with shape (None, 28, 28) for input KerasTensor(type_spec=TensorSpec(shape=(None, 28, 28), dtype=tf.float32, name='sequential_5_input'), name='sequential_5_input', description="created by layer 'sequential_5_input'"), but it was called on an input with incompatible shape (None, 28, 84).
WARNING:tensorflow:Model was constructed with shape (None, 28, 28) for input KerasTensor(type_spec=TensorSpec(shape=(None, 28, 28), dtype=tf.float32, name='flatten_3_input'), name='flatten_3_input', description="created by layer 'flatten_3_input'"), but it was called on an input with incompatible shape (None, 28, 84).

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-181-b6162819a38d> in <module>()
----> 1 predictions_single = probability_model.predict(img)
      2 
      3 plt.imshow(test_img)
      4 plt.show()

9 frames

/usr/local/lib/python3.7/dist-packages/tensorflow/python/framework/func_graph.py in wrapper(*args, **kwargs)
    992           except Exception as e:  # pylint:disable=broad-except
    993             if hasattr(e, "ag_error_metadata"):
--> 994               raise e.ag_error_metadata.to_exception(e)
    995             else:
    996               raise

ValueError: in user code:

    /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:1586 predict_function  *
        return step_function(self, iterator)
    /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:1576 step_function  **
        outputs = model.distribute_strategy.run(run_step, args=(data,))
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/distribute/distribute_lib.py:1286 run
        return self._extended.call_for_each_replica(fn, args=args, kwargs=kwargs)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/distribute/distribute_lib.py:2849 call_for_each_replica
        return self._call_for_each_replica(fn, args, kwargs)
    /usr/local/lib/python3.7/dist-packages/tensorflow/python/distribute/distribute_lib.py:3632 _call_for_each_replica
        return fn(*args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:1569 run_step  **
        outputs = model.predict_step(data)
    /usr/local/lib/python3.7/dist-packages/keras/engine/training.py:1537 predict_step
        return self(x, training=False)
    /usr/local/lib/python3.7/dist-packages/keras/engine/base_layer.py:1037 __call__
        outputs = call_fn(inputs, *args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/keras/engine/sequential.py:369 call
        return super(Sequential, self).call(inputs, training=training, mask=mask)
    /usr/local/lib/python3.7/dist-packages/keras/engine/functional.py:415 call
        inputs, training=training, mask=mask)
    /usr/local/lib/python3.7/dist-packages/keras/engine/functional.py:550 _run_internal_graph
        outputs = node.layer(*args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/keras/engine/base_layer.py:1037 __call__
        outputs = call_fn(inputs, *args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/keras/engine/sequential.py:369 call
        return super(Sequential, self).call(inputs, training=training, mask=mask)
    /usr/local/lib/python3.7/dist-packages/keras/engine/functional.py:415 call
        inputs, training=training, mask=mask)
    /usr/local/lib/python3.7/dist-packages/keras/engine/functional.py:550 _run_internal_graph
        outputs = node.layer(*args, **kwargs)
    /usr/local/lib/python3.7/dist-packages/keras/engine/base_layer.py:1020 __call__
        input_spec.assert_input_compatibility(self.input_spec, inputs, self.name)
    /usr/local/lib/python3.7/dist-packages/keras/engine/input_spec.py:254 assert_input_compatibility
        ' but received input with shape '   display_shape(x.shape))

    ValueError: Input 0 of layer dense_6 is incompatible with the layer: expected axis -1 of input shape to have value 784 but received input with shape (None, 2352)

I thought it was a problem with the image shape so I tried out different answers on StackOverflow, but none of them gave me a 28x28 image. One I tried got me 28x84, but 28x28 isn't coming because of the extra 3 in the shape of the image.

CodePudding user response:

Fashion MNIST is a grayscale image dataset. Whereas your custom image has shape (28,28,3) that implies it is an RGB image. Also you need to normalize your image too.

test_img_array = test_img_array / 255.0 # normalize
test_img_array = tf.image.rgb_to_grayscale(test_img_array) # will return shape (28, 28, 1)
test_img_array = tf.squeeze(test_img_array, axis = -1) # shape is (28, 28)

Last, you need to add batch dimension.

test_img_array = tf.expand_dims(test_img_array, axis = 0) # shape: (1, 28, 28)

Predict:

predictions_single = probability_model.predict(test_img_array)

Alternatively, load_img takes an argument called color_mode which has default value of rgb. So instead of using tf.image.rgb_to_grayscale you can pass grayscale in the first place.

  • Related