0
$\begingroup$

I am doing image classification using Convolutional neural networks, but I have a problem, because the images I want to classify are all of different sizes. My code is the following:

import numpy as np
import tensorflow as tf
import keras
from keras.preprocessing.image import ImageDataGenerator

trainingset = '/content/drive/My Drive/Colab Notebooks/Train'
testset = '/content/drive/My Drive/Colab Notebooks/Test'

batch_size = 32
train_datagen = ImageDataGenerator(
    rescale = 1. / 255,\
    zoom_range=0.1,\
    rotation_range=10,\
    width_shift_range=0.1,\
    height_shift_range=0.1,\
    horizontal_flip=True,\
    vertical_flip=False)

train_generator = train_datagen.flow_from_directory(
    directory=trainingset,
    target_size=(118, 224),
    color_mode="rgb",
    batch_size=batch_size,
    class_mode="categorical",
    shuffle=True
)

test_datagen = ImageDataGenerator(
    rescale = 1. / 255)

test_generator = test_datagen.flow_from_directory(
    directory=testset,
    target_size=(118, 224),
    color_mode="rgb",
    batch_size=batch_size,
    class_mode="categorical",
    shuffle=False
)

num_samples = train_generator.n
num_classes = train_generator.num_classes
input_shape = train_generator.image_shape

classnames = [k for k,v in train_generator.class_indices.items()]

print("Image input %s" %str(input_shape))
print("Classes: %r" %classnames)

print('Loaded %d training samples from %d classes.' % 
  (num_samples,num_classes))
print('Loaded %d test samples from %d classes.' % 
   (test_generator.n,test_generator.num_classes))

and

from keras.models import Sequential
from keras.layers import Dense, Activation, Dropout, Flatten,\
                     Conv2D, MaxPooling2D
from keras.layers.normalization import BatchNormalization
from keras import regularizers
from keras import optimizers

def AlexNet(input_shape, num_classes, regl2 = 0.0001, lr=0.0001):

model = Sequential()

# C1 Convolutional Layer 
model.add(Conv2D(filters=96, input_shape=input_shape, kernel_size=(11,11),\
                 strides=(2,4), padding='valid'))
model.add(Activation('relu'))
# Pooling
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
# Batch Normalisation before passing it to the next layer
model.add(BatchNormalization())

# C2 Convolutional Layer
model.add(Conv2D(filters=256, kernel_size=(11,11), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Pooling
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
# Batch Normalisation
model.add(BatchNormalization())

# C3 Convolutional Layer
model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Batch Normalisation
model.add(BatchNormalization())

# C4 Convolutional Layer
model.add(Conv2D(filters=384, kernel_size=(3,3), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Batch Normalisation
model.add(BatchNormalization())

# C5 Convolutional Layer
model.add(Conv2D(filters=256, kernel_size=(3,3), strides=(1,1), padding='valid'))
model.add(Activation('relu'))
# Pooling
model.add(MaxPooling2D(pool_size=(2,2), strides=(2,2), padding='valid'))
# Batch Normalisation
model.add(BatchNormalization())

# Flatten
model.add(Flatten())

flatten_shape = (input_shape[0]*input_shape[1]*input_shape[2],)

# D1 Dense Layer
model.add(Dense(4096, input_shape=flatten_shape, kernel_regularizer=regularizers.l2(regl2)))
model.add(Activation('relu'))
# Dropout
model.add(Dropout(0.4))
# Batch Normalisation
model.add(BatchNormalization())

# D2 Dense Layer
model.add(Dense(4096, kernel_regularizer=regularizers.l2(regl2)))
model.add(Activation('relu'))
# Dropout
model.add(Dropout(0.4))
# Batch Normalisation
model.add(BatchNormalization())

# D3 Dense Layer
model.add(Dense(1000,kernel_regularizer=regularizers.l2(regl2)))
model.add(Activation('relu'))
# Dropout
model.add(Dropout(0.4))
# Batch Normalisation
model.add(BatchNormalization())

# Output Layer
model.add(Dense(num_classes))
model.add(Activation('softmax'))

# Compile

adam = optimizers.Adam(lr=lr)
model.compile(loss='categorical_crossentropy', optimizer=adam, metrics=['accuracy'])

return model

# create the model
model = AlexNet(input_shape,num_classes)
model.summary()

now, if I do the training, I get:

steps_per_epoch=train_generator.n//train_generator.batch_size
val_steps=test_generator.n//test_generator.batch_size+1

try:
    history = model.fit_generator(train_generator, epochs=50, verbose=1,\
                    steps_per_epoch=steps_per_epoch,\
                    validation_data=test_generator,\
                    validation_steps=val_steps)
except KeyboardInterrupt:
    pass

if get the following error message:

ValueError                                Traceback (most recent call last)
<ipython-input-11-70354a7752ae> in <module>()
      3 
      4 try:
----> 5     history = model.fit_generator(train_generator, epochs=50, 
verbose=1,                    steps_per_epoch=steps_per_epoch,                    
validation_data=test_generator,                    
validation_steps=val_steps)
      6 except KeyboardInterrupt:
      7     pass

8 frames
/usr/local/lib/python3.6/dist-packages/keras/engine/training_utils.py in 
standardize_input_data(data, names, shapes, check_batch_axis, 
exception_prefix)
    139                             ': expected ' + names[i] + ' to have 
shape ' +
    140                             str(shape) + ' but got array with shape ' +
--> 141                             str(data_shape))
    142     return data
    143 

ValueError: Error when checking target: expected activation_9 to have shape 
(4,) but got array with shape (5,)

so, this should mean that the images I want to classify are of different sizes. So how can I do classification in this case?

I think I should reshape the images somehow in such a way they have all the same size.

I have looked up on the internet for a solution, but I haven't find anything that works well. Can somebody please help me? Thanks in advance.

[EDIT]I am trying to do the following to resize the photos:

from PIL import Image
import os, sys

path = "/content/drive/My Drive/Colab Notebooks/Train"
dirs = os.listdir( path )

def resize():
    for item in dirs:
        if os.path.isfile(path+item):
            im = Image.open(path+item)
            f, e = os.path.splitext(path+item)
            imResize = im.resize((200,200), Image.ANTIALIAS)
            imResize.save(f + ' resized.jpg', 'JPEG', quality=90)

resize()

In particular, I write this code before building the network.

But it still gives me the same error. I am really stuck on this.

[EDIT 2] I have also tried to apply this to the sub folders, so if I have:

enter image description here

I have considered sigularly the sub-directories HAZE,SUNNY,CLOUDY,SNOWY , but it still does not work.

The fact is that I don't see what I am doing wrong in the code above.

$\endgroup$
0
$\begingroup$

I am not an expert in image classification but from the little I know I can tell you that the images should have the same size because the images are converted to an structured array of size n (pictures) x (width (px) x height (px) x 3)

The 3 is due to the arrays RGB.

If the width and height are not the same, the derived structured array will not have the same size for all individuals.

There should be some package that helps you convert the images to the same size.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.