{"cells":[{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true},"cell_type":"code","source":"# Import required libraries\nimport os\nimport gc\nimport sys\nimport json\nimport random\nfrom pathlib import Path\n\nimport cv2 # CV2 for image manipulation\nimport numpy as np # linear algebra\nimport pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)\n\nimport seaborn as sns\nimport matplotlib.image as mpimg\nfrom matplotlib import pyplot as plt\n\nfrom sklearn.model_selection import StratifiedKFold, KFold","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"max","execution_count":null,"outputs":[]},{"metadata":{"_uuid":"d629ff2d2480ee46fbb7e2d37f6b5fab8052498a","_cell_guid":"79c7e3d0-c299-4dcb-8224-4455121ee9b0","trusted":true},"cell_type":"code","source":"!ls /kaggle/input/imaterialist-fashion-2020-fgvc7/","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"%%time\nwith open('/kaggle/input/imaterialist-fashion-2020-fgvc7/label_descriptions.json', 'r') as file:\n    label_desc = json.load(file)\nsample_sub_df = pd.read_csv('/kaggle/input/imaterialist-fashion-2020-fgvc7/sample_submission.csv')\ntrain_df = pd.read_csv('/kaggle/input/imaterialist-fashion-2020-fgvc7/train.csv')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sample_sub_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'Shape of training dataset: {train_df.shape}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'# of images in training set: {train_df[\"ImageId\"].nunique()}')\nprint(f'# of images in test set: {sample_sub_df[\"ImageId\"].nunique()}')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image size analysis in training dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.DataFrame([train_df['Height'].describe(), train_df['Width'].describe()]).T.loc[['max', 'min', 'mean']]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Height and Width destribution of training images"},{"metadata":{"trusted":true},"cell_type":"code","source":"image_shape_df = train_df.groupby(\"ImageId\")[\"Height\", \"Width\"].first()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(16, 5))\nax1.hist(image_shape_df['Height'], bins=100)\nax1.set_title(\"Height distribution\")\nax2.hist(image_shape_df['Width'], bins=100)\nax2.set_title(\"Width distribution\")\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image with minimum height"},{"metadata":{"trusted":true},"cell_type":"code","source":"x=list(set(train_df[train_df['Height'] == train_df['Height'].min()]['ImageId']))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"len(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (70,7))\nmin_height = list(set(train_df[train_df['Height'] == train_df['Height'].min()]['ImageId']))[0]\nplt.imshow(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{min_height}.jpg'))\nplt.grid(False)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image with maximum height"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (70,7))\nmax_height = list(set(train_df[train_df['Height'] == train_df['Height'].max()]['ImageId']))[0]\nplt.imshow(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{max_height}.jpg'))\nplt.grid(False)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image with minimum width"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (70,7))\nmin_width = list(set(train_df[train_df['Width'] == train_df['Width'].min()]['ImageId']))[0]\nplt.imshow(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{min_width}.jpg'))\nplt.grid(False)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image with maximum width"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (70,7))\nmax_width = list(set(train_df[train_df['Width'] == train_df['Width'].max()]['ImageId']))[0]\nplt.imshow(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{max_width}.jpg'))\nplt.grid(False)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"area_df = pd.DataFrame()\narea_df['ImageId'] = train_df['ImageId']\narea_df['area'] = train_df['Height'] * train_df['Width']\nmin_area = list(set(area_df[area_df['area'] == area_df['area'].min()]['ImageId']))[0]\nmax_area = list(set(area_df[area_df['area'] == area_df['area'].max()]['ImageId']))[0]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image with minimum area"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (70,7))\nplt.imshow(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{min_area}.jpg'))\nplt.grid(False)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Image with maximum area"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (70,7))\nplt.imshow(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{max_area}.jpg'))\nplt.grid(False)\nplt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Details about Classes and Attributes"},{"metadata":{"trusted":true},"cell_type":"code","source":"num_classes = len(label_desc['categories'])\nnum_attributes = len(label_desc['attributes'])\nprint(f'Total # of classes: {num_classes}')\nprint(f'Total # of attributes: {num_attributes}')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"categories_df = pd.DataFrame(label_desc['categories'])\nattributes_df = pd.DataFrame(label_desc['attributes'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"pd.set_option('display.max_rows', 300)\nattributes_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# ## Plotting a few training images without any masks"},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_images(size=12, figsize=(12, 12)):\n    # First get some images to be plotted\n    image_ids = train_df['ImageId'].unique()[:12]\n    images=[]\n    \n    for image in image_ids:\n        images.append(mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{image}.jpg'))\n    \n    # Plot images in groups of 4 images\n    n_groups = 4\n    \n    count = 0\n    for index in range(size // 4):\n        fig, ax = plt.subplots(nrows=2, ncols=2, figsize=figsize)\n        for row in ax:\n            for col in row:\n                col.imshow(images[count])\n                col.axis('off')\n                count += 1\n        plt.show()\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_images()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting a few images with given segments"},{"metadata":{"trusted":true},"cell_type":"code","source":"def create_mask(size):\n    image_ids = train_df['ImageId'].unique()[:size]\n    images_meta=[]\n\n    for image_id in image_ids:\n        img = mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{image_id}.jpg')\n        images_meta.append({\n            'image': img,\n            'shape': img.shape,\n            'encoded_pixels': train_df[train_df['ImageId'] == image_id]['EncodedPixels'],\n            'class_ids':  train_df[train_df['ImageId'] == image_id]['ClassId']\n        })\n\n    masks = []\n    for image in images_meta:\n        shape = image.get('shape')\n        encoded_pixels = list(image.get('encoded_pixels'))\n        class_ids = list(image.get('class_ids'))\n        \n        # Initialize numpy array with shape same as image size\n        height, width = shape[:2]\n        mask = np.zeros((height, width)).reshape(-1)\n        \n        # Iterate over encoded pixels and create mask\n        for segment, (pixel_str, class_id) in enumerate(zip(encoded_pixels, class_ids)):\n            splitted_pixels = list(map(int, pixel_str.split()))\n            pixel_starts = splitted_pixels[::2]\n            run_lengths = splitted_pixels[1::2]\n            assert max(pixel_starts) < mask.shape[0]\n            for pixel_start, run_length in zip(pixel_starts, run_lengths):\n                pixel_start = int(pixel_start) - 1\n                run_length = int(run_length)\n                mask[pixel_start:pixel_start+run_length] = 255 - class_id * 4\n        masks.append(mask.reshape((height, width), order='F'))  # https://stackoverflow.com/questions/45973722/how-does-numpy-reshape-with-order-f-work\n    return masks, images_meta","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_segmented_images(size=12, figsize=(14, 14)):\n    # First create masks from given segments\n    masks, images_meta = create_mask(size)\n    \n    # Plot images in groups of 4 images\n    n_groups = 4\n    count = 0\n    for index in range(size // 4):\n        fig, ax = plt.subplots(nrows=2, ncols=2, figsize=figsize)\n        for row in ax:\n            for col in row:\n                col.imshow(images_meta[count]['image'])\n                col.imshow(masks[count], alpha=0.75)\n                col.axis('off')\n                count += 1\n        plt.show()\n    gc.collect()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_segmented_images()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"max","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Analysing Categories and Attributes"},{"metadata":{"trusted":true},"cell_type":"code","source":"categories_df = pd.DataFrame(label_desc.get('categories'))\nattributes_df = pd.DataFrame(label_desc.get('attributes'))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'# of categories: {len(categories_df)}')\nprint(f'# of attributes: {len(attributes_df)}')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"So there are 46 categories (classes) and 294 attributes. Let's see some of the categories and attributes"},{"metadata":{"trusted":true},"cell_type":"code","source":"categories_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"attributes_df.head()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"category_map, attribute_map = {}, {}\nfor cat in label_desc.get('categories'):\n    category_map[cat.get('id')] = cat.get('name')\nfor attr in label_desc.get('attributes'):\n    attribute_map[attr.get('id')] = attr.get('name')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"label_desc['categories']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#seperated by a comma\n\n\ndef extract(x):\n    i=0\n    num=\"\"\n    extract_list=[]\n\n    while(i<=len(x)):\n        if(i==len(x)):\n            extract_list.append(num)\n            break\n        if(x[i]!=','):\n            num=num+x[i]\n            i=i+1\n        else:\n            extract_list.append(num)\n            i=i+1\n            num=\"\"\n    return extract_list\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"raw","source":"\nlist1=extract(train_df.loc[i,'AttributesIds'])"},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"attributes_description_list=[]\n\nfor i in range(0,train_df.shape[0]):\n    attributes_description_list.append(extract (str(train_df.loc[i,'AttributesIds'])))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"attributes_description_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['Attributes_Values']=attributes_description_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"attributes_list=[]\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"label_desc['attributes'][295-47]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"attributes_sub_list=[]\nattributes_list=[]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in range(0, train_df.shape[0]):\n    for j in train_df.loc[i,'Attributes_Values']:\n\n        if j=='nan':\n            attributes_sub_list.append('nan')\n            \n        elif int(j)>234:\n            attributes_sub_list.append(label_desc['attributes'][int(j)-47]['name'])\n        else:\n            attributes_sub_list.append(label_desc['attributes'][int(j)]['name'])\n    attributes_list.append(attributes_sub_list)\n    attributes_sub_list=[]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"attributes_list\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"We are trying to see the variation of attributes per class ID"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['train_attributes_value']=attributes_list","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_cat_2=train_df[train_df['ClassId']==0]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_cat_2","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"**So we are trying to see for a particular class what is the various attributes value**"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_cat_2.iloc[0]['train_attributes_value']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"all_attrubutes_class0_list=[]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Basically I am checking how many unique attributes are there in a class"},{"metadata":{"trusted":true},"cell_type":"code","source":"\nfor i in range(0,train_df_cat_2.shape[0]):\n#     print(len(train_df_cat_2.iloc[i]['train_attributes_value']))\n    for j in train_df_cat_2.iloc[i]['train_attributes_value']:\n        all_attrubutes_class0_list.append(j)\n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x=set(all_attrubutes_class0_list)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"x=list(x)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"for i in x:\n    print(i)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class_attribute = np.zeros((47,341),dtype='int64')\nclz_attrid2idx = [[] for _ in range(46)]\nclass_attribute.shape","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"For all the classe what is the distribution"},{"metadata":{"trusted":true},"cell_type":"code","source":"for c,i in zip(train_df.ClassId,train_df.Attributes_Values):\n    for a in i:\n         if a!='nan':\n             class_attribute[int(c),int(a)] = int(1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"clz_attr_num = class_attribute.sum(axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"clz_attr_num","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"label_desc['attributes'][293]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def rle_to_mask(rle_string,height,width):\n    rows, cols = height, width\n    if rle_string == -1:\n        return np.zeros((height, width))\n    else:\n        rleNumbers = [int(numstring) for numstring in rle_string.split(' ')]\n        rlePairs = np.array(rleNumbers).reshape(-1,2)\n        img = np.zeros(rows*cols,dtype=np.uint8)\n        for index,length in rlePairs:\n            index -= 1\n            img[index:index+length] = 255\n        img = img.reshape(cols,rows)\n        img = img.T\n        return img","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"df = train_df.iloc[1]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"mask = rle_to_mask(df.EncodedPixels,df.Height,df.Width)\nimag = cv2.imread(\"../input/imaterialist-fashion-2020-fgvc7/train/\"+str(df.ImageId)+\".jpg\")\nimag[mask==0] = 255","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"imag","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"where = np.where(imag < 255)\nif len(where[0]) > 0 and len(where[1]) > 0:\n    y1= min(where[0])\n    y2=max(where[0])\n    x1=min(where[1])\n    x2=max(where[1])\n    \nplt.imshow(imag[y1:y2,x1:x2])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"import os\nimport numpy as np\nimport torch\nfrom PIL import Image\n\n\nclass PennFudanDataset(object):\n    def __init__(self, root, transforms):\n        self.root = root\n        self.transforms = transforms\n        # load all image files, sorting them to\n        # ensure that they are aligned\n        self.imgs = list(sorted(os.listdir(os.path.join(root, \"PNGImages\"))))\n        self.masks = list(sorted(os.listdir(os.path.join(root, \"PedMasks\"))))\n\n    def __getitem__(self, idx):\n        # load images ad masks\n        img_path = os.path.join(self.root, \"PNGImages\", self.imgs[idx])\n        mask_path = os.path.join(self.root, \"PedMasks\", self.masks[idx])\n        img = Image.open(img_path).convert(\"RGB\")\n        # note that we haven't converted the mask to RGB,\n        # because each color corresponds to a different instance\n        # with 0 being background\n        mask = Image.open(mask_path)\n        # convert the PIL Image into a numpy array\n        mask = np.array(mask)\n        # instances are encoded as different colors\n        obj_ids = np.unique(mask)\n        # first id is the background, so remove it\n        obj_ids = obj_ids[1:]\n\n        # split the color-encoded mask into a set\n        # of binary masks\n        masks = mask == obj_ids[:, None, None]\n\n        # get bounding box coordinates for each mask\n        num_objs = len(obj_ids)\n        boxes = []\n        for i in range(num_objs):\n            pos = np.where(masks[i])\n            xmin = np.min(pos[1])\n            xmax = np.max(pos[1])\n            ymin = np.min(pos[0])\n            ymax = np.max(pos[0])\n            boxes.append([xmin, ymin, xmax, ymax])\n\n        # convert everything into a torch.Tensor\n        boxes = torch.as_tensor(boxes, dtype=torch.float32)\n        # there is only one class\n        labels = torch.ones((num_objs,), dtype=torch.int64)\n        masks = torch.as_tensor(masks, dtype=torch.uint8)\n\n        image_id = torch.tensor([idx])\n        area = (boxes[:, 3] - boxes[:, 1]) * (boxes[:, 2] - boxes[:, 0])\n        # suppose all instances are not crowd\n        iscrowd = torch.zeros((num_objs,), dtype=torch.int64)\n\n        target = {}\n        target[\"boxes\"] = boxes\n        target[\"labels\"] = labels\n        target[\"masks\"] = masks\n        target[\"image_id\"] = image_id\n        target[\"area\"] = area\n        target[\"iscrowd\"] = iscrowd\n\n        if self.transforms is not None:\n            img, target = self.transforms(img, target)\n\n        return img, target\n\n    def __len__(self):\n        return len(self.imgs)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['ClassId'] = train_df['ClassId'].map(category_map)\ntrain_df['ClassId'] = train_df['ClassId'].astype('category')","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Let's see the class wise distribution of segments in training dataset"},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set(style='darkgrid')\nfig, ax = plt.subplots(figsize = (10,10))\nsns.countplot(y='ClassId',data=train_df , ax=ax, order = train_df['ClassId'].value_counts().index)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"### Now let's visualize an image with all its classes and attributes"},{"metadata":{"trusted":true},"cell_type":"code","source":"IMAGE_ID = '000b3ec2c6eaffb491a5abb72c2e3e26'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Get the an image id given in the training set for visualization\nvis_df = train_df[train_df['ImageId'] == IMAGE_ID]\nvis_df['ClassId'] = vis_df['ClassId'].cat.codes\nvis_df = vis_df.reset_index(drop=True)\nvis_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"From above table, this image has 8 segmentes and a few attributes. Let's visualize all of them!"},{"metadata":{},"cell_type":"markdown","source":"## Let's first the plot the plain image"},{"metadata":{"trusted":true},"cell_type":"code","source":"plt.figure(figsize = (110,11))\nimage = mpimg.imread(f'/kaggle/input/imaterialist-fashion-2020-fgvc7/train/{IMAGE_ID}.jpg')\nplt.grid(False)\nplt.imshow(image)\nplt.plot()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df[train_df['ImageId'] == IMAGE_ID]","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Now let's plot each segment in a separate image"},{"metadata":{"trusted":true},"cell_type":"code","source":"segments = list(vis_df['EncodedPixels'])\nclass_ids = list(vis_df['ClassId'])\nmasks = []\nfor segment, class_id in zip(segments, class_ids):\n    \n    height = vis_df['Height'][0]\n    width = vis_df['Width'][0]\n    # Initialize empty mask\n    mask = np.zeros((height, width)).reshape(-1)\n    \n    # Iterate over encoded pixels and create mask\n    splitted_pixels = list(map(int, segment.split()))\n    pixel_starts = splitted_pixels[::2]\n    run_lengths = splitted_pixels[1::2]\n    assert max(pixel_starts) < mask.shape[0]\n    for pixel_start, run_length in zip(pixel_starts, run_lengths):\n        pixel_start = int(pixel_start) - 1\n        run_length = int(run_length)\n        mask[pixel_start:pixel_start+run_length] = 255 - class_id * 4\n\n    mask = mask.reshape((height, width), order='F')\n    masks.append(mask)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def plot_individual_segment(*masks, image, figsize=(110, 11)):\n    plt.figure(figsize = figsize)\n    plt.imshow(image)\n    for mask in masks:\n        plt.imshow(mask, alpha=0.6)\n    plt.axis('off')\n    plt.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 1st Segment: ClassId: \"Shoe\" and no attributes "},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[0], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 2nd Segment: ClassId: \"shoe\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[1], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 3rd Segment with ClassId: \"pants\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[2], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"* ## Plotting 4th Segment with ClassId: \"top, t-shirt, sweatshirt\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[3], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 5th Segment with ClassId: \"pocket\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[4], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 6th Segment with ClassId: \"sleeve\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[5], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 7th Segment with ClassId: \"sleeve\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[6], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Plotting 8th segment with Class \"neckline\""},{"metadata":{"trusted":true},"cell_type":"code","source":"plot_individual_segment(masks[6], image=image)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Some of the segments have no attributes. Let's check how many such segment exists in training dataset."},{"metadata":{"trusted":true},"cell_type":"code","source":"print(f'Segments that do not have attributes: {train_df[\"AttributesIds\"].isna().sum()/len(train_df) * 100} %')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['ClassId'] = train_df['ClassId'].cat.codes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_classID_2=train_df[train_df['ClassId']==2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_classID_2=train_df_classID_2.dropna(subset=['AttributesIds'])","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_classID_2['AttributesIds']=train_df_classID_2['AttributesIds'].astype('int64')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_classID_2=train_df[train_df['ClassId']==2]","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"\nfor i in range (2,3):\n    if train_df['AttributesIds'][i]=='163':\n        print(\"hello\")\n        ","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df_classID_2.loc[75:,'AttributesIds']","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"sns.set(style='darkgrid')\nfig, ax = plt.subplots(figsize = (10,10))\nsns.countplot(y='AttributesIds',data=train_df_classID_2, ax=ax, order = train_df_classID_2['AttributesIds'].value_counts().index)\nfig.show()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Matching class id with attributes ID to understand possible attributes(text) "},{"metadata":{"trusted":true},"cell_type":"code","source":"label_desc['attributes']\n","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's check of missing values in training dataset for columns other than \"AttributeIds\""},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df[['ImageId', 'EncodedPixels', 'Height', 'Width', 'ClassId']].isna().sum()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Data Preparation and modeling"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df['ClassId'] = train_df['ClassId'].cat.codes","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"1 Drop attributeIds for simplicity for now. TODO: Need to take this in consideration once the basic model is ready with ClassId"},{"metadata":{"trusted":true},"cell_type":"code","source":"train_df = train_df.drop('AttributesIds', axis=1)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"image_df = train_df.groupby('ImageId')['EncodedPixels', 'ClassId'].agg(lambda x: list(x))\nsize_df = train_df.groupby('ImageId')['Height', 'Width'].mean()\nimage_df = image_df.join(size_df, on='ImageId')\n\nprint(\"Total images: \", len(image_df))\nimage_df.head()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Reference: https://github.com/matterport/Mask_RCNN/blob/master/samples/shapes/train_shapes.ipynb"},{"metadata":{"trusted":true},"cell_type":"code","source":"# !pip install tensorflow==1.15","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# import os\n# from pathlib import Path\n# !git clone https://www.github.com/matterport/Mask_RCNN.git\n# os.chdir('Mask_RCNN')\n\n# !rm -rf .git # to prevent an error when the kernel is committed\n# !rm -rf images assets # to prevent displaying images at the bottom of a kernel","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# !wget --quiet https://github.com/matterport/Mask_RCNN/releases/download/v2.0/mask_rcnn_coco.h5\n# !ls -lh mask_rcnn_coco.h5\n\n# COCO_WEIGHTS_PATH = 'mask_rcnn_coco.h5'","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"DATA_DIR = Path('/kaggle/input/imaterialist-fashion-2020-fgvc7')\nROOT_DIR = Path('/kaggle/working')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"from mrcnn.config import Config\nfrom mrcnn import utils\nimport mrcnn.model as modellib\nfrom mrcnn import visualize\nfrom mrcnn.model import log","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class FashionConfig(Config):\n    \"\"\"Configuration for training on the toy shapes dataset.\n    Derives from the base Config class and overrides values specific\n    to the toy shapes dataset.\n    \"\"\"\n    # Give the configuration a recognizable name\n    NAME = \"class\"\n\n    # Train on 1 GPU and 8 images per GPU. We can put multiple images on each\n    # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).\n    GPU_COUNT = 1\n    IMAGES_PER_GPU = 8\n\n    # Number of classes (including background)\n    NUM_CLASSES = 1 + len(categories_df)  # background + 46 classes\n\n    # Use small images for faster training. Set the limits of the small side\n    # the large side, and that determines the image shape.\n    IMAGE_MIN_DIM = 256\n    IMAGE_MAX_DIM = 256\n\n    # Use smaller anchors because our image and objects are small\n    RPN_ANCHOR_SCALES = (8, 16, 32, 64, 128)  # anchor side in pixels\n\n    # Reduce training ROIs per image because the images are small and have\n    # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.\n    TRAIN_ROIS_PER_IMAGE = 32\n\n    # Use a small epoch since the data is simple\n    STEPS_PER_EPOCH = 100\n\n    # use small validation steps since the epoch is small\n    VALIDATION_STEPS = 5\n    \nconfig = FashionConfig()\nconfig.display()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"class FashionDataset(utils.Dataset):\n    def __init__(self, df):\n        super().__init__(self)\n        \n        self.IMAGE_SIZE = 256\n        \n        # Add classes\n        for cat in label_desc['categories']:\n            self.add_class('fashion', cat.get('id'), cat.get('name'))\n        \n        # Add images\n        for i, row in df.iterrows():\n            self.add_image(\"fashion\", \n                           image_id=row.name, \n                           path=str(DATA_DIR/'train'/row.name) + '.jpg', \n                           labels=row['ClassId'],\n                           annotations=row['EncodedPixels'], \n                           height=row['Height'], width=row['Width'])\n            \n    def _resize_image(self, image_path):\n        print(image_path)\n        img = cv2.imread(image_path)\n        img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n        img = cv2.resize(img, (self.IMAGE_SIZE, self.IMAGE_SIZE), interpolation=cv2.INTER_AREA)  \n        return img\n        \n    def load_image(self, image_id):\n        return self._resize_image(self.image_info[image_id]['path'])\n    \n    def image_reference(self, image_id):\n        info = self.image_info[image_id]\n        return info['path'], [x for x in info['labels']]\n    \n    def load_mask(self, image_id):\n        info = self.image_info[image_id]\n                \n        mask = np.zeros((self.IMAGE_SIZE, self.IMAGE_SIZE, len(info['annotations'])), dtype=np.uint8)\n        labels = []\n        \n        for m, (annotation, label) in enumerate(zip(info['annotations'], info['labels'])):\n            sub_mask = np.full(info['height']*info['width'], 0, dtype=np.uint8)\n            annotation = [int(x) for x in annotation.split(' ')]\n            \n            for i, start_pixel in enumerate(annotation[::2]):\n                sub_mask[start_pixel: start_pixel+annotation[2*i+1]] = 1\n\n            sub_mask = sub_mask.reshape((info['height'], info['width']), order='F')\n            sub_mask = cv2.resize(sub_mask, (self.IMAGE_SIZE, self.IMAGE_SIZE), interpolation=cv2.INTER_NEAREST)\n            \n            mask[:, :, m] = sub_mask\n            labels.append(int(label)+1)\n            \n        return mask, np.array(labels)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"dataset = FashionDataset(image_df)\ndataset.prepare()\n\nfor i in range(6):\n    image_id = random.choice(dataset.image_ids)\n    print(dataset.image_reference(image_id))\n    \n    image = dataset.load_image(image_id)\n    mask, class_ids = dataset.load_mask(image_id)\n    visualize.display_top_masks(image, mask, class_ids, dataset.class_names, limit=4)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# This code partially supports k-fold training, \n# you can specify the fold to train and the total number of folds here\nFOLD = 0\nN_FOLDS = 5\n\nkf = KFold(n_splits=N_FOLDS, random_state=42, shuffle=True)\nsplits = kf.split(image_df) # ideally, this should be multilabel stratification\n\ndef get_fold():    \n    for i, (train_index, valid_index) in enumerate(splits):\n        if i == FOLD:\n            return image_df.iloc[train_index], image_df.iloc[valid_index]\n        \ntrain_df, valid_df = get_fold()\n\ntrain_dataset = FashionDataset(train_df)\ntrain_dataset.prepare()\n\nvalid_dataset = FashionDataset(valid_df)\nvalid_dataset.prepare()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"## Training"},{"metadata":{"trusted":true},"cell_type":"code","source":"# Note that any hyperparameters here, such as LR, may still not be optimal\nLR = 1e-4\nEPOCHS = [2, 6, 8]\n\nimport warnings \nwarnings.filterwarnings(\"ignore\")","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Let's load the COCO dataset weights to our Model."},{"metadata":{"trusted":true},"cell_type":"code","source":"model = modellib.MaskRCNN(mode='training', config=config, model_dir=ROOT_DIR)\n\n# Load weights trained on MS COCO, but skip layers that\n# are different due to the different number of classes\n# See README for instructions to download the COCO weights\nmodel.load_weights(COCO_MODEL_PATH, by_name=True,\n                   exclude=[\"mrcnn_class_logits\", \"mrcnn_bbox_fc\", \n                            \"mrcnn_bbox\", \"mrcnn_mask\"])","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# In Progress... Stay Tuned!"}],"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"pygments_lexer":"ipython3","nbconvert_exporter":"python","version":"3.6.4","file_extension":".py","codemirror_mode":{"name":"ipython","version":3},"name":"python","mimetype":"text/x-python"}},"nbformat":4,"nbformat_minor":4}