Cainvas

Flower Classification Model

Credit: AITS Cainvas Community

Photo by ILLO on Dribbble

Importing Libraries & Dataset

In [1]:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import csv
import imageio
import os, shutil
from tensorflow import keras
In [2]:
!wget https://cainvas-static.s3.amazonaws.com/media/user_data/cainvas-admin/flower_data.zip
--2021-07-13 09:49:27--  https://cainvas-static.s3.amazonaws.com/media/user_data/rishirajak/flower_data.zip
Resolving cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)... 52.219.158.15
Connecting to cainvas-static.s3.amazonaws.com (cainvas-static.s3.amazonaws.com)|52.219.158.15|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 26671531 (25M) [application/zip]
Saving to: ‘flower_data.zip.2’

flower_data.zip.2   100%[===================>]  25.44M  97.5MB/s    in 0.3s    

2021-07-13 09:49:27 (97.5 MB/s) - ‘flower_data.zip.2’ saved [26671531/26671531]

In [3]:
!unzip -qo flower_data.zip.1
In [4]:
label_1 = "flower_data/train/1"
dirs_label_1 =  os.listdir(label_1)
In [5]:
img = 'image_06736.jpg'
label_path = label_1+'/'+img
label_path
Out[5]:
'flower_data/train/1/image_06736.jpg'

Fetch Image from path

In [6]:
def get_image(path):    
    #visualise a flower
    flower = imageio.imread(path)
    #print(flower.shape)
    #plt.figure(figsize=(5,5))
    plt.imshow(flower)
In [7]:
get_image(label_path)

Build Dataframe containing Image abs paths and Labels

In [8]:
#Create Empty Dataframe
df = pd.DataFrame(columns=['image_abs_path','image_labels'])
In [9]:
df
Out[9]:
image_abs_path image_labels
In [10]:
#Flower Name Dictionary
flower_names = {"21": "fire lily", "3": "canterbury bells", "45": "bolero deep blue", "1": "pink primrose", 
 "34": "mexican aster", "27": "prince of wales feathers", "7": "moon orchid", "16": "globe-flower",
 "25": "grape hyacinth", "26": "corn poppy", "79": "toad lily", "39": "siam tulip", "24": "red ginger",
 "67": "spring crocus", "35": "alpine sea holly", "32": "garden phlox", "10": "globe thistle", 
 "6": "tiger lily", "93": "ball moss", "33": "love in the mist", "9": "monkshood", 
 "102": "blackberry lily", "14": "spear thistle", "19": "balloon flower", 
 "100": "blanket flower", "13": "king protea", "49": "oxeye daisy", "15": "yellow iris", 
 "61": "cautleya spicata", "31": "carnation", "64": "silverbush", "68": "bearded iris", 
 "63": "black-eyed susan", "69": "windflower", "62": "japanese anemone", "20": "giant white arum lily",
 "38": "great masterwort", "4": "sweet pea", "86": "tree mallow", "101": "trumpet creeper", 
 "42": "daffodil", "22": "pincushion flower", "2": "hard-leaved pocket orchid", "54": "sunflower", 
 "66": "osteospermum", "70": "tree poppy", "85": "desert-rose", "99": "bromelia", "87": "magnolia", 
 "5": "english marigold", "92": "bee balm", "28": "stemless gentian", "97": "mallow", "57": "gaura",
 "40": "lenten rose", "47": "marigold", "59": "orange dahlia", "48": "buttercup", "55": "pelargonium",
 "36": "ruby-lipped cattleya", "91": "hippeastrum", "29": "artichoke", "71": "gazania", 
 "90": "canna lily", "18": "peruvian lily", "98": "mexican petunia", "8": "bird of paradise", 
 "30": "sweet william", "17": "purple coneflower", "52": "wild pansy", "84": "columbine", 
 "12": "colt's foot", "11": "snapdragon", "96": "camellia", "23": "fritillary", "50": "common dandelion", 
 "44": "poinsettia", "53": "primula", "72": "azalea", "65": "californian poppy", "80": "anthurium",
 "76": "morning glory", "37": "cape flower", "56": "bishop of llandaff", "60": "pink-yellow dahlia", 
 "82": "clematis", "58": "geranium", "75": "thorn apple", "41": "barbeton daisy", "95": "bougainvillea",
 "43": "sword lily", "83": "hibiscus", "78": "lotus lotus", "88": "cyclamen",
 "94": "foxglove", "81": "frangipani", "74": "rose", "89": "watercress", "73": "water lily",
 "46": "wallflower", "77": "passion flower", "51": "petunia"}
