601 lines
16 KiB
Plaintext
Executable File
601 lines
16 KiB
Plaintext
Executable File
{
|
||
"cells": [
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 1,
|
||
"id": "f8d96fcf",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"import os\n",
|
||
"import cv2\n",
|
||
"import json\n",
|
||
"import glob\n",
|
||
"import shutil\n",
|
||
"from labelme import utils\n",
|
||
"import seaborn as sns\n",
|
||
"import numpy as np\n",
|
||
"import pandas as pd\n",
|
||
"import matplotlib.pyplot as plt\n",
|
||
"\n",
|
||
"from tqdm import tqdm\n",
|
||
"from PIL import ImageEnhance\n",
|
||
"from PIL import Image\n",
|
||
"from skimage.feature import peak_local_max\n",
|
||
"\n",
|
||
"from core.e2e import get_metrics"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 2,
|
||
"id": "8537a10b-d7a7-4e0b-a27b-8448eb409bd8",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"data_base_path = '/home/andrewtal/Workspace/metrials/v15_Final/data/infer'\n",
|
||
"\n",
|
||
"slide_path = os.path.join(data_base_path, 'slide')\n",
|
||
"slide_gt_path = os.path.join(data_base_path, 'slide_gt')\n",
|
||
"slide_gt3_path = os.path.join(data_base_path, 'slide_gt3')\n",
|
||
"slide_pred_path = os.path.join(data_base_path, 'slide_pred')\n",
|
||
"slide_pden_path = os.path.join(data_base_path, 'slide_pred_den')\n",
|
||
"slide_vis_path = os.path.join(data_base_path, 'slide_vis')\n",
|
||
"patch_path = os.path.join(data_base_path, 'patch')\n",
|
||
"\n",
|
||
"os.makedirs(slide_path, exist_ok=True)\n",
|
||
"os.makedirs(slide_gt_path, exist_ok=True)\n",
|
||
"os.makedirs(slide_gt3_path, exist_ok=True)\n",
|
||
"os.makedirs(slide_pred_path, exist_ok=True)\n",
|
||
"os.makedirs(slide_pden_path, exist_ok=True)\n",
|
||
"os.makedirs(slide_vis_path, exist_ok=True)\n",
|
||
"os.makedirs(patch_path, exist_ok=True)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "c935b002",
|
||
"metadata": {},
|
||
"source": [
|
||
"# UTILS"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 3,
|
||
"id": "13205b6d",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def norm_0_1(mask):\n",
|
||
" x_min = np.min(mask)\n",
|
||
" x_max = np.max(mask)\n",
|
||
" \n",
|
||
" new_mask = (mask-x_min)/(x_max-x_min)\n",
|
||
" \n",
|
||
" return new_mask\n",
|
||
"\n",
|
||
"def get_dotsmap(den_map, min_dis=8, thres=0.3):\n",
|
||
" \n",
|
||
" if np.max(den_map) < thres:\n",
|
||
" return []\n",
|
||
" \n",
|
||
" den_map = norm_0_1(den_map)\n",
|
||
" \n",
|
||
" x_y = peak_local_max(\n",
|
||
" den_map, \n",
|
||
" min_distance = min_dis,\n",
|
||
" threshold_abs = thres,\n",
|
||
" )\n",
|
||
" \n",
|
||
" dots_map = np.zeros(den_map.shape)\n",
|
||
" dots_map[x_y[:, 0].tolist(), x_y[:, 1].tolist()] = 1\n",
|
||
" \n",
|
||
" return dots_map"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "0856aa9b-6972-4202-a81d-69a54526830d",
|
||
"metadata": {
|
||
"tags": []
|
||
},
|
||
"source": [
|
||
"# 中心点检测"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "d6d03146",
|
||
"metadata": {
|
||
"tags": []
|
||
},
|
||
"source": [
|
||
"## 数据裁剪 (模型预测级别)\n",
|
||
"单张图像大小为(1024, 1024),预测模型输入大小为(256,256)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 4,
|
||
"id": "3bd836ac",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"def generate_one(img_path):\n",
|
||
" img = np.array(Image.open(img_path))\n",
|
||
" \n",
|
||
" input_size = 2048\n",
|
||
" patch_size = 256\n",
|
||
" roi_size = 128\n",
|
||
" margin = int((patch_size - roi_size) / 2)\n",
|
||
"\n",
|
||
" assert(img.shape == (input_size, input_size))\n",
|
||
"\n",
|
||
" for hs in range(0, input_size, roi_size):\n",
|
||
" for ws in range(0, input_size, roi_size):\n",
|
||
" # hs\n",
|
||
" if hs - margin < 0:\n",
|
||
" phs = 0\n",
|
||
" elif hs + roi_size + margin > input_size:\n",
|
||
" phs = input_size - patch_size\n",
|
||
" else:\n",
|
||
" phs = hs - margin\n",
|
||
"\n",
|
||
" phe = phs + patch_size\n",
|
||
"\n",
|
||
" # ws\n",
|
||
" if ws - margin < 0:\n",
|
||
" pws = 0\n",
|
||
" elif ws + roi_size + margin > input_size:\n",
|
||
" pws = input_size - patch_size\n",
|
||
" else:\n",
|
||
" pws = ws - margin\n",
|
||
"\n",
|
||
" pwe = pws + patch_size\n",
|
||
"\n",
|
||
" Image.fromarray(img[phs:phe, pws:pwe]).save(\n",
|
||
" img_path.replace('/slide/', '/patch/').replace(\n",
|
||
" '.jpg', '_{}_{}_{}_{}.jpg'.format(int(hs), int(ws), int(phs), int(pws))\n",
|
||
" )\n",
|
||
" )"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "89329db5",
|
||
"metadata": {
|
||
"scrolled": true
|
||
},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"3"
|
||
]
|
||
},
|
||
"execution_count": 7,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"img_list = glob.glob(os.path.join(slide_path, '*.jpg'), recursive=True); len(img_list)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "0dab5bc1",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"for item in img_list:\n",
|
||
" generate_one(item)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "00cc16e2",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 预测 Patch 结果"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "2b5abb65",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"# python inference.py"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "d2e061e2-0985-4d77-8944-4f4e6b10523b",
|
||
"metadata": {},
|
||
"source": [
|
||
"# GT"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 5,
|
||
"id": "713377ef-70e3-4231-9da1-9127e216c870",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"3"
|
||
]
|
||
},
|
||
"execution_count": 5,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"json_list = glob.glob(os.path.join(slide_path, '*.json'), recursive=True); len(json_list)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 6,
|
||
"id": "4ef0ff20-9c9c-4d60-ad35-630875053495",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"for json_path in json_list:\n",
|
||
" base_name = json_path.split('/')[-1].split('.')[0]\n",
|
||
" with open(json_path) as f:\n",
|
||
" j_data = json.load(f)\n",
|
||
"\n",
|
||
" y = np.array(np.array([item['label'] for item in j_data['shapes']]) != 'Norm', np.uint8) + 1\n",
|
||
" p = np.array([item['points'][0][::-1] for item in j_data['shapes']], np.int32)\n",
|
||
"\n",
|
||
" m = np.zeros((2048, 2048))\n",
|
||
" m[p[:, 0], p[:, 1]] = y\n",
|
||
" m = np.array(m, np.uint8)\n",
|
||
"\n",
|
||
" Image.fromarray(m).save('{}/{}.png'.format(slide_gt_path, base_name))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 7,
|
||
"id": "840d713e-0c26-4fe5-a5d5-edb15dad4b11",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"data_dict = {\n",
|
||
" 'Norm': 1,\n",
|
||
" 'LineSV': 2,\n",
|
||
" 'SV': 3\n",
|
||
"}"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 8,
|
||
"id": "c597a743-9932-49d0-a56f-5053e7a47306",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"for json_path in json_list:\n",
|
||
" base_name = json_path.split('/')[-1].split('.')[0]\n",
|
||
" with open(json_path) as f:\n",
|
||
" j_data = json.load(f)\n",
|
||
"\n",
|
||
" y = np.array([data_dict[item['label']] for item in j_data['shapes']], np.uint8)\n",
|
||
" p = np.array([item['points'][0][::-1] for item in j_data['shapes']], np.int32)\n",
|
||
"\n",
|
||
" m = np.zeros((2048, 2048))\n",
|
||
" m[p[:, 0], p[:, 1]] = y\n",
|
||
" m = np.array(m, np.uint8)\n",
|
||
"\n",
|
||
" Image.fromarray(m).save('{}/{}.png'.format(slide_gt3_path, base_name))"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "3ec0e255",
|
||
"metadata": {},
|
||
"source": [
|
||
"## 重整预测结果"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 13,
|
||
"id": "cd6b5cff-4b9b-465f-b7bc-ee1c218eb6d9",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"name": "stderr",
|
||
"output_type": "stream",
|
||
"text": [
|
||
"100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 8/8 [02:22<00:00, 17.82s/it]\n"
|
||
]
|
||
}
|
||
],
|
||
"source": [
|
||
"pds = []\n",
|
||
"for i in tqdm(range(8)):\n",
|
||
" with open('./infer_patch_{}.json'.format(str(i))) as f:\n",
|
||
" data = json.load(f)\n",
|
||
" \n",
|
||
" imgs = np.array(data['img_path'])\n",
|
||
" pds += [np.array(data['pred'])]"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "84b86d4e-2670-40f4-859f-1d123e9367b4",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"slide_pred_path = os.path.join(data_base_path, 'slide_pred_{}'.format(n))\n",
|
||
"os.makedirs(slide_pred_path, exist_ok=True)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 14,
|
||
"id": "5575c5ca-fa26-446f-9c8d-bd8af40b3bd7",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"pds_m = np.mean(np.array(pds), axis=0)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "609b1b74-0949-4ed5-a5ce-da491d08758f",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Save Results"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 15,
|
||
"id": "96cee923",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"array([0.99319904, 0.98927185, 0.99120423])"
|
||
]
|
||
},
|
||
"execution_count": 15,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"imgs_name = np.array([item.split('/')[-1].split('_')[0] for item in imgs])\n",
|
||
"imgs_name_sets = set(imgs_name)\n",
|
||
"\n",
|
||
"input_size = 2048\n",
|
||
"roi_size = 128\n",
|
||
"\n",
|
||
"for name in imgs_name_sets:\n",
|
||
" idx = imgs_name == name\n",
|
||
"\n",
|
||
" imgs_temp = imgs[idx]\n",
|
||
" pds_temp = pds_m[idx]\n",
|
||
"\n",
|
||
" den_map = np.zeros((input_size, input_size), np.float32)\n",
|
||
"\n",
|
||
" for i, item in enumerate(imgs_temp):\n",
|
||
" hs, ws, phs, pws = item.split('/')[-1].split('.')[0].split('_')[-4:]\n",
|
||
" hs = int(hs)\n",
|
||
" ws = int(ws)\n",
|
||
" phs = int(phs)\n",
|
||
" pws = int(pws)\n",
|
||
"\n",
|
||
" den_map[hs:hs+roi_size, ws:ws+roi_size] = pds_temp[i][hs-phs:hs-phs+roi_size, ws-pws:ws-pws+roi_size]\n",
|
||
"\n",
|
||
" np.save('{}/{}.npy'.format(slide_pden_path, name), den_map)\n",
|
||
" dots_map = get_dotsmap(den_map, min_dis=8, thres=0.3)\n",
|
||
"\n",
|
||
" Image.fromarray(dots_map).convert('L').save(\n",
|
||
" os.path.join(slide_pred_path, '{}.png'.format(name))\n",
|
||
" )\n",
|
||
"\n",
|
||
"base_names = ['5', '10', '15']\n",
|
||
"results = []\n",
|
||
"for base_name in base_names:\n",
|
||
" gt = cv2.imread('{}/{}.png'.format(slide_gt_path, base_name), 0)\n",
|
||
" pred = cv2.imread('{}/{}.png'.format(slide_pred_path, base_name), 0)\n",
|
||
" results += [get_metrics(gt, pred, 0.5)]\n",
|
||
"\n",
|
||
"np.mean(results, axis=0)"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 19,
|
||
"id": "85cd28c5-dd54-42cf-a85b-79426a5e4121",
|
||
"metadata": {},
|
||
"outputs": [
|
||
{
|
||
"data": {
|
||
"text/plain": [
|
||
"[(0.9941186954197113, 0.9982104509663565, 0.9961603714617376),\n",
|
||
" (0.9962653387871243, 0.9989300998573466, 0.997595939809456),\n",
|
||
" (0.9892130857648099, 0.9706749956619816, 0.9798563671396042)]"
|
||
]
|
||
},
|
||
"execution_count": 19,
|
||
"metadata": {},
|
||
"output_type": "execute_result"
|
||
}
|
||
],
|
||
"source": [
|
||
"results"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "markdown",
|
||
"id": "96445c27-9791-45f1-bb35-35d4e078a429",
|
||
"metadata": {},
|
||
"source": [
|
||
"# Plot"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 16,
|
||
"id": "0d5f03f2-5818-47ca-90af-6ee6cdb7bf88",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"base_names = ['5', '10', '15']"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": 18,
|
||
"id": "c600f9e3-34e4-412d-8eb0-3b5b5e5f2f75",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": [
|
||
"for base_name in base_names:\n",
|
||
" img_path = '../../data/slidep/{}.jpg'.format(base_name)\n",
|
||
" gt_path = '../../data/infer/slide_gt/{}.png'.format(base_name)\n",
|
||
" pd_path = '../../data/infer/slide_pred/{}.png'.format(base_name)\n",
|
||
" den_path = '../../data/infer/slide_pred_den/{}.npy'.format(base_name)\n",
|
||
"\n",
|
||
" img = cv2.imread(img_path, 0)\n",
|
||
" gt = cv2.imread(gt_path, 0)\n",
|
||
" pd = cv2.imread(pd_path, 0)\n",
|
||
" den = np.load(den_path)\n",
|
||
"\n",
|
||
" plt.figure(figsize=(15, 6))\n",
|
||
" plt.subplot(1, 3, 1)\n",
|
||
" plt.imshow(img, cmap='gray')\n",
|
||
" plt.axis('off')\n",
|
||
" plt.title('Ground truth_'+base_name)\n",
|
||
" h, w = np.where(gt != 0)\n",
|
||
" plt.scatter(w, h, s=4)\n",
|
||
"\n",
|
||
" plt.subplot(1, 3, 2)\n",
|
||
" plt.imshow(den_map)\n",
|
||
" plt.axis('off')\n",
|
||
" plt.title('Density map_'+base_name)\n",
|
||
"\n",
|
||
" plt.subplot(1, 3, 3)\n",
|
||
" plt.imshow(img, cmap='gray')\n",
|
||
" h, w = np.where(pd != 0)\n",
|
||
" plt.scatter(w, h, s=4)\n",
|
||
" plt.axis('off')\n",
|
||
" plt.title('Prediction_'+base_name)\n",
|
||
" plt.tight_layout()\n",
|
||
"\n",
|
||
" plt.savefig('{}/{}.jpg'.format(slide_vis_path, base_name), dpi=200)\n",
|
||
" plt.close()"
|
||
]
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "fe34998f-aa2f-4160-804b-a959d96ac272",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "1ab53ed8-3f82-43b4-ac90-9c6fa0cf72c9",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "05b370dd-9582-47c3-be2f-3ab2eee08bb0",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "a7b1b7c9-f329-4407-bd2a-3dc1e7984b7c",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "93a997eb-0d99-40ae-a7c5-7eb84cbbc64f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "57fc2159-e317-4065-8c5a-8adf0fa48ff6",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "6c651935-2577-4227-93d7-908e05c08716",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "26d2a8e8-c8d0-453a-82d8-02660ebf354f",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
},
|
||
{
|
||
"cell_type": "code",
|
||
"execution_count": null,
|
||
"id": "8dac93ed-8fa3-4516-b616-34c583d75b42",
|
||
"metadata": {},
|
||
"outputs": [],
|
||
"source": []
|
||
}
|
||
],
|
||
"metadata": {
|
||
"kernelspec": {
|
||
"display_name": "cmae",
|
||
"language": "python",
|
||
"name": "cmae"
|
||
},
|
||
"language_info": {
|
||
"codemirror_mode": {
|
||
"name": "ipython",
|
||
"version": 3
|
||
},
|
||
"file_extension": ".py",
|
||
"mimetype": "text/x-python",
|
||
"name": "python",
|
||
"nbconvert_exporter": "python",
|
||
"pygments_lexer": "ipython3",
|
||
"version": "3.8.16"
|
||
}
|
||
},
|
||
"nbformat": 4,
|
||
"nbformat_minor": 5
|
||
}
|