{"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_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"## Create cutmix augmentation","metadata":{}},{"cell_type":"markdown","source":"### Finally we get such images:","metadata":{}},{"cell_type":"code","source":"import cv2\nimport matplotlib.pyplot as plt\n\n\nexample1 = cv2.imread(\"../input/cutmix-examples/1c60d7a7695d_c1a8710f13a5_b2a7f3d06a50_caa06f9a4057_cutmix.png\", cv2.IMREAD_COLOR)\nexample2 = cv2.imread(\"../input/cutmix-examples/3b70c0fef171_6b2f2fab222f_a28407ce196e_559904fcd4a2_cutmix.png\", cv2.IMREAD_COLOR)\n\nfig, ax = plt.subplots(1,2, figsize=(17, 17))\nax[0].imshow(example1)\nax[1].imshow(example2)\nfig.tight_layout()","metadata":{"_kg_hide-input":true,"_kg_hide-output":false,"execution":{"iopub.status.busy":"2021-12-10T10:29:41.879587Z","iopub.execute_input":"2021-12-10T10:29:41.880317Z","iopub.status.idle":"2021-12-10T10:29:42.643778Z","shell.execute_reply.started":"2021-12-10T10:29:41.880275Z","shell.execute_reply":"2021-12-10T10:29:42.643045Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### You can mix different classes or cutmix only one class. ","metadata":{}},{"cell_type":"code","source":"# imports\nfrom typing import List\n\nimport pandas\nimport pandas as pd\nimport random\nimport numpy as np\nimport cv2\nimport os\nimport torch\nimport shutil\n\nfrom pathlib import Path\nfrom random import shuffle\n\nfrom pandas import DataFrame\nfrom tqdm import tqdm","metadata":{"execution":{"iopub.status.busy":"2021-12-10T10:29:42.645417Z","iopub.execute_input":"2021-12-10T10:29:42.646208Z","iopub.status.idle":"2021-12-10T10:29:42.651562Z","shell.execute_reply.started":"2021-12-10T10:29:42.646158Z","shell.execute_reply":"2021-12-10T10:29:42.650718Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# constants\nIMAGE_WIDTH = 704\nIMAGE_HEIGHT = 520\nCLASSES = ['astro', 'cort', 'shsy5y']\nMIN_SIZES = [150, 75, 75]","metadata":{"execution":{"iopub.status.busy":"2021-12-10T10:29:42.652872Z","iopub.execute_input":"2021-12-10T10:29:42.653639Z","iopub.status.idle":"2021-12-10T10:29:42.66785Z","shell.execute_reply.started":"2021-12-10T10:29:42.653593Z","shell.execute_reply":"2021-12-10T10:29:42.66706Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# helping functions\ndef get_all_files_in_folder(folder: Path, types: List) -> List[Path]:\n    files_grabbed = []\n    for t in types:\n        files_grabbed.extend(folder.rglob(t))\n    files_grabbed = sorted(files_grabbed, key=lambda x: x)\n    return files_grabbed\n\n\ndef seed_everything(seed: int) -> None:\n    random.seed(seed)\n    os.environ['PYTHONHASHSEED'] = str(seed)\n    np.random.seed(seed)\n    torch.manual_seed(seed)\n    torch.cuda.manual_seed(seed)\n    torch.backends.cudnn.deterministic = True\n    torch.backends.cudnn.benchmark = True\n\n\ndef recreate_folder(path):\n    output_dir = Path(path)\n    if output_dir.exists() and output_dir.is_dir():\n        shutil.rmtree(output_dir)\n    Path(output_dir).mkdir(parents=True, exist_ok=True)\n    \n# get points for every part (4 parts)\ndef get_points_for_parts():\n    result = []\n    all_points = list(range(IMAGE_WIDTH * IMAGE_HEIGHT))\n\n    start_points = [0, IMAGE_WIDTH // 2, len(all_points) // 2, len(all_points) // 2 + IMAGE_WIDTH // 2]\n    lenghts = [len(all_points) // 2, len(all_points) // 2, len(all_points), len(all_points)]\n\n    for (s, lenght) in zip(start_points, lenghts):\n        points = []\n        while s < lenght:\n            for j in range(IMAGE_WIDTH // 2):\n                points.append(s)\n                s += 1\n\n            s += IMAGE_WIDTH // 2\n        result.append(points)\n\n    return result","metadata":{"execution":{"iopub.status.busy":"2021-12-10T10:29:42.669232Z","iopub.execute_input":"2021-12-10T10:29:42.669982Z","iopub.status.idle":"2021-12-10T10:29:42.683776Z","shell.execute_reply.started":"2021-12-10T10:29:42.669919Z","shell.execute_reply":"2021-12-10T10:29:42.683082Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def calculate_mask_for_current_part(annot, points, label_index) -> str:\n    start_points = [int(x) for x in annot.split()[::2]]\n    lenghts = [int(x) for x in annot.split()[1::2]]\n\n    annot_result = \"\"\n    size = 0\n\n    for i, start_point in enumerate(start_points):\n        mask_line = []\n        for j in range(lenghts[i]):\n            mask_line.append(start_point + j)\n\n        mask_line = sorted(list(set(mask_line) & set(points)))\n\n        if mask_line:\n            annot_result += str(mask_line[0]) + \" \" + str(len(mask_line)) + \" \"\n            size += len(mask_line)\n\n    annot_result = annot_result[:-1]\n\n    if size < MIN_SIZES[label_index]:\n        annot_result = \"\"\n\n    # delete samples on borders\n    # if annot_result != \"\" and annot_result != annot:\n    #     annot_result = \"\"\n\n    return annot_result","metadata":{"execution":{"iopub.status.busy":"2021-12-10T10:29:42.686877Z","iopub.execute_input":"2021-12-10T10:29:42.687072Z","iopub.status.idle":"2021-12-10T10:29:42.696848Z","shell.execute_reply.started":"2021-12-10T10:29:42.687048Z","shell.execute_reply":"2021-12-10T10:29:42.696123Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"def create_augmented_image(df: DataFrame, input_images_path: str, output_images_path: str, points_parts) -> List:\n    all_images_ids = list(set(list(df[\"id\"])))\n    shuffle(all_images_ids)\n\n    cutmix_images = []\n    cutmix_images_ids = []\n    annotations = {}\n    for i in range(4):\n        image_id = random.choice(all_images_ids)\n        image = cv2.imread(str(Path(input_images_path).joinpath(str(image_id))) + \".png\", cv2.IMREAD_COLOR)\n        cutmix_images_ids.append(image_id)\n        cutmix_images.append(image)\n\n        image_annotation = list(df[df[\"id\"] == image_id][\"annotation\"])\n        label = list(df[df[\"id\"] == image_id][\"cell_type\"])[0]\n        for annot in image_annotation:\n            mask_annot = calculate_mask_for_current_part(annot, points_parts[i], CLASSES.index(label))\n            if mask_annot:\n                key = label\n                value = mask_annot\n                annotations[key] = annotations[key] + [value] if key in annotations else annotations.setdefault(\n                    key,\n                    [value])\n\n    image = np.vstack((np.hstack((cutmix_images[0][:IMAGE_HEIGHT // 2, :IMAGE_WIDTH // 2],\n                                  cutmix_images[1][:IMAGE_HEIGHT // 2, IMAGE_WIDTH // 2:])),\n                       np.hstack((cutmix_images[2][IMAGE_HEIGHT // 2:, :IMAGE_WIDTH // 2],\n                                  cutmix_images[3][IMAGE_HEIGHT // 2:, IMAGE_WIDTH // 2:]))))\n\n    image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)\n    cv2.imwrite(str(Path(output_images_path).joinpath(\"images\").joinpath(\"_\".join(cutmix_images_ids) + \"_cutmix.png\")),\n                image)\n\n    annot_res = []\n    for key, value in annotations.items():\n        for an in value:\n            annot_res.append(\n                [\"_\".join(cutmix_images_ids) + \"_cutmix\", an, IMAGE_WIDTH, IMAGE_HEIGHT, key, '', '', '',\n                 ''])\n\n    return annot_res","metadata":{"execution":{"iopub.status.busy":"2021-12-10T10:29:42.699877Z","iopub.execute_input":"2021-12-10T10:29:42.701348Z","iopub.status.idle":"2021-12-10T10:29:42.714057Z","shell.execute_reply.started":"2021-12-10T10:29:42.701312Z","shell.execute_reply":"2021-12-10T10:29:42.713036Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"# main\nseed_everything(42)\ninput_images_path = \"../input/sartorius-cell-instance-segmentation/train\"\noutput_images_path = \"/kaggle/working/cutmix\"\nrecreate_folder(output_images_path)\nrecreate_folder(output_images_path + \"/images\")\n\ndf = pd.read_csv(\"../input/sartorius-cell-instance-segmentation/train.csv\")\n# df = df[df[\"cell_type\"] == \"cort\"] #cutmix only one class\n\npoints_parts = get_points_for_parts()\n\nannot_result = []\ncount = 3 # count of cutmix images\nfor i in tqdm(range(count)):\n    annot = create_augmented_image(df, input_images_path, output_images_path, points_parts)\n    annot_result.extend(annot)\n\n# create annotations\ndf = pd.DataFrame(annot_result,\n                  columns=['id', 'annotation', 'width', 'height', 'cell_type', 'plate_time', 'sample_date',\n                           'sample_id', 'elapsed_timedelta'])\ndf.to_csv(\"/kaggle/working/cutmix/\" + \"images_aug.csv\", index=False)\nprint(\"Done!\")","metadata":{"execution":{"iopub.status.busy":"2021-12-10T10:29:42.715257Z","iopub.execute_input":"2021-12-10T10:29:42.715564Z","iopub.status.idle":"2021-12-10T10:30:55.611353Z","shell.execute_reply.started":"2021-12-10T10:29:42.715527Z","shell.execute_reply":"2021-12-10T10:30:55.610632Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"### If you find it useful please upvote 👍","metadata":{}}]}