Fifa worldcup 2018 Round of 16 flag detection using CNN

Building a convolutional neural network that will be able to predict if the given image is of flag from one of the country that qualified for the fifa worldcup 2018 round of 16.

Fifa worldcup 2018 Round of 16 flags classification using Keras

Now that we have all our dependencies installed and also have a basic understanding of CNNs, we are ready to perform our classification task. Download the files from the google drive link given above, unzip and paste it in your working directory. Rename the directory name to Data In your working directory,  We will be going through each portion of the code to understand what is being done.

import keras
from keras import optimizers
from keras.models import Model, load_model
from keras.layers import Dense, Dropout, Flatten,Input
from keras.layers import Conv2D, MaxPooling2D

from sklearn.datasets import load_files
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split

import os
import cv2
import numpy as np

At first, we import the necessary dependencies.

#define number of epochs to train for
epochs = 20

# input image dimensions
img_rows, img_cols = 64, 64
DATA_DIR='./Data'

#number of class labels = total number of countries
datas=load_files(DATA_DIR, load_content= False)
total_countries=len(datas.target_names)

Next, we define our constants. We train for 20 epochs. The input image size will be converted to a fixed size of 64*64 and “Data” is the directory where our training data is stored. The class labels is equal to the total number of countries in the training data.

The steps to follow in training the CNN model are:

  • Prepare input
  • Build the model
  • Train the model

We define a separate function for each of these tasks

Prepare Input

def build_data(datas):
    X = []
    y = []
    encoder = LabelBinarizer()
    encoded_dict=dict()
    hotcoded_label = encoder.fit_transform(datas.target_names)

    for i in range(len(datas.target_names)):
        encoded_dict[datas.target_names[i]]=hotcoded_label[i]

    for country in os.listdir(DATA_DIR):
        label=encoded_dict[country]
        for each_flag in os.listdir(DATA_DIR+'/'+country): 
            actual_path = os.path.join(DATA_DIR,country,each_flag)
            img_data = cv2.imread(actual_path)
            img_data = cv2.resize(img_data, (img_rows, img_cols))
            X.append(np.array(img_data))
            y.append(label)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=36)

    X_train = np.asarray(X_train)
    X_test = np.asarray(X_test)
    y_train = np.asarray(y_train)
    y_test = np.asarray(y_test)

    return [X_train, X_test, y_train, y_test]

Here, we prepare data as input for our CNN model. For X-label, we read input images using OpenCV and convert them to a fixed shape of 64*64. For y-label, we convert each of the country names to one hot encoded vector using sklearn’s LabelBinarizer. Finally, the data is split into test and training set using sklearn’s train_test_split with 90% of data as training data and 10% as test data.

Build the model

def create_model(input_shape,classes):
    img_input = Input(shape=input_shape)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)
    x = Flatten(name='flatten')(x)
    x = Dense(512, activation='relu', name='fc1')(x)
    x = Dropout(0.2)(x)
    x = Dense(256, activation='relu', name='fc2')(x)
    x = Dropout(0.2)(x)
    x = Dense(classes, activation='softmax', name='final_output')(x)
    
    model = Model(img_input, x, name='flag')
    return model

Here we build model for our CNN. The activation function we use on convolution layers is relu and on the final output layer is softmax. This is pretty much self-explanatory if you know the theories of CNN so I’m not going to dive deeper in this. If there is anything you’d like me to explain, please mention in the comment below and I’ll get back to you.

Train the model

def train_model(x_train, x_test, y_train, y_test):
    input_shape=(img_rows,img_cols,3)
    model=create_model(input_shape,total_countries)
    adams=optimizers.Adam(lr=1e-4)
    model.compile(loss='categorical_crossentropy',
                optimizer= adams,
                metrics=['accuracy'])
    model.fit(x = x_train, y = y_train, epochs=epochs)
    score = model.evaluate(x_test, y_test, verbose=1)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])
    model.save('final_roun16_flagdetection.h5')   
    return model

We train our CNN model on the dataset we prepared earlier. The input shape is the shape of the image with the color channels (64*64*3) and the output shape total number of countries (16). We use adam optimizer with a learning rate of e^-4 as it seems to give much better accuracy than the default learning rate of e^-3. The loss function we use is categorical cross entropy and we train it for the number of epochs we defined earlier. We will later use this model to predict on input data so we save it.

Finally, we define our main function as