In [11]:
#Select Top 10 To be used for Classification
few_flowers = {}
for i in range(1,11):
    few_flowers[str(i)]=flower_names[str(i)]
few_flowers
Out[11]:
{'1': 'pink primrose',
 '2': 'hard-leaved pocket orchid',
 '3': 'canterbury bells',
 '4': 'sweet pea',
 '5': 'english marigold',
 '6': 'tiger lily',
 '7': 'moon orchid',
 '8': 'bird of paradise',
 '9': 'monkshood',
 '10': 'globe thistle'}
In [12]:
few_flowers['5']
Out[12]:
'english marigold'
In [13]:
#Function that can build a dataframe on passing folderpath and number of subfolders.
def getdata(folder_path,num_subfolders):
    flowers = pd.DataFrame(columns=['image_abs_path','image_labels'])
    for label in range(1,num_subfolders+1):
        #print("processing for label: {}".format(label))
        label_i = folder_path+"/"+str(label)
        #read directory
        dirs_label_i =  os.listdir(label_i)
        idx = 0
        for image in dirs_label_i:
            #create a absolute image path
            flower_i = os.path.join(label_i,image)
            #print('Absolute path for image no. {} and label {}: {}'\
                  #.format(idx,label,flower_i))

            #fill the dataframe with path and label
            flowers = flowers.append({'image_abs_path':flower_i,
                            'image_labels':flower_names[str(label)]},
                           ignore_index=True)
            idx += 1
    return flowers
In [14]:
#Create Train Set
path = "flower_data/train"
num_folders = 10

train = getdata(folder_path=path,num_subfolders=num_folders)
In [15]:
train
Out[15]:
image_abs_path image_labels
0 flower_data/train/1/image_06734.jpg pink primrose
1 flower_data/train/1/image_06736.jpg pink primrose
2 flower_data/train/1/image_06741.jpg pink primrose
3 flower_data/train/1/image_06761.jpg pink primrose
4 flower_data/train/1/image_06742.jpg pink primrose
... ... ...
291 flower_data/train/10/image_07114.jpg globe thistle
292 flower_data/train/10/image_07093.jpg globe thistle
293 flower_data/train/10/image_07115.jpg globe thistle
294 flower_data/train/10/image_07108.jpg globe thistle
295 flower_data/train/10/image_07110.jpg globe thistle

296 rows × 2 columns

In [16]:
#Create Valid set
valid_path = "flower_data/valid"

valid = getdata(folder_path=valid_path,num_subfolders=num_folders)
In [17]:
valid
Out[17]:
image_abs_path image_labels
0 flower_data/valid/1/image_06756.jpg pink primrose
1 flower_data/valid/1/image_06755.jpg pink primrose
2 flower_data/valid/1/image_06758.jpg pink primrose
3 flower_data/valid/1/image_06765.jpg pink primrose
4 flower_data/valid/1/image_06769.jpg pink primrose
5 flower_data/valid/1/image_06739.jpg pink primrose
6 flower_data/valid/1/image_06763.jpg pink primrose
7 flower_data/valid/1/image_06749.jpg pink primrose
8 flower_data/valid/2/image_05101.jpg hard-leaved pocket orchid
9 flower_data/valid/2/image_05142.jpg hard-leaved pocket orchid
10 flower_data/valid/2/image_05124.jpg hard-leaved pocket orchid
11 flower_data/valid/2/image_05136.jpg hard-leaved pocket orchid
12 flower_data/valid/2/image_05094.jpg hard-leaved pocket orchid
13 flower_data/valid/2/image_05137.jpg hard-leaved pocket orchid
14 flower_data/valid/3/image_06621.jpg canterbury bells
15 flower_data/valid/3/image_06631.jpg canterbury bells
16 flower_data/valid/4/image_05680.jpg sweet pea
17 flower_data/valid/4/image_05681.jpg sweet pea
18 flower_data/valid/4/image_05638.jpg sweet pea
19 flower_data/valid/4/image_05660.jpg sweet pea
20 flower_data/valid/4/image_05657.jpg sweet pea
21 flower_data/valid/4/image_05677.jpg sweet pea
22 flower_data/valid/5/image_05164.jpg english marigold
23 flower_data/valid/5/image_05199.jpg english marigold
24 flower_data/valid/5/image_05209.jpg english marigold
25 flower_data/valid/5/image_05196.jpg english marigold
26 flower_data/valid/5/image_05168.jpg english marigold
27 flower_data/valid/5/image_05188.jpg english marigold
28 flower_data/valid/5/image_05192.jpg english marigold
29 flower_data/valid/6/image_08105.jpg tiger lily
30 flower_data/valid/7/image_07216.jpg moon orchid
31 flower_data/valid/8/image_03342.jpg bird of paradise
32 flower_data/valid/8/image_03349.jpg bird of paradise
33 flower_data/valid/8/image_03366.jpg bird of paradise
34 flower_data/valid/8/image_03313.jpg bird of paradise
35 flower_data/valid/8/image_03330.jpg bird of paradise
36 flower_data/valid/9/image_06414.jpg monkshood
37 flower_data/valid/9/image_06398.jpg monkshood
38 flower_data/valid/9/image_06420.jpg monkshood
39 flower_data/valid/10/image_07107.jpg globe thistle
40 flower_data/valid/10/image_07094.jpg globe thistle
41 flower_data/valid/10/image_07102.jpg globe thistle
42 flower_data/valid/10/image_07101.jpg globe thistle

