{"cells":[{"metadata":{},"cell_type":"markdown","source":"This is segmentation problem and multiclass labeling problem.\nHere we will try to segment the images."},{"metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"_kg_hide-input":true},"cell_type":"code","source":"# import required packages\nimport numpy as np\nimport pandas as pd\n\nfrom pathlib import Path\nfrom fastai.vision import *\nfrom fastai.callbacks.hooks import *\nfrom fastai.utils.mem import *\n\nfrom itertools import groupby\nfrom progressbar import ProgressBar\nimport cv2\nimport os\nimport json\nimport torchvision\n\ncategory_num = 46 + 1\n\nclass ImageMask():\n    masks = {}\n    \n    def make_mask_img(self, segment_df):\n        seg_width = segment_df.iloc[0].Width\n        seg_height = segment_df.iloc[0].Height\n        \n        seg_img = np.copy(self.masks.get((seg_width, seg_height)))\n        try:\n            if not seg_img:\n                seg_img = np.full(seg_width*seg_height, category_num-1, dtype=np.int32)\n                self.masks[(seg_width, seg_height)] = np.copy(seg_img)\n        except:\n            # seg_img exists\n            pass\n        for encoded_pixels, class_id in zip(segment_df[\"EncodedPixels\"].values, segment_df[\"ClassId\"].values):\n            pixel_list = list(map(int, encoded_pixels.split(\" \")))\n            for i in range(0, len(pixel_list), 2):\n                start_index = pixel_list[i] - 1\n                index_len = pixel_list[i+1] - 1\n                if int(class_id.split(\"_\")[0]) < category_num - 1:\n                    seg_img[start_index:start_index+index_len] = int(class_id.split(\"_\")[0])\n        seg_img = seg_img.reshape((seg_height, seg_width), order='F')\n        return seg_img\n        \n\ndef create_label(images, path_lbl):\n    \"\"\"\n    img_name = \"53d0ee82b3b7200b3cec8c3c1becead9.jpg\"\n    img_df = df[df.ImageId == img_name]\n    img_mask = ImageMask()\n    mask = img_mask.make_mask_img(img_df)\n    \"\"\"\n    img_mask = ImageMask()\n\n    print(\"Start creating label\")\n    for i,img in enumerate(images):\n        fname = path_lbl.joinpath(os.path.splitext(img)[0] + '_P.png').as_posix()\n        if os.path.isfile(fname): # skip\n            continue\n        img_df = df[df.ImageId == img]\n        mask = img_mask.make_mask_img(img_df)\n        img_mask_3_chn = np.dstack((mask, mask, mask))\n        cv2.imwrite(fname, img_mask_3_chn)\n        if i % 40 ==0 : print(i, end=\" \")\n    print(\"Finish creating label\")\n            \n        \ndef get_predictions(path_test, learn, size):\n    # predicts = get_predictions(path_test, learn)\n    learn.model.cuda()\n    files = list(path_test.glob(\"**/*.jpg\"))    #<---------- HERE\n    test_count = len(files)\n    results = {}\n    for i, img in enumerate(files):\n        results[img.stem] = learn.predict(open_image(img).resize(size))[1].data.numpy().flatten()\n    \n        if i%20==0:\n            print(\"\\r{}/{}\".format(i, test_count), end=\"\")\n    return results       \n        \n\n# https://www.kaggle.com/go1dfish/u-net-baseline-by-pytorch-in-fgvc6-resize\ndef encode(input_string):\n    return [(len(list(g)), k) for k,g in groupby(input_string)]\n\ndef run_length(label_vec):\n    encode_list = encode(label_vec)\n    index = 1\n    class_dict = {}\n    for i in encode_list:\n        if i[1] != category_num-1:\n            if i[1] not in class_dict.keys():\n                class_dict[i[1]] = []\n            class_dict[i[1]] = class_dict[i[1]] + [index, i[0]]\n        index += i[0]\n    return class_dict\n\n    \ndef get_submission_df(predicts):\n    sub_list = []\n    for img_name, mask_prob in predicts.items():\n        class_dict = run_length(mask_prob)\n        if len(class_dict) == 0:\n            sub_list.append([img_name, \"1 1\", 1])\n        else:\n            for key, val in class_dict.items():\n                sub_list.append([img_name + \".jpg\", \" \".join(map(str, val)), key])\n        # sub_list\n    jdf = pd.DataFrame(sub_list, columns=['ImageId','EncodedPixels', 'ClassId'])\n    return jdf\n        \n        \ndef test_mask_to_img(segment_df):\n    \"\"\"\n    plt.imshow(test_mask_to_img(jdf))\n    \"\"\"\n    seg_img = np.full(size*size, category_num-1, dtype=np.int32)\n    for encoded_pixels, class_id in zip(segment_df[\"EncodedPixels\"].values, segment_df[\"ClassId\"].values):\n        encoded_pixels= str(encoded_pixels)\n        class_id = str(class_id)\n        \n        pixel_list = list(map(int, encoded_pixels.split(\" \")))\n        for i in range(0, len(pixel_list), 2):\n            start_index = pixel_list[i] - 1\n            index_len = pixel_list[i+1] - 1\n            if int(class_id.split(\"_\")[0]) < category_num - 1:\n                seg_img[start_index:start_index+index_len] = int(class_id.split(\"_\")[0])\n        seg_img = seg_img.reshape((size, size), order='F')\n    return seg_img\n    \n","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"The `../input/imaterialist2019labels/labels/labels/` contains images created offline and uploaded to Kaggle.\nThis code can be used to speedup the label creation. It took close to 8 hrs. \nThe python process used to hang after ~3000 images. I have to monitor the process and restart again.\n```\nimg_mask = ImageMask()\ndef create_label(img):\n    fname = path_lbl.joinpath(os.path.splitext(img)[0] + '_P.png').as_posix()\n    #if os.path.isfile(fname): # skip\n    #    return\n    img_df = df[df.ImageId == img]\n    mask = img_mask.make_mask_img(img_df)\n    img_mask_3_chn = np.dstack((mask, mask, mask))\n    cv2.imwrite(fname, img_mask_3_chn)\n    print(\".\", end=\" \")\n\n\npath = Path('/home/jupyter/comp/')\npath_lbl = path/'labels'\npath_img = path/'train'\ndf = pd.read_csv(path/'train.csv')\nimages = df.ImageId.unique()\n\n\nwith Pool(processes=5) as pool:\n    pool.map(create_label, images)\n```"},{"metadata":{"trusted":true},"cell_type":"code","source":"path = Path(\"../input/imaterialist-fashion-2019-FGVC6/\")\npath_img = path/'train'\npath_lbl = Path(\"../input/imaterialist2019labels/labels/labels/\")\npath_test = path/'test'\n# if  not os.path.isdir(path_lbl):\n#     os.makedirs(path_lbl)\n\n# create a folder for the mask images\nif  not os.path.isdir(path_lbl):\n    os.makedirs(path_lbl)\n    \n# category is in util\nsize = 224               # <---------------- HERE\n\n# train dataframe\ndf = pd.read_csv(path/'train.csv')\n\n# get and show categories\nwith open(path/\"label_descriptions.json\") as f:\n    label_descriptions = json.load(f)\n\nlabel_names = [x['name'] for x in label_descriptions['categories']]\nprint(label_names)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"img_name = \"53d0ee82b3b7200b3cec8c3c1becead9.jpg\"\n\nimg_df = df[df.ImageId == img_name]\nimg_mask = ImageMask()\nmask = img_mask.make_mask_img(img_df)\n\n# img_mask = make_mask_img(img_df)\nplt.imshow(mask)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"images = df.ImageId.unique()[:10000]        # <---------------- HERE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# Already created\n# create_label(images, path_lbl)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Create Learner"},{"metadata":{"trusted":true},"cell_type":"code","source":"get_y_fn = lambda x: path_lbl/f'{Path(x).stem}_P.png'\n\nbs = 16\n#classes = label_names\nclasses = list(range(category_num))\nwd = 1e-2\n\nimages_df = pd.DataFrame(images)\n\n\nsrc = (SegmentationItemList.from_df(images_df, path, folder='train')\n       .split_by_rand_pct()\n       .label_from_func(get_y_fn, classes=classes)\n       .add_test_folder('test')\n     )","execution_count":1,"outputs":[{"output_type":"error","ename":"NameError","evalue":"name 'category_num' is not defined","traceback":["\u001b[0;31m---------------------------------------------------------------------------\u001b[0m","\u001b[0;31mNameError\u001b[0m                                 Traceback (most recent call last)","\u001b[0;32m<ipython-input-1-fcd92f4ecf0c>\u001b[0m in \u001b[0;36m<module>\u001b[0;34m()\u001b[0m\n\u001b[1;32m      3\u001b[0m \u001b[0mbs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m16\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      4\u001b[0m \u001b[0;31m#classes = label_names\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mclasses\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcategory_num\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m      6\u001b[0m \u001b[0mwd\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m1e-2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m      7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n","\u001b[0;31mNameError\u001b[0m: name 'category_num' is not defined"]}]},{"metadata":{"trusted":true},"cell_type":"code","source":"\ndef no_tfms(self, x, size, resize_method): return x\nEmptyLabel.apply_tfms = no_tfms\n\ndata = (src.transform(tfms=get_transforms(), size=size, resize_method=ResizeMethod.SQUISH, tfm_y=True)\n       .databunch(bs=bs,num_workers=4)\n        .normalize(imagenet_stats)\n       )","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"def acc_fashion(input, target):\n    target = target.squeeze(1)\n    mask = target != (category_num - 1)\n    return (input.argmax(dim=1)[mask]==target[mask]).float().mean()\n\nlearn = unet_learner(data, models.resnet34, metrics=acc_fashion, wd=wd, model_dir=\"/kaggle/working/models\")\n\n# look at a batch\ndata.show_batch(3, figsize=(10,10))","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# find lr\n\n# lr_find(learn)\n# learn.recorder.plot()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"Commented above line. For 224 1e-4 is good lr. After 5 cycle no major improvements."},{"metadata":{"trusted":true},"cell_type":"code","source":"lr=1e-4\nlearn.fit_one_cycle(5, slice(lr), pct_start=0.9) #<------------ HERE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"#  take a look at some results\nlearn.show_results()","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# unfreeze earlier weights\n# decrease the learning rate\n# train for 10 more cycles unfrozen\n\nlearn.unfreeze()\nlrs = slice(lr/400,lr/4)\n\nlearn.fit_one_cycle(5, lrs, pct_start=0.8)          #<------------ HERE","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"# more results\n\nlearn.show_results()","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# Do prediction & get encoded result ready for submission\n"},{"metadata":{"trusted":true},"cell_type":"code","source":"# check can we save model\nlearn.save('stage-1-224')","execution_count":null,"outputs":[]},{"metadata":{"trusted":true,"_kg_hide-output":true,"collapsed":true},"cell_type":"code","source":"predicts = get_predictions(path_test, learn, size)\nlen(predicts)","execution_count":null,"outputs":[]},{"metadata":{"trusted":true},"cell_type":"code","source":"submission_df = get_submission_df(predicts)\nsubmission_df.to_csv(\"./submission.csv\", index=False)","execution_count":null,"outputs":[]},{"metadata":{},"cell_type":"markdown","source":"# DONE"},{"metadata":{"trusted":true},"cell_type":"code","source":"test_df = df[df.ImageId==\"53d0ee82b3b7200b3cec8c3c1becead9.jpg\"]\npred = learn.predict(open_image((path_img/img_name).as_posix()).resize(size))\npred[0]","execution_count":null,"outputs":[]}],"metadata":{"kernelspec":{"display_name":"Python 3","language":"python","name":"python3"},"language_info":{"name":"python","version":"3.6.4","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"}},"nbformat":4,"nbformat_minor":1}