{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.7.9","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"gpu","dataSources":[{"sourceId":23823,"databundleVersionId":1920183,"sourceType":"competition"},{"sourceId":1911681,"sourceType":"datasetVersion","datasetId":1128406},{"sourceId":1934626,"sourceType":"datasetVersion","datasetId":1128710}],"dockerImageVersionId":30056,"isInternetEnabled":false,"language":"python","sourceType":"notebook","isGpuEnabled":true}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"This is simple mmdetection infrence script as a base line.\nTraining part can be foud [here](https://www.kaggle.com/its7171/mmdetection-for-segmentation-training).","metadata":{"papermill":{"duration":0.009854,"end_time":"2021-02-02T02:49:13.549001","exception":false,"start_time":"2021-02-02T02:49:13.539147","status":"completed"},"tags":[]}},{"cell_type":"code","source":"!rsync -a ../input/mmdetection-v280/mmdetection ../\n!pip install ../input/mmdetection-v280/src/mmdet-2.8.0/mmdet-2.8.0/\n!pip install ../input/mmdetection-v280/src/mmpycocotools-12.0.3/mmpycocotools-12.0.3/\n!pip install ../input/mmdetection-v280/src/addict-2.4.0-py3-none-any.whl\n!pip install ../input/mmdetection-v280/src/yapf-0.30.0-py2.py3-none-any.whl\n!pip install ../input/mmdetection-v280/src/mmcv_full-1.2.6-cp37-cp37m-manylinux1_x86_64.whl","metadata":{"_kg_hide-output":true,"execution":{"iopub.status.busy":"2025-06-03T02:47:39.15439Z","iopub.execute_input":"2025-06-03T02:47:39.154709Z","iopub.status.idle":"2025-06-03T02:50:58.498471Z","shell.execute_reply.started":"2025-06-03T02:47:39.154683Z","shell.execute_reply":"2025-06-03T02:50:58.497536Z"},"papermill":{"duration":151.034626,"end_time":"2021-02-02T02:51:44.592784","exception":false,"start_time":"2021-02-02T02:49:13.558158","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pandas as pd\nimport numpy as np\nimport os\nimport cv2\nfrom tqdm import tqdm\nimport pickle\nfrom itertools import groupby\nfrom pycocotools import mask as mutils\nfrom pycocotools import _mask as coco_mask\nimport matplotlib.pyplot as plt\nimport os\nimport base64\nimport typing as t\nimport zlib\nimport random\nrandom.seed(0)\n\n","metadata":{"execution":{"iopub.status.busy":"2025-06-03T02:51:11.171102Z","iopub.execute_input":"2025-06-03T02:51:11.171481Z","iopub.status.idle":"2025-06-03T02:51:11.176437Z","shell.execute_reply.started":"2025-06-03T02:51:11.171447Z","shell.execute_reply":"2025-06-03T02:51:11.175592Z"},"papermill":{"duration":0.216599,"end_time":"2021-02-02T02:51:44.826551","exception":false,"start_time":"2021-02-02T02:51:44.609952","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# helper funcs","metadata":{"papermill":{"duration":0.016707,"end_time":"2021-02-02T02:51:44.860458","exception":false,"start_time":"2021-02-02T02:51:44.843751","status":"completed"},"tags":[]}},{"cell_type":"code","source":"def encode_binary_mask(mask: np.ndarray) -> t.Text:\n  \"\"\"Converts a binary mask into OID challenge encoding ascii text.\"\"\"\n\n  # check input mask --\n  if mask.dtype != np.bool:\n    raise ValueError(\n        \"encode_binary_mask expects a binary mask, received dtype == %s\" %\n        mask.dtype)\n\n  mask = np.squeeze(mask)\n  if len(mask.shape) != 2:\n    raise ValueError(\n        \"encode_binary_mask expects a 2d mask, received shape == %s\" %\n        mask.shape)\n\n  # convert input mask to expected COCO API input --\n  mask_to_encode = mask.reshape(mask.shape[0], mask.shape[1], 1)\n  mask_to_encode = mask_to_encode.astype(np.uint8)\n  mask_to_encode = np.asfortranarray(mask_to_encode)\n\n  # RLE encode mask --\n  encoded_mask = coco_mask.encode(mask_to_encode)[0][\"counts\"]\n\n  # compress and base64 encoding --\n  binary_str = zlib.compress(encoded_mask, zlib.Z_BEST_COMPRESSION)\n  base64_str = base64.b64encode(binary_str)\n  return base64_str.decode()\n\ndef read_img(image_id, color, train_or_test='train', image_size=None):\n    filename = f'{ROOT}/{train_or_test}/{image_id}_{color}.png'\n    assert os.path.exists(filename), f'not found {filename}'\n    img = cv2.imread(filename, cv2.IMREAD_UNCHANGED)\n    if image_size is not None:\n        img = cv2.resize(img, (image_size, image_size))\n    if img.dtype == 'uint16':\n        img = (img/256).astype('uint8')\n    return img\n\ndef load_RGBY_image(image_id, train_or_test='train', image_size=None):\n    red = read_img(image_id, \"red\", train_or_test, image_size)\n    green = read_img(image_id, \"green\", train_or_test, image_size)\n    blue = read_img(image_id, \"blue\", train_or_test, image_size)\n    # using rgb only here\n    #yellow = read_img(image_id, \"yellow\", train_or_test, image_size)\n    stacked_images = np.transpose(np.array([red, green, blue]), (1,2,0))\n    return stacked_images\n\ndef print_masked_img(image_id, mask):\n    img = load_RGBY_image(image_id, train_or_test)\n    \n    plt.figure(figsize=(15, 15))\n    plt.subplot(1, 3, 1)\n    plt.imshow(img)\n    plt.title('Image')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 2)\n    plt.imshow(mask)\n    plt.title('Mask')\n    plt.axis('off')\n    \n    plt.subplot(1, 3, 3)\n    plt.imshow(img)\n    plt.imshow(mask, alpha=0.6)\n    plt.title('Image + Mask')\n    plt.axis('off')\n    plt.show()","metadata":{"execution":{"iopub.status.busy":"2025-06-03T02:51:14.385353Z","iopub.execute_input":"2025-06-03T02:51:14.385683Z","iopub.status.idle":"2025-06-03T02:51:14.396291Z","shell.execute_reply.started":"2025-06-03T02:51:14.385651Z","shell.execute_reply":"2025-06-03T02:51:14.395305Z"},"papermill":{"duration":0.033138,"end_time":"2021-02-02T02:51:44.910682","exception":false,"start_time":"2021-02-02T02:51:44.877544","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# generate files for mmdetection","metadata":{"papermill":{"duration":0.016528,"end_time":"2021-02-02T02:51:44.94507","exception":false,"start_time":"2021-02-02T02:51:44.928542","status":"completed"},"tags":[]}},{"cell_type":"markdown","source":"# inference","metadata":{"papermill":{"duration":0.018048,"end_time":"2021-02-02T02:51:47.239699","exception":false,"start_time":"2021-02-02T02:51:47.221651","status":"completed"},"tags":[]}},{"cell_type":"code","source":"# I just made following config files based on default mask_rcnn.\n# The main changes are CustomDataset, num_classes, data path, etc.\n# Other than that, I used it as is for mmdetection.\n!ls -l ../mmdetection/configs/hpa/","metadata":{"execution":{"iopub.status.busy":"2025-06-03T03:13:52.654035Z","iopub.execute_input":"2025-06-03T03:13:52.654398Z","iopub.status.idle":"2025-06-03T03:13:53.686454Z","shell.execute_reply.started":"2025-06-03T03:13:52.654358Z","shell.execute_reply":"2025-06-03T03:13:53.68565Z"},"papermill":{"duration":0.652169,"end_time":"2021-02-02T02:51:47.910085","exception":false,"start_time":"2021-02-02T02:51:47.257916","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# save first 20% mask with single cell include whole information","metadata":{}},{"cell_type":"code","source":"#step 1\nimport os\nimport pandas as pd\nimport numpy as np\nimport cv2\nimport pickle\nfrom tqdm import tqdm\nfrom pycocotools import mask as coco_mask\n\n# ========== STEP 0: 设置路径和参数 ==========\nROOT = '../input/hpa-single-cell-image-classification/'\nSAVE_IMAGE_DIR = '../work/mmdet_v4_train20_percent/'\nSAVE_PKL_PATH = '../work/mmdet_v4_train20_percent.pkl'\nINFER_RESULT_PATH = '../mmdetection/result_new.pkl'\nSAVE_CELL_INFO_PATH = '../work/train20percent_cells_fullinfo.pkl'\n\n# ========== STEP 1: 准备图像（前 20%） ==========\ndf = pd.read_csv(os.path.join(ROOT, 'train.csv'))\nnum_total = len(df)\nnum_subset = int(num_total * 0.01)\ndf_new = df.iloc[:num_subset].copy()\nimage_ids = df_new['ID'].values\n\nos.makedirs(SAVE_IMAGE_DIR, exist_ok=True)\nprint(f\"✅ 创建图像保存目录: {SAVE_IMAGE_DIR}\")\n\nannos = []\nfor image_id in tqdm(image_ids, desc=\"保存图像 JPG\"):\n    # 读取图像\n    def read_img(image_id, color):\n        path = os.path.join(ROOT, 'train', f\"{image_id}_{color}.png\")\n        img = cv2.imread(path, cv2.IMREAD_UNCHANGED)\n        if img.dtype == 'uint16':\n            img = (img / 256).astype('uint8')\n        return img\n\n    def load_RGBY_image(image_id):\n        r = read_img(image_id, \"red\")\n        g = read_img(image_id, \"green\")\n        b = read_img(image_id, \"blue\")\n        img = np.transpose(np.array([r, g, b]), (1, 2, 0))\n        return img\n\n    img = load_RGBY_image(image_id)\n    cv2.imwrite(os.path.join(SAVE_IMAGE_DIR, f'{image_id}.jpg'), img)\n\n    annos.append({\n        'filename': f'{image_id}.jpg',\n        'width': img.shape[1],\n        'height': img.shape[0],\n        'ann': {\n            'bboxes': None,\n            'labels': None,\n            'masks': None\n        }\n    })\n\n# 保存 inference 输入文件\nwith open(SAVE_PKL_PATH, 'wb') as f:\n    pickle.dump(annos, f)\n\nprint(f\"✅ 已保存 {len(annos)} 张图像及其 annotation 到 {SAVE_PKL_PATH}\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T02:51:53.291781Z","iopub.execute_input":"2025-06-03T02:51:53.292162Z","iopub.status.idle":"2025-06-03T02:52:46.715467Z","shell.execute_reply.started":"2025-06-03T02:51:53.29212Z","shell.execute_reply":"2025-06-03T02:52:46.714588Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pickle\n\nSAVE_PKL_PATH = '../work/mmdet_v4_train20_percent.pkl'\n\n# 假设 annos 是你构造的包含图像路径和信息的列表\n# 如果没有，可以重新执行生成 annos 的部分代码\n\nwith open(SAVE_PKL_PATH, 'wb') as f:\n    pickle.dump(annos, f)\n\nprint(f\"✅ 成功保存：{SAVE_PKL_PATH}，共 {len(annos)} 张图像\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T02:55:29.571088Z","iopub.execute_input":"2025-06-03T02:55:29.571487Z","iopub.status.idle":"2025-06-03T02:55:29.577865Z","shell.execute_reply.started":"2025-06-03T02:55:29.571451Z","shell.execute_reply":"2025-06-03T02:55:29.576912Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"exp_name = \"v4\"\nconf_name = \"mask_rcnn_s101_fpn_syncbn-backbone+head_mstrain_1x_coco\"\nmodel_name = 'mask_rcnn_resnest101_v5_ep9'\n\n# 指定输入/输出路径\ninput_pkl = '../work/mmdet_v4_train20_percent.pkl'\noutput_pkl = '../mmdetection/result_new.pkl'\n\n# 模型配置与权重路径\nconfig = f'configs/hpa_{exp_name}/{conf_name}.py'\nmodel_file = f'../input/hpa-models/{model_name}.pth'\n\ncmd = (\n    f'python tools/test.py {config} {model_file} '\n    f'--out {output_pkl} '\n    f'--cfg-options '\n    f'test_dataloader.dataset.type=CustomDataset '\n    f'test_dataloader.dataset.ann_file={input_pkl} '\n    f'test_dataloader.dataset.img_prefix={SAVE_IMAGE_DIR} '\n    f'test_dataloader.dataset.classes=[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17] '\n    f'test_dataloader.dataset.pipeline[0].type=LoadImageFromFile '\n    f'test_cfg.rcnn.score_thr=0.001'\n)\nann_file=os.path.join(os.getenv('ANN_FILE', '../work/mmdet_v4_train20_percent.pkl')),\n\n\n# 在 mmdetection 目录下运行\n!cd ../mmdetection; {cmd}\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T03:11:56.854934Z","iopub.execute_input":"2025-06-03T03:11:56.855271Z","iopub.status.idle":"2025-06-03T03:12:15.530582Z","shell.execute_reply.started":"2025-06-03T03:11:56.855223Z","shell.execute_reply":"2025-06-03T03:12:15.529696Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import pickle\nresult = pickle.load(open('../mmdetection/result_new.pkl', 'rb'))\nprint(f\"共有结果：{len(result)} 张图像\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-06-03T02:50:59.597478Z","iopub.status.idle":"2025-06-03T02:50:59.597992Z","shell.execute_reply":"2025-06-03T02:50:59.597719Z"}},"outputs":[],"execution_count":null}]}