Visualise Images

In [18]:
def get_n_images(n,df,label):
    import warnings
    warnings.filterwarnings('ignore')
    train = df[df["image_labels"]==label]
    print(len(train))
    i = 0
    m = n/2
    plt.figure(figsize=(12, 6))
    for path in train['image_abs_path'][0:n]:
        plt.subplot(2,m,i+1)
        get_image(path)
        #plt.title(train['image_labels'][i])
        i += 1
    plt.tight_layout()
    plt.show()
In [19]:
get_n_images(10,train,"english marigold")
27

Check Proportion of flowers

In [20]:
def plotHbar(df,flower_names):
    numbers = []
    flowers = list(flower_names.values())
    for i in flowers:
        numbers.append(len(df[df['image_labels']==i]))
    plt.figure(figsize=(12,20))
    plt.barh(flowers,numbers,align='center',color='green',)
    plt.title("Flower Counts")
    plt.show()
In [21]:
plotHbar(train,few_flowers)
In [22]:
plotHbar(valid,few_flowers)
In [23]:
#just to fetch any flower through label
def get_key(val,flower_names):
    for key, value in flower_names.items():
        if val == value:
            return key,value
In [24]:
sample = ['english marigold','rose']
for flower in sample:
    print(get_key(flower,few_flowers))
('5', 'english marigold')
None

Datapreprocess by using Image Data Generator.

In [25]:
def datapreprocessing(dataframe,bsize):
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    
    train_gen = ImageDataGenerator(rescale=1.0/255)

    train_generator = train_gen.flow_from_dataframe(
        dataframe,
        x_col= dataframe.columns[0],
        y_col=dataframe.columns[1],
        target_size=(150,150),
        batch_size=bsize,
        color_mode="rgb",
        shuffle=True,
        class_mode='categorical')
    
    return train_generator

def datapreprocessing_aug(dataframe,bsize):
    from tensorflow.keras.preprocessing.image import ImageDataGenerator
    
    train_gen = ImageDataGenerator(zoom_range=0.5,
                                   rescale=1.0/255,
                                   horizontal_flip=True,
                                   rotation_range=40,
                                  )

    train_generator = train_gen.flow_from_dataframe(
        dataframe,
        x_col= dataframe.columns[0],
        y_col=dataframe.columns[1],
        target_size=(150,150),
        batch_size=bsize,
        color_mode="rgb",
        shuffle=True,
        class_mode='categorical')
    return train_generator
In [26]:
#Create Sets to be used in model.
train_generated = datapreprocessing(train,bsize=1) 
valid_generated = datapreprocessing(valid,bsize=1)
train_generated_aug = datapreprocessing_aug(train,bsize=1)
valid_generated_aug = datapreprocessing_aug(valid,bsize=1)
Found 296 validated image filenames belonging to 10 classes.
Found 43 validated image filenames belonging to 10 classes.
Found 296 validated image filenames belonging to 10 classes.
Found 43 validated image filenames belonging to 10 classes.

Visualise Images present in Generator

In [27]:
def visualize_gen(train_generator):   
    #Visualising Images Processed
    plt.figure(figsize=(12, 6))
    for i in range(0, 10):
        plt.subplot(2, 5, i+1)
        for X_batch, Y_batch in train_generator:
            image = X_batch[0]        
            plt.axis("off")
            plt.imshow((image*255).astype(np.uint8))
            break
    plt.tight_layout()
    plt.show()
In [28]:
visualize_gen(train_generated)