{"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":"https://towardsdatascience.com/trian-yolov8-instance-segmentation-on-your-data-6ffa04b2debd","metadata":{}},{"cell_type":"code","source":"import random\n\nimport numpy as np\nimport matplotlib.pyplot as plt\n\nfrom glob import glob\nfrom PIL import Image\nfrom skimage import draw\nfrom pathlib import Path\nfrom rasterio import features","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-05-26T07:42:10.054633Z","iopub.execute_input":"2023-05-26T07:42:10.055031Z","iopub.status.idle":"2023-05-26T07:42:10.062009Z","shell.execute_reply.started":"2023-05-26T07:42:10.054984Z","shell.execute_reply":"2023-05-26T07:42:10.059340Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create dummy data","metadata":{}},{"cell_type":"code","source":"def create_image(path, img_size, min_radius):\n    path.parent.mkdir( parents=True, exist_ok=True )\n    \n    arr = np.zeros((img_size, img_size)).astype(np.uint8)\n    center_x = random.randint(min_radius, (img_size-min_radius))\n    center_y = random.randint(min_radius, (img_size-min_radius))\n    max_radius = min(center_x, center_y, img_size - center_x, img_size - center_y)\n    radius = random.randint(min_radius, max_radius)\n\n    row_indxs, column_idxs = draw.ellipse(center_x, center_y, radius, radius, shape=arr.shape)\n    \n    arr[row_indxs, column_idxs] = 255\n\n    im = Image.fromarray(arr)\n    im.save(path)\n\ndef create_images(data_root_path, train_num, val_num, test_num, img_size=640, min_radius=10):\n    data_root_path = Path(data_root_path)\n    \n    for i in range(train_num):\n        create_image(data_root_path / 'train' / 'images' / f'img_{i}.png', img_size, min_radius)\n        \n    for i in range(val_num):\n        create_image(data_root_path / 'val' / 'images' / f'img_{i}.png', img_size, min_radius)\n        \n    for i in range(test_num):\n        create_image(data_root_path / 'test' / 'images' / f'img_{i}.png', img_size, min_radius)\n\ncreate_images('datasets', train_num=120, val_num=40, test_num=40, img_size=120, min_radius=10)\n","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:04:42.098281Z","iopub.execute_input":"2023-05-26T08:04:42.098713Z","iopub.status.idle":"2023-05-26T08:04:42.309048Z","shell.execute_reply.started":"2023-05-26T08:04:42.098682Z","shell.execute_reply":"2023-05-26T08:04:42.308136Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_image_paths = glob('/kaggle/working/datasets/train/images/*')\ntrain_image_paths.sort()\nimage = Image.open(train_image_paths[0])\n\nfig, ax = plt.subplots(1, 3)\nfor i in range(3):\n    image = Image.open(train_image_paths[i])\n    ax[i].imshow(image)","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:05:44.039229Z","iopub.execute_input":"2023-05-26T08:05:44.039604Z","iopub.status.idle":"2023-05-26T08:05:44.645370Z","shell.execute_reply.started":"2023-05-26T08:05:44.039575Z","shell.execute_reply":"2023-05-26T08:05:44.644362Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":"## Create labels","metadata":{}},{"cell_type":"markdown","source":"Label file contains one label and segmentation mask's coordinates in one line. The coordinates should be normalized.  \n{label} {x1} {y1} {x2} {y2}・・・","metadata":{}},{"cell_type":"code","source":"def create_label(image_path, label_path):\n    arr = np.asarray(Image.open(image_path))\n\n    # There may be a better way to do it, but this is what I have found so far\n    cords = list(features.shapes(arr, mask=(arr >0)))[0][0]['coordinates'][0]\n    label_line = '0 ' + ' '.join([f'{int(cord[0])/arr.shape[0]} {int(cord[1])/arr.shape[1]}' for cord in cords])\n\n    label_path.parent.mkdir( parents=True, exist_ok=True )\n    with label_path.open('w') as f:\n        f.write(label_line)\n\nfor images_dir_path in [Path(f'datasets/{x}/images') for x in ['train', 'val', 'test']]:\n    for img_path in images_dir_path.iterdir():\n        label_path = img_path.parent.parent / 'labels' / f'{img_path.stem}.txt'\n        label_line = create_label(img_path, label_path)","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:04:45.426732Z","iopub.execute_input":"2023-05-26T08:04:45.427404Z","iopub.status.idle":"2023-05-26T08:04:45.854885Z","shell.execute_reply.started":"2023-05-26T08:04:45.427369Z","shell.execute_reply":"2023-05-26T08:04:45.853952Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"train_label_paths = glob('/kaggle/working/datasets/train/labels/*')\ntrain_label_paths.sort()\n\nwith open(train_label_paths[0], 'r') as f:\n    label = f.read()\n    label = np.array(label.split(' ')).astype(float) * 120\n    label = label[1:].reshape(-1, 2).astype(int)\n    \n    mask = np.zeros((120, 120))\n    for axis in label:\n        mask[axis[1], axis[0]] = 1\n    \nmask = mask / 120\nplt.imshow(mask)","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:06:46.241972Z","iopub.execute_input":"2023-05-26T08:06:46.242323Z","iopub.status.idle":"2023-05-26T08:06:46.541723Z","shell.execute_reply.started":"2023-05-26T08:06:46.242295Z","shell.execute_reply":"2023-05-26T08:06:46.540726Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"yaml_content = f'''\ntrain: train/images\nval: val/images\ntest: test/images\n\nnames: ['circle']\n    '''\n    \nwith Path('data.yaml').open('w') as f:\n    f.write(yaml_content)","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:12:28.512429Z","iopub.execute_input":"2023-05-26T08:12:28.512779Z","iopub.status.idle":"2023-05-26T08:12:28.518860Z","shell.execute_reply.started":"2023-05-26T08:12:28.512751Z","shell.execute_reply":"2023-05-26T08:12:28.517793Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!pip install ultralytics","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:13:10.095707Z","iopub.execute_input":"2023-05-26T08:13:10.096080Z","iopub.status.idle":"2023-05-26T08:13:26.431379Z","shell.execute_reply.started":"2023-05-26T08:13:10.096051Z","shell.execute_reply":"2023-05-26T08:13:26.430235Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from ultralytics import YOLO\n\nmodel = YOLO(\"yolov8n-seg.pt\")\n\nresults = model.train(\n        batch=8,\n        device=\"cpu\",\n        data=\"data.yaml\",\n        epochs=7,\n        imgsz=120,\n    )","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:18:48.757418Z","iopub.execute_input":"2023-05-26T08:18:48.757843Z","iopub.status.idle":"2023-05-26T08:20:46.491553Z","shell.execute_reply.started":"2023-05-26T08:18:48.757795Z","shell.execute_reply":"2023-05-26T08:20:46.490371Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"!ls runs/segment/train3","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:25:10.955590Z","iopub.execute_input":"2023-05-26T08:25:10.956005Z","iopub.status.idle":"2023-05-26T08:25:11.951136Z","shell.execute_reply.started":"2023-05-26T08:25:10.955970Z","shell.execute_reply":"2023-05-26T08:25:11.949671Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"from IPython.display import Image as show_image\nshow_image(filename=\"runs/segment/train3/val_batch0_labels.jpg\")","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:23:32.589673Z","iopub.execute_input":"2023-05-26T08:23:32.590662Z","iopub.status.idle":"2023-05-26T08:23:32.603524Z","shell.execute_reply.started":"2023-05-26T08:23:32.590621Z","shell.execute_reply":"2023-05-26T08:23:32.601512Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"show_image(filename=\"runs/segment/train3/MaskP_curve.png\")","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:24:38.329518Z","iopub.execute_input":"2023-05-26T08:24:38.329924Z","iopub.status.idle":"2023-05-26T08:24:38.341618Z","shell.execute_reply.started":"2023-05-26T08:24:38.329894Z","shell.execute_reply":"2023-05-26T08:24:38.340745Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:28:46.130412Z","iopub.execute_input":"2023-05-26T08:28:46.131243Z","iopub.status.idle":"2023-05-26T08:28:46.387769Z","shell.execute_reply.started":"2023-05-26T08:28:46.131198Z","shell.execute_reply":"2023-05-26T08:28:46.386807Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"my_model = YOLO('runs/segment/train3/weights/best.pt')\nresults = list(my_model('datasets/test/images/img_2.png', conf=0.128))\nresult = results[0]\n\nimage = Image.open('datasets/test/images/img_2.png')\nmasks = result.masks.masks\n\n\nfig, ax = plt.subplots(1, 2)\nax[0].imshow(image)\nax[1].imshow(masks[0,:,:])","metadata":{"execution":{"iopub.status.busy":"2023-05-26T08:45:57.864459Z","iopub.execute_input":"2023-05-26T08:45:57.864887Z","iopub.status.idle":"2023-05-26T08:45:58.436027Z","shell.execute_reply.started":"2023-05-26T08:45:57.864852Z","shell.execute_reply":"2023-05-26T08:45:58.435082Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"","metadata":{},"execution_count":null,"outputs":[]}]}