{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"nvidiaTeslaT4","dataSources":[{"sourceId":84969,"databundleVersionId":10033515,"sourceType":"competition"},{"sourceId":139474,"sourceType":"modelInstanceVersion","isSourceIdPinned":true,"modelInstanceId":118113,"modelId":141350}],"dockerImageVersionId":30804,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"# CZII making datasets for YOLO\n!pip install zarr\nimport json\nimport numpy as np\nimport pandas as pd\nimport matplotlib.pyplot as plt\nimport zarr\nfrom tqdm import tqdm\nimport glob, os\nimport cv2","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:26.562966Z","iopub.execute_input":"2025-01-14T18:51:26.563723Z","iopub.status.idle":"2025-01-14T18:51:39.137351Z","shell.execute_reply.started":"2025-01-14T18:51:26.563687Z","shell.execute_reply":"2025-01-14T18:51:39.136262Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Kod przetwarza ścieżki eksperymentów z katalogu\n# i tworzy mapowania pomiędzy indeksami a nazwami eksperymentów\nruns = sorted(glob.glob('/kaggle/input/czii-cryo-et-object-identification/train/overlay/ExperimentRuns/*'))\nruns = [os.path.basename(file_name) for file_name in runs]\n\nid_run_dict = {i: r for i, r in zip(range(len(runs)), runs)}\nprint(id_run_dict)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:39.139612Z","iopub.execute_input":"2025-01-14T18:51:39.140876Z","iopub.status.idle":"2025-01-14T18:51:39.158711Z","shell.execute_reply.started":"2025-01-14T18:51:39.140822Z","shell.execute_reply":"2025-01-14T18:51:39.158014Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Funkcja przetwarza obraz w postaci macierzy \n# na 8-bitowy zakres (od 0 do 255), czyli zdjęcie.\ndef convert_to_8bit(x):\n    lower, upper = np.percentile(x, (0.5, 99.5))\n    x = np.clip(x, lower, upper)\n    x = (x - x.min()) / (x.max() - x.min() + 1e-12) * 255\n    return x.round().astype(\"uint8\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:39.159563Z","iopub.execute_input":"2025-01-14T18:51:39.159781Z","iopub.status.idle":"2025-01-14T18:51:39.165228Z","shell.execute_reply.started":"2025-01-14T18:51:39.159756Z","shell.execute_reply":"2025-01-14T18:51:39.164365Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Słownik: nazwy cząsteczek (etykiety) względem id.\nlabel_id_dict = {\n        'apo-ferritin': 0,\n        'beta-amylase': 1,\n        'beta-galactosidase': 2,\n        'ribosome': 3,\n        'thyroglobulin': 4,\n        'virus-like-particle': 5\n    }\n\n#Słownik: nazwy cząsteczek (etykiety) względem średnicy cząsteczki.\nparticle_radius = {\n        'apo-ferritin': 60,\n        'beta-amylase': 65,\n        'beta-galactosidase': 90,\n        'ribosome': 150,\n        'thyroglobulin': 130,\n        'virus-like-particle': 135,\n    }\n\nparticle_names = ['apo-ferritin', 'beta-amylase', 'beta-galactosidase', 'ribosome', 'thyroglobulin', 'virus-like-particle']","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:39.166682Z","iopub.execute_input":"2025-01-14T18:51:39.167626Z","iopub.status.idle":"2025-01-14T18:51:39.178094Z","shell.execute_reply.started":"2025-01-14T18:51:39.167579Z","shell.execute_reply":"2025-01-14T18:51:39.177007Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#Przygotowanie folderów pod zbiory treningowe i walidacyjne\nos.makedirs(\"images/train\", exist_ok=True)\nos.makedirs(\"images/val\", exist_ok=True)\nos.makedirs(\"labels/val\", exist_ok=True)\nos.makedirs(\"labels/train\", exist_ok=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:39.181115Z","iopub.execute_input":"2025-01-14T18:51:39.181955Z","iopub.status.idle":"2025-01-14T18:51:39.190897Z","shell.execute_reply.started":"2025-01-14T18:51:39.181914Z","shell.execute_reply":"2025-01-14T18:51:39.190098Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Funkcja make_annotate_yolo ma za zadanie przetworzyć dane z zestawu obrazów 3D (Cryo-ET),\n# odpowiednio je przekształcić i przygotować dane w formacie kompatybilnym z YOLO.\n# Obejmuje to generowanie obrazów 2D, normalizację intensywności oraz tworzenie plików tekstowych \n# z adnotacjami odpowiadającymi formatowi YOLO.\n\ndef make_annotate_yolo(run_name, is_train_path=True):\n    is_train_path = 'train' if is_train_path else 'val'\n\n    vol = zarr.open(f'/kaggle/input/czii-cryo-et-object-identification/train/static/ExperimentRuns/{r}/VoxelSpacing10.000/denoised.zarr', mode='r')\n    vol = vol[0]\n    vol2 = convert_to_8bit(vol)\n    \n    n_imgs = vol2.shape[0]\n    for j in range(n_imgs):\n        newvol = vol2[j]\n        newvolf = np.stack([newvol]*3, axis=-1)\n        newvolf = cv2.resize(newvolf, (640,640))\n        cv2.imwrite(f'images/{is_train_path}/{run_name}_{j*10}.png', newvolf)\n        with open(f'labels/{is_train_path}/{run_name}_{j*10}.txt', 'w'):\n            pass\n            \n    for p, particle in enumerate(tqdm(particle_names)):\n        # impossible, not scored\n        if particle==\"beta-amylase\":\n            continue\n        json_each_paticle = f\"/kaggle/input/czii-cryo-et-object-identification/train/overlay/ExperimentRuns/{run_name}/Picks/{particle}.json\"\n        df = pd.read_json(json_each_paticle) \n        for axis in \"x\", \"y\", \"z\":\n            df[axis] = df.points.apply(lambda x: x[\"location\"][axis])\n\n        \n        radius = particle_radius[particle]\n        for i, row in df.iterrows():\n            start_z = np.round(row['z'] - radius).astype(np.int32)\n            start_z = max(0, start_z//10)\n            end_z = np.round(row['z'] + radius).astype(np.int32)\n            end_z = min(n_imgs, end_z//10)\n            \n            for j in range(start_z+1, end_z+1-1, 1):\n                with open(f'labels/{is_train_path}/{run_name}_{j*10}.txt', 'a') as f:\n                    f.write(f'{label_id_dict[particle]} {row[\"x\"]/10/vol2.shape[1]} {row[\"y\"]/10/vol2.shape[2]} {radius/10/vol2.shape[1]*2} {radius/10/vol2.shape[2]*2} \\n')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:39.192371Z","iopub.execute_input":"2025-01-14T18:51:39.192721Z","iopub.status.idle":"2025-01-14T18:51:39.203951Z","shell.execute_reply.started":"2025-01-14T18:51:39.192683Z","shell.execute_reply":"2025-01-14T18:51:39.202928Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Iteracja przez listę przebiegów eksperymentu i generowanie obrazów i adnotacji zgodnych z YOLO.\n# Pierwszy przebieg jest przypisywany do zbioru walidacyjnego (is_train_path=False), podczas gdy pozostałe są przypisywane do zbioru szkoleniowego (is_train_path=True).\nfor i, r in enumerate(runs):\n    make_annotate_yolo(r, is_train_path=False if i==0 else True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:51:39.204922Z","iopub.execute_input":"2025-01-14T18:51:39.205925Z","iopub.status.idle":"2025-01-14T18:52:49.352345Z","shell.execute_reply.started":"2025-01-14T18:51:39.205876Z","shell.execute_reply":"2025-01-14T18:52:49.351441Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import shutil\nos.makedirs('datasets/czii_det2d', exist_ok=True)\nshutil.move('images/train', 'datasets/czii_det2d/images/train')\nshutil.move('images/val', 'datasets/czii_det2d/images')\nshutil.move('labels/train', 'datasets/czii_det2d/labels/train')\nshutil.move('labels/val', 'datasets/czii_det2d/labels')","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:52:49.353587Z","iopub.execute_input":"2025-01-14T18:52:49.353869Z","iopub.status.idle":"2025-01-14T18:52:50.687530Z","shell.execute_reply.started":"2025-01-14T18:52:49.353842Z","shell.execute_reply":"2025-01-14T18:52:50.686555Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"%%writefile czii_conf.yaml\n\npath: /kaggle/working/datasets/czii_det2d # dataset root dir\ntrain: images/train # train images (relative to 'path') \nval: images/val # val images (relative to 'path') \n\nnc: 6\n\n# Classes\nnames:\n  0: apo-ferritin\n  1: beta-amylase\n  2: beta-galactosidase\n  3: ribosome\n  4: thyroglobulin\n  5: virus-like-particle","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:52:50.689042Z","iopub.execute_input":"2025-01-14T18:52:50.689270Z","iopub.status.idle":"2025-01-14T18:52:50.695352Z","shell.execute_reply.started":"2025-01-14T18:52:50.689247Z","shell.execute_reply":"2025-01-14T18:52:50.694426Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!pip install ultralytics\nfrom tqdm import tqdm\nimport glob, os\nfrom ultralytics import YOLO","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:52:50.696488Z","iopub.execute_input":"2025-01-14T18:52:50.696895Z","iopub.status.idle":"2025-01-14T18:53:06.555047Z","shell.execute_reply.started":"2025-01-14T18:52:50.696857Z","shell.execute_reply":"2025-01-14T18:53:06.554302Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# załaduj wstępnie wytrenowany model\nmodel = YOLO(\"/kaggle/input/yolo11/pytorch/default/1/yolo11l.pt\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:53:06.556004Z","iopub.execute_input":"2025-01-14T18:53:06.556524Z","iopub.status.idle":"2025-01-14T18:53:07.474053Z","shell.execute_reply.started":"2025-01-14T18:53:06.556496Z","shell.execute_reply":"2025-01-14T18:53:07.473370Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Trenowanie modelu\n_ = model.train(\n    data=\"/kaggle/working/czii_conf.yaml\",\n    epochs=100,\n    warmup_epochs=10,\n    optimizer='AdamW',\n    cos_lr=True,\n    lr0=3e-4,\n    lrf=0.03,\n    imgsz=640,\n    device=\"0,1\",\n    weight_decay=0.005,\n    batch=32,\n    scale=0,\n    flipud=0.5,\n    fliplr=0.5,\n    degrees=45,\n    shear=5,\n    mixup=0.2,\n    copy_paste=0.25,\n    seed=8620,\n    pretrained=False  # Wyłączenie użycia wstępnych wag\n)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T18:53:07.475033Z","iopub.execute_input":"2025-01-14T18:53:07.475285Z","iopub.status.idle":"2025-01-14T19:54:57.936261Z","shell.execute_reply.started":"2025-01-14T18:53:07.475259Z","shell.execute_reply":"2025-01-14T19:54:57.935236Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"#model = YOLO(\"/kaggle/working/yolo11n.pt\")\nmodel = YOLO(\"/kaggle/working/runs/detect/train/weights/best.pt\")\nmetrics = model.val(data=\"/kaggle/working/czii_conf.yaml\", imgsz=640, batch=16, conf=0.25, iou=0.6, device=\"0\", save_json=True)\nprint(metrics.box.map)  # map50-95\nprint(metrics.box.map50)  # map50\nprint(metrics.box.map75)  # map75\nprint(metrics.box.maps)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T20:50:40.311979Z","iopub.execute_input":"2025-01-14T20:50:40.312419Z","iopub.status.idle":"2025-01-14T20:50:52.923804Z","shell.execute_reply.started":"2025-01-14T20:50:40.312353Z","shell.execute_reply":"2025-01-14T20:50:52.922771Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"results = model(\"/kaggle/working/datasets/czii_det2d/images/val/TS_5_4_1010.png\")\nresults[0].show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-01-14T20:54:30.445241Z","iopub.execute_input":"2025-01-14T20:54:30.446052Z","iopub.status.idle":"2025-01-14T20:54:30.576268Z","shell.execute_reply.started":"2025-01-14T20:54:30.446002Z","shell.execute_reply":"2025-01-14T20:54:30.575495Z"}},"outputs":[],"execution_count":null}]}