{"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":"for discussion, refer to\nhttps://www.kaggle.com/competitions/vesuvius-challenge-ink-detection/discussion/407972#2286191","metadata":{}},{"cell_type":"code","source":"import sys\nsys.path.append('/kaggle/input/ink-00/my_lib')\nsys.path.append('/kaggle/input/pretrainedmodels/pretrainedmodels-0.7.4')\nsys.path.append('/kaggle/input/efficientnet-pytorch/EfficientNet-PyTorch-master')\nsys.path.append('/kaggle/input/timm-pytorch-image-models/pytorch-image-models-master')\nsys.path.append('/kaggle/input/segmentation-models-pytorch/segmentation_models.pytorch-master')\nsys.path.append('/kaggle/input/einops/einops-master')\n\nfrom helper import *\nimport hashlib\nimport numpy as np\nimport pandas as pd\n\nfrom collections import defaultdict\nfrom glob import glob\nimport PIL.Image as Image\nImage.MAX_IMAGE_PIXELS = 10000000000  # Ignore PIL warnings about large images\n\nimport cv2\n\nimport torch\nimport torch.nn as nn\nimport torch.nn.functional as F\n\nfrom einops import rearrange, reduce, repeat\nimport segmentation_models_pytorch as smp\nfrom segmentation_models_pytorch.decoders.unet.decoder import UnetDecoder, DecoderBlock\nfrom timm.models.resnet import *\n\n\nimport matplotlib\nimport matplotlib.pyplot as plt\n#matplotlib.use('TkAgg')\n%matplotlib inline \n  \nprint('import ok !!!')","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","execution":{"iopub.status.busy":"2023-06-03T10:43:24.157177Z","iopub.execute_input":"2023-06-03T10:43:24.157575Z","iopub.status.idle":"2023-06-03T10:43:30.864981Z","shell.execute_reply.started":"2023-06-03T10:43:24.157544Z","shell.execute_reply":"2023-06-03T10:43:30.863907Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"class Config(object):\n    mode = [\n        #'train', #\n        'test', 'skip_fake_test',\n    ]\n    crop_fade  = 32\n    crop_size  = 256\n    crop_depth = 5\n    infer_fragment_z = [16, 48]\n\nCFG = Config()\nCFG.rot_tta  = True #False #False #\n\n\nif 'train' in CFG.mode:\n    CFG.stride = CFG.crop_size//2 #56 #\nif 'test' in CFG.mode:\n    CFG.stride = CFG.crop_size//2\n    CFG.rot_tta = True\n \ndef cfg_to_text():\n    d = Config.__dict__\n    text = [f'\\t{k} : {v}' for k,v in d.items() if not (k.startswith('__') and k.endswith('__'))]\n    d = CFG.__dict__\n    text += [f'\\t{k} : {v}' for k,v in d.items() if not (k.startswith('__') and k.endswith('__'))]\n    return 'CFG\\n'+'\\n'.join(text)\n\nprint(cfg_to_text())","metadata":{"execution":{"iopub.status.busy":"2023-06-03T10:43:30.867085Z","iopub.execute_input":"2023-06-03T10:43:30.867897Z","iopub.status.idle":"2023-06-03T10:43:30.877558Z","shell.execute_reply.started":"2023-06-03T10:43:30.867861Z","shell.execute_reply":"2023-06-03T10:43:30.876526Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"## dataset ##\nif 'train' in CFG.mode:\n    data_dir = '/kaggle/input/vesuvius-challenge-ink-detection/train'\n    valid_id =[\n        '1',#'2b',\n    ]\n\nif 'test' in CFG.mode: \n    data_dir = '/kaggle/input/vesuvius-challenge-ink-detection/test'\n    valid_id = glob(f'{data_dir}/*')\n    valid_id = sorted(valid_id)\n    valid_id = [f.split('/')[-1] for f in valid_id]\n\n    # https://www.kaggle.com/competitions/vesuvius-challenge-ink-detection/discussion/410985\n    a_file = f'{data_dir}/a/mask.png'\n    with open(a_file,'rb') as f:\n        hash_md5 = hashlib.md5(f.read()).hexdigest()\n    is_skip_test = hash_md5 == '0b0fffdc0e88be226673846a143bb3e0'\n    print('is_skip_test:',is_skip_test)\n\n#---\nprint('data_dir', data_dir)\nprint('valid_id', valid_id)\n\ndef do_binarise(m, threshold=0.5):\n    m = m-m.min()\n    m = m/(m.max()+1e-7)\n    m = (m>threshold).astype(np.float32)\n    return m\n\ndef read_data(fragment_id, z0=CFG.infer_fragment_z[0], z1=CFG.infer_fragment_z[1]):\n    volume = []\n    start_timer = timer()\n    for i in range(z0,z1):\n        v = np.array(Image.open(f'{data_dir}/{fragment_id}/surface_volume/{i:02d}.tif'), dtype=np.uint16)\n        v = (v >> 8).astype(np.uint8)\n        #v = (v / 65535.0 * 255).astype(np.uint8)\n        volume.append(v)\n        print(f'\\r @ read_data(): volume{fragment_id}  {time_to_str(timer() - start_timer, \"sec\")}', end='', flush=True)\n    #print('')\n    volume = np.stack(volume, -1)\n    height, width, depth = volume.shape\n    #print(f'fragment_id={fragment_id} volume: {volume.shape}')\n\n    #---\n    mask = cv2.imread(f'{data_dir}/{fragment_id}/mask.png',cv2.IMREAD_GRAYSCALE)\n    mask = do_binarise(mask)\n\n    if 'train' in CFG.mode:\n        ir    = cv2.imread(f'{data_dir}/{fragment_id}/ir.png',cv2.IMREAD_GRAYSCALE)\n        label = cv2.imread(f'{data_dir}/{fragment_id}/inklabels.png',cv2.IMREAD_GRAYSCALE)\n        ir    = ir/255\n        label = do_binarise(label)\n\n    if 'test' in CFG.mode:\n        ir = None\n        label = None\n\n    d = dotdict(\n        fragment_id = fragment_id,\n        volume = volume,\n        ir     = ir,\n        label  = label,\n        mask   = mask,\n    )\n    return d\n\ndef read_data1(fragment_id):\n    if fragment_id=='2a':\n        y = 9456\n        d = read_data('2')\n        d = dotdict(\n            fragment_id='2a',\n            volume  = d.volume[:y],\n            ir      = d.ir[:y],\n            label   = d.label[:y],\n            mask    = d.mask[:y],\n        )\n    elif  fragment_id=='2b':\n        y = 9456\n        d = read_data('2')\n        d = dotdict(\n            fragment_id='2b',\n            volume  = d.volume[y:],\n            ir      = d.ir[y:],\n            label   = d.label[y:],\n            mask    = d.mask[y:],\n        )\n    elif  fragment_id=='2aa':\n        y0,y1 = 0, 7074\n        d = read_data('2')\n        d = dotdict(\n            fragment_id='2aa',\n            volume  = d.volume[y0:y1],\n            ir      = d.ir[y0:y1],\n            label   = d.label[y0:y1],\n            mask    = d.mask[y0:y1],\n        )\n\n\n    else:\n        d = read_data(fragment_id)\n    return d\n\ndef run_check_data():\n    d=read_data1(valid_id[0])#valid_id[0]\n    print('')\n    print('fragment_id:', d.fragment_id)\n    print('volume:', d.volume.shape, d.volume.min(), d.volume.max())\n    print('mask  :', d.mask.shape, d.mask.min(), d.mask.max())\n    if 'train' in CFG.mode:\n        print('ir    :', d.ir.shape, d.ir.min(), d.ir.max())\n        print('label :', d.label.shape, d.label.min(), d.label.max())\n\n#run_check_data()\nprint('data ok !!!')","metadata":{"execution":{"iopub.status.busy":"2023-06-03T10:43:30.879375Z","iopub.execute_input":"2023-06-03T10:43:30.880211Z","iopub.status.idle":"2023-06-03T10:43:30.903906Z","shell.execute_reply.started":"2023-06-03T10:43:30.880176Z","shell.execute_reply":"2023-06-03T10:43:30.902577Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"###### infer here !!!!\n\ndef make_infer_mask():\n    s = CFG.crop_size\n    f = CFG.crop_fade\n    x = np.linspace(-1, 1, s)\n    y = np.linspace(-1, 1, s)\n    xx, yy = np.meshgrid(x, y)\n    d = 1 - np.maximum(np.abs(xx), np.abs(yy))\n    d1 = np.clip(d, 0, f / s * 2)\n    d1 = d1 / d1.max()\n    infer_mask = d1\n    return infer_mask\n\n\n\ndef infer_one(net, d, batch_size=8):\n\n    #get coord\n    crop_size  = CFG.crop_size\n    stride = CFG.stride\n    H,W,D  = d.volume.shape\n\n    ##pad #assume H,W >size\n    px, py = W % stride, H % stride\n    if (px != 0) or (py != 0):\n        px = stride - px\n        py = stride - py\n        pad_volume = np.pad(d.volume, [(0, py), (0, px), (0, 0)], constant_values=0)\n    else:\n        pad_volume = d.volume\n\n    pH, pW, _ = pad_volume.shape\n    x = np.arange(0, pW - crop_size + 1, stride)\n    y = np.arange(0, pH - crop_size + 1, stride)\n    x, y = np.meshgrid(x, y)\n    xy = np.stack([x, y], -1).reshape(-1, 2)\n    print('H,W,pH,pW,len(xy)', H, W, pH, pW, len(xy))\n\n\n    infer_mask = make_infer_mask()\n\n    #----\n    batch_iter = []\n    for t in range(0,len(xy),batch_size):\n        batch_iter.append(xy[t:t+batch_size])\n\n\n    probability = np.zeros((pH,pW))\n    count = np.zeros((pH,pW))\n\n    num_net = len(net)\n    for i in range(num_net):\n        nnet = net[i].cuda()\n        nnet = net[i].eval()\n\n        #---\n        start_timer = timer()\n        for t, xy0 in enumerate(batch_iter):\n            #print('\\r', t, len(batch_iter), end='')\n\n            volume =[]\n            for x0,y0 in xy0 :\n                v = pad_volume[y0:y0 + crop_size, x0:x0 + crop_size]\n                volume.append(v)\n            volume = np.stack(volume)\n            volume = np.ascontiguousarray(volume.transpose(0,3,1,2))\n            volume = volume/255\n            volume = torch.from_numpy(volume).float().cuda()\n            ##print(volume.shape)\n\n            batch = { 'volume': volume }\n            k = 0\n            c = 0\n            with torch.no_grad():\n                with torch.cuda.amp.autocast(enabled=True):\n\n                    if not CFG.rot_tta:\n                        output = nnet(batch)\n                        k += output['ink'].data.cpu().numpy()\n                        c += 1\n\n                    #--\n                    if CFG.rot_tta: #tta\n                        pass\n                        v = [\n                            volume,\n                            torch.rot90(volume, k=1, dims=(-2, -1)),\n                            torch.rot90(volume, k=2, dims=(-2, -1)),\n                            torch.rot90(volume, k=3, dims=(-2, -1)),\n                        ]\n                        K=len(v)\n                        batch = {\n                            'volume': torch.cat(v,0)\n                        }\n                        output = nnet(batch)\n                        ink = output['ink']\n\n                        B,_,h,w = volume.shape\n                        ink = ink.reshape(K, B, 1, h, w)\n                        ink = [\n                            ink[0],\n                            torch.rot90(ink[1], k=-1, dims=(-2, -1)),\n                            torch.rot90(ink[2], k=-2, dims=(-2, -1)),\n                            torch.rot90(ink[3], k=-3, dims=(-2, -1)),\n                        ]\n                        ink = torch.stack(ink, dim=0)\n                        ink = ink.mean(0)\n\n                        k += ink.data.cpu().numpy()\n                        c += 1\n                    #--\n            k = k/c\n            ##print(k.shape)\n            for b in range(len(k)):\n                x0,y0 = xy0[b]\n                probability[y0:y0 + crop_size, x0:x0 + crop_size] += k[b,0]*infer_mask\n                count[y0:y0 + crop_size, x0:x0 + crop_size] += infer_mask\n            print(f'\\r net[{i}] @infer_one(): {t} / {len(batch_iter)} : {time_to_str(timer() - start_timer, \"sec\")}', end='', flush=True)\n\n    print('')\n    probability = probability/(count+0.000001)\n    probability = probability[:H,:W]\n    probability = probability*d.mask\n    return probability\n\n\n######################################\nimport sys\nsys.path.append('/kaggle/input/ink-00')\n# from my_model_05 import Net as Resnet34\n# from my_model_06 import Net as Resnet50\n\nfrom my_model_07 import Net as Resnet34MeanPool\n\nfrom my_model_07 import *\nrun_check_net()\n\n\n######################################\nif ('skip_fake_test' in CFG.mode) and (is_skip_test):\n    submit_df = pd.DataFrame({\n        'Id': valid_id,\n        'Predicted':['1 2', '1 2']\n    })\nelse:\n    model = [\n#[ Resnet34, '/kaggle/input/ink-weight-05/00015548.model.pth'],\n#[ Resnet50, '/kaggle/input/ink-weight-05/00011952.model.pth'],\n[ Resnet34MeanPool, '/kaggle/input/ink-weight-05/fold1-Resnet34MeanPool.00018924.model.pth'],\n\n]\n \n\n    #----\n    net = []\n    for i,(Net,checkpoint) in enumerate(model):\n        print(checkpoint)\n        n = Net()\n        f = torch.load(checkpoint, map_location=lambda storage, loc: storage)\n        print(n.load_state_dict(f['state_dict'], strict=False))  # True\n        net.append(n)\n\n    #----\n    print(cfg_to_text())\n    print('')\n    submission = defaultdict(list)\n    for t,fragment_id in enumerate(valid_id):\n        d = read_data1(fragment_id)\n\n        print('==================================')\n        print('fragment_id', d.fragment_id)\n        print('\\tmask', d.mask.shape)\n        print('\\tvolume', d.volume.shape)\n        print('CFG.stride', CFG.stride)\n        print('CFG.crop_size', CFG.crop_size)  \n        print('')\n\n        probability = infer_one(net, d)\n        print('probability', probability.shape)\n\n        probability = d.mask*probability\n        predict = (probability>0.55).astype(np.uint8)\n\n        #----\n        submission['Id'].append(fragment_id)\n        submission['Predicted'].append(mask_to_rle(predict))\n\n        #----\n        probability8 = (probability * 255).astype(np.uint8)\n        plt.figure(t), plt.imshow(probability8, cmap='gray')\n        #plt.waitforbuttonpress()\n        if 'train' in CFG.mode:\n            text = metric_to_text(probability, d.label, d.mask)\n            print(text)\n        print('')\n\n    print('')\n    submit_df = pd.DataFrame.from_dict(submission)\n\nprint('')\nprint(cfg_to_text())\nsubmit_df.to_csv('submission.csv', index=False)\nprint(submit_df)\nprint('submission.csv ok!!!')\n\n ","metadata":{"execution":{"iopub.status.busy":"2023-06-03T10:43:30.906710Z","iopub.execute_input":"2023-06-03T10:43:30.907187Z","iopub.status.idle":"2023-06-03T11:03:31.980993Z","shell.execute_reply.started":"2023-06-03T10:43:30.907154Z","shell.execute_reply":"2023-06-03T11:03:31.980073Z"},"trusted":true},"execution_count":null,"outputs":[]},{"cell_type":"code","source":"'''\n/kaggle/input/ink-weight-05/fold1-Resnet34MeanPool.00018924.model.pth\n_IncompatibleKeys(missing_keys=['aux.0.weight', 'aux.0.bias', 'aux.1.weight', 'aux.1.bias', 'aux.2.weight', 'aux.2.bias', 'aux.3.weight', 'aux.3.bias', 'aux.4.weight', 'aux.4.bias'], unexpected_keys=[])\nCFG\n\tvalid_threshold : 0.8\n\tbeta : 1\n\tcrop_fade : 32\n\tcrop_size : 256\n\tcrop_depth : 5\n\tinfer_fragment_z : [0, 32]\n\tdz : 0\n\trot_tta : True\n\tstride : 64\n\n @ read_data(): volume1   0 min 49 sec==================================\nfragment_id 1\n\tmask (8181, 6330)\n\tvolume (8181, 6330, 32)\nCFG.stride 64\nCFG.crop_size 256\n\nH,W,pH,pW,len(xy) 8181 6330 8192 6336 12000\n net[0] @infer_one(): 1499 / 1500 : 18 min 41 sec\nprobability (8181, 6330)\nbce=0.19801\np_sum  th   prec   recall   fpr   dice   score\n-----------------------------------------------\n0.56, 0.10, 0.292, 0.898, 0.251,  0.441,  0.339\n0.36, 0.20, 0.393, 0.763, 0.136,  0.518,  0.436\n0.24, 0.30, 0.501, 0.650, 0.075,  0.566,  0.526\n0.15, 0.40, 0.628, 0.524, 0.036,  0.571,  0.605\n0.09, 0.50, 0.761, 0.388, 0.014,  0.514,  0.639\n0.05, 0.60, 0.864, 0.244, 0.004,  0.381,  0.575\n0.02, 0.70, 0.931, 0.099, 0.001,  0.179,  0.350\n0.00, 0.80, 0.998, 0.012, 0.000,  0.023,  0.060\n0.00, 0.90, 0.000, 0.000, 0.000,  0.000,  0.001\n\n\n\nCFG\n\tvalid_threshold : 0.8\n\tbeta : 1\n\tcrop_fade : 32\n\tcrop_size : 256\n\tcrop_depth : 5\n\tinfer_fragment_z : [0, 32]\n\tdz : 0\n\trot_tta : True\n\tstride : 64\n  Id                                          Predicted\n0  1  732898 4 732928 15 739227 7 739255 28 745555 1...\nsubmission.csv ok!!!\n\n'''","metadata":{"execution":{"iopub.status.busy":"2023-06-03T11:03:31.982059Z","iopub.execute_input":"2023-06-03T11:03:31.982634Z","iopub.status.idle":"2023-06-03T11:03:31.989315Z","shell.execute_reply.started":"2023-06-03T11:03:31.982591Z","shell.execute_reply":"2023-06-03T11:03:31.988346Z"},"trusted":true},"execution_count":null,"outputs":[]}]}