{"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,"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,"execution":{"iopub.status.busy":"2025-05-23T09:19:04.833114Z","iopub.execute_input":"2025-05-23T09:19:04.833398Z","iopub.status.idle":"2025-05-23T09:22:34.344454Z","shell.execute_reply.started":"2025-05-23T09:19:04.833327Z","shell.execute_reply":"2025-05-23T09:22:34.343416Z"}},"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\nexp_name = \"v4\"\nconf_name = \"mask_rcnn_s101_fpn_syncbn-backbone+head_mstrain_1x_coco\"\nmodel_name = 'mask_rcnn_resnest101_v5_ep9'\nROOT = '../input/hpa-single-cell-image-classification/'\ntrain_or_test = 'test'\ndf = pd.read_csv(os.path.join(ROOT, 'sample_submission.csv'))\nif len(df) == 559:\n    debug = True\n    df = df[:3]\nelse:\n    debug = False","metadata":{"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,"execution":{"iopub.status.busy":"2025-05-23T09:22:34.347057Z","iopub.execute_input":"2025-05-23T09:22:34.347345Z","iopub.status.idle":"2025-05-23T09:22:34.531714Z","shell.execute_reply.started":"2025-05-23T09:22:34.347314Z","shell.execute_reply":"2025-05-23T09:22:34.53107Z"}},"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":{"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,"execution":{"iopub.status.busy":"2025-05-23T09:22:34.533352Z","iopub.execute_input":"2025-05-23T09:22:34.533588Z","iopub.status.idle":"2025-05-23T09:22:34.543873Z","shell.execute_reply.started":"2025-05-23T09:22:34.533566Z","shell.execute_reply":"2025-05-23T09:22:34.542958Z"}},"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":"code","source":"out_image_dir = f'../work/mmdet_{exp_name}_{train_or_test}/'\n!mkdir -p {out_image_dir}\n\nannos = []\nfor idx in tqdm(range(len(df))):\n    image_id = df.iloc[idx].ID\n    img = load_RGBY_image(image_id, train_or_test)\n    \n    cv2.imwrite(f'{out_image_dir}/{image_id}.jpg', img)\n    ann = {\n        'filename': 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    annos.append(ann)\n    \nwith open(f'../work/mmdet_{exp_name}_tst.pkl', 'wb') as f:\n    pickle.dump(annos, f)","metadata":{"lines_to_next_cell":2,"papermill":{"duration":2.240857,"end_time":"2021-02-02T02:51:47.202634","exception":false,"start_time":"2021-02-02T02:51:44.961777","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-23T09:22:34.544861Z","iopub.execute_input":"2025-05-23T09:22:34.54507Z","iopub.status.idle":"2025-05-23T09:22:36.96198Z","shell.execute_reply.started":"2025-05-23T09:22:34.545049Z","shell.execute_reply":"2025-05-23T09:22:36.961198Z"}},"outputs":[],"execution_count":null},{"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":{"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":"code","source":"config = f'configs/hpa_{exp_name}/{conf_name}.py'\nmodel_file = f'../input/hpa-models/{model_name}.pth'\nresult_pkl = f'../work/{model_name}.pkl'\nadditional_conf = '--cfg-options'\nadditional_conf += ' test_cfg.rcnn.score_thr=0.001'\ncmd = f'python tools/test.py {config} {model_file} --out {result_pkl} {additional_conf}'\n!cd ../mmdetection; {cmd}\nresult = pickle.load(open('../mmdetection/'+result_pkl, 'rb'))\n\n# 假设 result 是你加载完成的推理结果（已经存在）\n\n# Step 1: 显式保存 .pkl 到当前目录\nimport pickle\nwith open('mask_rcnn_resnest101_v5_ep9.pkl', 'wb') as f:\n    pickle.dump(result, f)\n\n# Step 2: 确保 /kaggle/working/ 下也有\n#import shutil\n#shutil.copy('mask_rcnn_resnest101_v5_ep9.pkl', '/kaggle/working/mask_rcnn_resnest101_v5_ep9.pkl')\n\n# Step 3: 确认路径存在\nimport os\nprint('✅ 文件是否存在:', os.path.exists('/kaggle/working/mask_rcnn_resnest101_v5_ep9.pkl'))\n","metadata":{"papermill":{"duration":22.227907,"end_time":"2021-02-02T02:52:10.157446","exception":false,"start_time":"2021-02-02T02:51:47.929539","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# result check","metadata":{"papermill":{"duration":0.020518,"end_time":"2021-02-02T02:52:10.198232","exception":false,"start_time":"2021-02-02T02:52:10.177714","status":"completed"},"tags":[]}},{"cell_type":"code","source":"for ii in range(3):\n    image_id = annos[ii]['filename'].replace('.jpg','').replace('.png','')\n    for class_id in range(19):\n        #print(ii,class_id,len(result[ii][0][class_id]), len(result[ii][1][class_id]))\n        bbs = result[ii][0][class_id]\n        sgs = result[ii][1][class_id]\n        for bb, sg in zip(bbs,sgs):\n            box = bb[:4]\n            cnf = bb[4]\n            h = sg['size'][0]\n            w = sg['size'][0]\n            if cnf > 0.3:\n                print(f'class_id:{class_id}, image_id:{image_id}, confidence:{cnf}')\n                mask = mutils.decode(sg).astype(bool)\n                print_masked_img(image_id, mask)","metadata":{"papermill":{"duration":116.347764,"end_time":"2021-02-02T02:54:06.565989","exception":false,"start_time":"2021-02-02T02:52:10.218225","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-23T09:23:05.161817Z","iopub.status.idle":"2025-05-23T09:23:05.16215Z","shell.execute_reply":"2025-05-23T09:23:05.161988Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# format submission file","metadata":{"papermill":{"duration":0.371128,"end_time":"2021-02-02T02:54:07.345079","exception":false,"start_time":"2021-02-02T02:54:06.973951","status":"completed"},"tags":[]}},{"cell_type":"code","source":"with open('submission.csv', 'w') as outf:\n    print('ID,ImageWidth,ImageHeight,PredictionString', file=outf)\n    for ii in range(len(annos)):\n        image_id = annos[ii]['filename'].replace('.jpg','').replace('.png','')\n        pred_strs = []\n        for class_id in range(19):\n            #print(ii,class_id,len(result[ii][0][class_id]), len(result[ii][1][class_id]))\n            bbs = result[ii][0][class_id]\n            sgs = result[ii][1][class_id]\n            for bb, sg in zip(bbs,sgs):\n                box = bb[:4]\n                cnf = bb[4]\n                h = sg['size'][0]\n                w = sg['size'][1]\n                #convert coco format to kaggle format\n                mask = mutils.decode(sg).astype(bool)\n                rle = encode_binary_mask(mask)\n                pred_strs.append(f'{class_id} {cnf} {rle}')\n        print(f'{image_id},{w},{h},{\" \".join(pred_strs)}', file=outf)\n","metadata":{"papermill":{"duration":1.168848,"end_time":"2021-02-02T02:54:08.874759","exception":false,"start_time":"2021-02-02T02:54:07.705911","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-23T09:23:05.163311Z","iopub.status.idle":"2025-05-23T09:23:05.163858Z","shell.execute_reply":"2025-05-23T09:23:05.163564Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"!ls -l ","metadata":{"papermill":{"duration":1.006478,"end_time":"2021-02-02T02:54:10.234273","exception":false,"start_time":"2021-02-02T02:54:09.227795","status":"completed"},"tags":[],"trusted":true,"execution":{"iopub.status.busy":"2025-05-23T09:23:05.164905Z","iopub.status.idle":"2025-05-23T09:23:05.165287Z","shell.execute_reply":"2025-05-23T09:23:05.165086Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"","metadata":{"papermill":{"duration":0.360863,"end_time":"2021-02-02T02:54:10.950096","exception":false,"start_time":"2021-02-02T02:54:10.589233","status":"completed"},"tags":[],"trusted":true},"outputs":[],"execution_count":null}]}