def main():
    x_train, x_test, y_train, y_test = build_data(datas)
    train_model(x_train, x_test, y_train, y_test)

if __name__ == "__main__":
    main()

The complete code for the file is posted below:

import keras
from keras import optimizers
from keras.models import Model, load_model
from keras.layers import Dense, Dropout, Flatten,Input
from keras.layers import Conv2D, MaxPooling2D

from sklearn.datasets import load_files
from sklearn.preprocessing import LabelBinarizer
from sklearn.model_selection import train_test_split

import os
import cv2
import numpy as np

#define number of epochs to train for
epochs = 20

# input image dimensions
img_rows, img_cols = 64, 64
DATA_DIR='./Data'

#number of class labels = total number of countries
datas=load_files(DATA_DIR, load_content= False)
total_countries=len(datas.target_names)

def build_data(datas):
    X = []
    y = []
    encoder = LabelBinarizer()
    encoded_dict=dict()
    hotcoded_label = encoder.fit_transform(datas.target_names)

    for i in range(len(datas.target_names)):
        encoded_dict[datas.target_names[i]]=hotcoded_label[i]

    for country in os.listdir(DATA_DIR):
        label=encoded_dict[country]
        for each_flag in os.listdir(DATA_DIR+'/'+country): 
            actual_path = os.path.join(DATA_DIR,country,each_flag)
            img_data = cv2.imread(actual_path)
            img_data = cv2.resize(img_data, (img_rows, img_cols))
            X.append(np.array(img_data))
            y.append(label)

    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.1, random_state=36)

    X_train = np.asarray(X_train)
    X_test = np.asarray(X_test)
    y_train = np.asarray(y_train)
    y_test = np.asarray(y_test)

    return [X_train, X_test, y_train, y_test]

def create_model(input_shape,classes):
    img_input = Input(shape=input_shape)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
    x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
    x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
    x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)
    x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)
    x = Flatten(name='flatten')(x)
    x = Dense(512, activation='relu', name='fc1')(x)
    x = Dropout(0.2)(x)
    x = Dense(256, activation='relu', name='fc2')(x)
    x = Dropout(0.2)(x)
    x = Dense(classes, activation='softmax', name='final_output')(x)
    
    model = Model(img_input, x, name='flag')
    return model

def train_model(x_train, x_test, y_train, y_test):
    input_shape=(img_rows,img_cols,3)
    model=create_model(input_shape,total_countries)
    adams=optimizers.Adam(lr=1e-4)
    model.compile(loss='categorical_crossentropy',
                optimizer= adams,
                metrics=['accuracy'])
    model.fit(x = x_train, y = y_train, epochs=epochs)
    score = model.evaluate(x_test, y_test, verbose=1)
    print('Test loss:', score[0])
    print('Test accuracy:', score[1])
    model.save('final_roun16_flagdetection.h5')   
    return model

def main():
    x_train, x_test, y_train, y_test = build_data(datas)
    train_model(x_train, x_test, y_train, y_test)

if __name__ == "__main__":
    main()

Save the file as “flags.py” in your working directory and run it using the command python3flags.py The training might take some time depending on your machine and when it’s complete, you should see an output like:

Epoch 18/20

583/583 [==============================] – 8s 13ms/step – loss: 0.2539 – acc: 0.9194

Epoch 19/20

583/583 [==============================] – 8s 13ms/step – loss: 0.1982 – acc: 0.9451

Epoch 20/20

583/583 [==============================] – 8s 13ms/step – loss: 0.2032 – acc: 0.9485

65/65 [==============================] – 0s 5ms/step

Test loss: 0.6747298387380747

Test accuracy: 0.8307692307692308

As we can see the model gives training accuracy of about 95% and testing accuracy of about 83%. (Actual results may vary).

Like us on facebook to receive more updates.

About Aryal Bibek 16 Articles
Learner and practitioner of Machine Learning and Deep Learning. Ph.D. student at The University of Texas at El Paso. Admin and Founder at python36.com

3 Comments on Fifa worldcup 2018 Round of 16 flag detection using CNN

  1. where should i give an input image for comparing images in the database(that means the images trained by cnn)

  2. noice tutor mate! one question about model architecture; is there a motiviation to increasing the size of cnn from 64 layers, to 128, to 256; then quartering downto 64, and then go up again to 128?

Leave a Reply

Your email address will not be published.




This site uses Akismet to reduce spam. Learn how your comment data is processed.