{"id":21525932,"url":"https://github.com/sraashis/deepdyn","last_synced_at":"2025-06-11T08:38:00.184Z","repository":{"id":29467380,"uuid":"103179201","full_name":"sraashis/deepdyn","owner":"sraashis","description":"pytorch implementation of paper https://www.frontiersin.org/articles/10.3389/fcomp.2020.00035/full","archived":false,"fork":false,"pushed_at":"2022-12-08T04:20:58.000Z","size":310706,"stargazers_count":63,"open_issues_count":19,"forks_count":22,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-24T01:12:40.022Z","etag":null,"topics":["centralized-image-processing","computer-vision","convolutional-neural-networks","cross-validation","custom-data-loader-pytorch","custom-dataloader","fundus-image","graph-algorithms","image-procesing","machine-learning","multiple-gpu","pytorch","pytorch-implementation","pytorch-vizualization","retinal-vessel-segmentation","u-net","unet","universal-pytorch-framework","vessel-segmentation"],"latest_commit_sha":null,"homepage":"","language":"Jupyter Notebook","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sraashis.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-09-11T19:33:05.000Z","updated_at":"2024-04-12T12:40:45.000Z","dependencies_parsed_at":"2023-01-14T15:00:52.857Z","dependency_job_id":null,"html_url":"https://github.com/sraashis/deepdyn","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sraashis%2Fdeepdyn","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sraashis%2Fdeepdyn/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sraashis%2Fdeepdyn/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sraashis%2Fdeepdyn/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sraashis","download_url":"https://codeload.github.com/sraashis/deepdyn/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248126964,"owners_count":21052115,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["centralized-image-processing","computer-vision","convolutional-neural-networks","cross-validation","custom-data-loader-pytorch","custom-dataloader","fundus-image","graph-algorithms","image-procesing","machine-learning","multiple-gpu","pytorch","pytorch-implementation","pytorch-vizualization","retinal-vessel-segmentation","u-net","unet","universal-pytorch-framework","vessel-segmentation"],"created_at":"2024-11-24T01:39:23.703Z","updated_at":"2025-04-09T23:23:46.428Z","avatar_url":"https://github.com/sraashis.png","language":"Jupyter Notebook","funding_links":[],"categories":[],"sub_categories":[],"readme":"Implementation of Deep Dynamic Networks for Retinal Vessel Segmentation (https://arxiv.org/abs/1903.07803)\n\n# A pytorch based framework for medical image processing with Convolutional Neural Network. \nAlong with example of unet for DRIVE dataset segmentation [1]. DRIVE dataset is composed of 40 retinal fundus images.\n\n### ***Update Jul 30, 2020: Please check a better, and pip installable version of the framework with an example over [Here](https://github.com/sraashis/easytorchexample).***\n\n## Required dependencies\n\nWe need python3, numpy, pandas, pytorch, torchvision, matplotlib and PILLOW packages\n\n```\npip install -r deepdyn/assets/requirements.txt\n```\n\n![Flow](assets/flow_ature.png)\n\n\n## Project Structure\n\n* [deepdyn/torchtrainer](https://github.com/sraashis/deepdyn/tree/master/nbee) framework core.\n* [deepdyn/utils](https://github.com/sraashis/deepdyn/tree/master/utils) Utilities for dealing with F1-score, image cropping, slicing, visual precision-recall, auto split train-validation-test set and many more.\n* [deepdyn/viz](https://github.com/sraashis/deepdyn/tree/master/viz) Easy pytorch visualization.\n* [deepdyn/testarch](https://github.com/sraashis/deepdyn/tree/master/nbee) Full end to end working [u-net(Olaf Ronneberger et al.)](https://arxiv.org/abs/1505.04597) and MINI-UNET as per Deep Dynamic(https://arxiv.org/abs/1903.07803) paper\nfor more robust retinal image segmentation.\n* [deepdyn/data](https://github.com/sraashis/deepdyn/tree/master/data) DRIVE dataset..\n\n## Dataset check\nOriginal image and respective ground-truth image. Ground-truth is a binary image with each vessel pixel(white) 255\n and background(black) 0.\n![Sample DRIVE image](assets/merged_drive.png)\n\n#### [U-net architecture link](https://arxiv.org/abs/1505.04597)\n![Unet](assets/unet.png)\n\n## Usage\nExample **main.py**\n```python\nimport testarch.unet as unet\nimport testarch.unet.runs as r_unet\nimport testarch.miniunet as mini_unet\nimport testarch.miniunet.runs as r_miniunet\nimport torchvision.transforms as tmf\n\n\ntransforms = tmf.Compose([\n    tmf.ToPILImage(),\n    tmf.ToTensor()\n])\n\nif __name__ == \"__main__\":\n    unet.run([r_unet.DRIVE], transforms)\n    mini_unet.run([r_miniunet.DRIVE], transforms)\n```\nWhere ***testarch.unet.runs*** file consist a predefined configuration  ***DRIVE*** with all necessary parameters.\n```python\nimport os\nsep = os.sep\nDRIVE = {\n    'Params': {\n        'num_channels': 1,\n        'num_classes': 2,\n        'batch_size': 4,\n        'epochs': 250,\n        'learning_rate': 0.001,\n        'patch_shape': (388, 388),\n        'patch_offset': (150, 150),\n        'expand_patch_by': (184, 184),\n        'use_gpu': True,\n        'distribute': True,\n        'shuffle': True,\n        'log_frequency': 5,\n        'validation_frequency': 1,\n        'mode': 'train',\n        'parallel_trained': False,\n    },\n    'Dirs': {\n        'image': 'data' + sep + 'DRIVE' + sep + 'images',\n        'mask': 'data' + sep + 'DRIVE' + sep + 'mask',\n        'truth': 'data' + sep + 'DRIVE' + sep + 'manual',\n        'logs': 'logs' + sep + 'DRIVE' + sep + 'UNET',\n        'splits_json': 'data' + sep + 'DRIVE' + sep + 'splits'\n    },\n\n    'Funcs': {\n        'truth_getter': lambda file_name: file_name.split('_')[0] + '_manual1.gif',\n        'mask_getter': lambda file_name: file_name.split('_')[0] + '_mask.gif',\n        'dparm': lambda x: np.random.choice(np.arange(1, 101, 1), 2)\n    }\n}\n```\nSimilarly, ***testarch.miniunet.runs*** file consist a predefined configuration  ***DRIVE*** with all necessary parameters. \n***NOTE: Make sure it picks up probability-maps from the logs of previous run.***\n\n```python\nimport os\nsep = os.sep\nDRIVE = {\n    'Params': {\n        'num_channels': 2,\n        'num_classes': 2,\n        'batch_size': 4,\n        'epochs': 100,\n        'learning_rate': 0.001,\n        'patch_shape': (100, 100),\n        'expand_patch_by': (40, 40)\n        'use_gpu': True,\n        'distribute': True,\n        'shuffle': True,\n        'log_frequency': 20,\n        'validation_frequency': 1,\n        'mode': 'train',\n        'parallel_trained': False\n    },\n    'Dirs': {\n        'image': 'data' + sep + 'DRIVE' + sep + 'images',\n        'image_unet': 'logs' + sep + 'DRIVE' + sep + 'UNET',\n        'mask': 'data' + sep + 'DRIVE' + sep + 'mask',\n        'truth': 'data' + sep + 'DRIVE' + sep + 'manual',\n        'logs': 'logs' + sep + 'DRIVE' + sep + 'MINI-UNET',\n        'splits_json': 'data' + sep + 'DRIVE' + sep + 'splits'\n    },\n\n    'Funcs': {\n        'truth_getter': lambda file_name: file_name.split('_')[0] + '_manual1.gif',\n        'mask_getter': lambda file_name: file_name.split('_')[0] + '_mask.gif'\n    }\n}\n```\n\n- **num_channels**: Input channels to the CNN. We are only feeding the green channel to unet.\n- **num_classes**: Output classes from CNN. We have vessel, background.\n- **patch_shape, expand_patch_by**: Unet takes 388 * 388 patch but also looks at 184 pixel on each dimension equally to make it 572 * 572. We mirror image if we run to image edges when expanding.\n So 572 * 572 goes in 388 * 388 * 2 comes out.\n- **patch_offset**: Overlap between two input patches. We get more data doing this.\n- **distribute**: Uses all gpu in parallel if set to True. [WARN]torch.cuda.set_device(1) Mustn't be done if set to True.\n- **shuffle**: Shuffle train data after every epoch.\n- **log_frequency**: Just print log after this number of batches with average scores. No rocket science :).\n- **validation_frequency**: Do validation after this number of epochs. We also persist the best performing model.\n- **mode**: train/test.\n- **parallel_trained**: If a resumed model was parallel trained or not.\n- **logs**: Dir for all logs\n- **splits_json**: A directory that consist of json files with list of files with keys 'train', 'test'\n'validation'. (https://github.com/sraashis/deepdyn/blob/master/utils/auto_split.py) takes a folder with all images and does that automatically. This is handy when we want to do k-fold cross validation. We jsut have to generate such k json files and put in splits_json folder. \n- **truth_getter, mask_getter**: A custom function that maps input_image to its ground_truth and mask respectively.\n\n## Sample log\n```text\nworkstation$ python main.py \nTotal Params: 31042434\n### SPLIT FOUND:  data/DRIVE/splits/UNET-DRIVE.json Loaded\nPatches: 135\nPatches: 9\nPatches: 9\nPatches: 9\nPatches: 9\nPatches: 9\nTraining...\nEpochs[1/40] Batch[5/34] loss:0.72354 pre:0.326 rec:0.866 f1:0.473 acc:0.833\nEpochs[1/40] Batch[10/34] loss:0.34364 pre:0.584 rec:0.638 f1:0.610 acc:0.912\nEpochs[1/40] Batch[15/34] loss:0.22827 pre:0.804 rec:0.565 f1:0.664 acc:0.939\nEpochs[1/40] Batch[20/34] loss:0.19549 pre:0.818 rec:0.629 f1:0.711 acc:0.947\nEpochs[1/40] Batch[25/34] loss:0.17726 pre:0.713 rec:0.741 f1:0.727 acc:0.954\nEpochs[1/40] Batch[30/34] loss:0.16564 pre:0.868 rec:0.691 f1:0.770 acc:0.946\nRunning validation..\n21_training.tif  PRF1A [0.66146, 0.37939, 0.4822, 0.93911]\n39_training.tif  PRF1A [0.79561, 0.28355, 0.41809, 0.93219]\n37_training.tif  PRF1A [0.78338, 0.47221, 0.58924, 0.94245]\n35_training.tif  PRF1A [0.83836, 0.45788, 0.59228, 0.94534]\n38_training.tif  PRF1A [0.64682, 0.26709, 0.37807, 0.92416]\nScore improved:  0.0 to 0.49741 BEST CHECKPOINT SAVED\nEpochs[2/40] Batch[5/34] loss:0.41760 pre:0.983 rec:0.243 f1:0.389 acc:0.916\nEpochs[2/40] Batch[10/34] loss:0.27762 pre:0.999 rec:0.025 f1:0.049 acc:0.916\nEpochs[2/40] Batch[15/34] loss:0.25742 pre:0.982 rec:0.049 f1:0.093 acc:0.886\nEpochs[2/40] Batch[20/34] loss:0.23239 pre:0.774 rec:0.421 f1:0.545 acc:0.928\nEpochs[2/40] Batch[25/34] loss:0.23667 pre:0.756 rec:0.506 f1:0.607 acc:0.930\nEpochs[2/40] Batch[30/34] loss:0.19529 pre:0.936 rec:0.343 f1:0.502 acc:0.923\nRunning validation..\n21_training.tif  PRF1A [0.95381, 0.45304, 0.6143, 0.95749]\n39_training.tif  PRF1A [0.84353, 0.48988, 0.6198, 0.94837]\n37_training.tif  PRF1A [0.8621, 0.60001, 0.70757, 0.95665]\n35_training.tif  PRF1A [0.86854, 0.64861, 0.74263, 0.96102]\n38_training.tif  PRF1A [0.93073, 0.28781, 0.43966, 0.93669]\nScore improved:  0.49741 to 0.63598 BEST CHECKPOINT SAVED\n...\n```\n## Results\nThe network is trained for 40 epochs with 15 training images, 5 validation images and 20 test images.\n![Training_Loss](assets/loss.png)\n![Training_Scores](assets/training_f1_acc.png)\nFigure above is the training cross-entropy loss, F1, and accuracy.\n![Precision-Recall color-Map](assets/train_pr_map.png)\nFigure above is the precision-recall map for training and validation respectively with color being the training iterations.\n![Validation_scores](assets/val_f1_acc.png)\nFigure above is the validation F1 and Accuracy.\n![Test scores and result](assets/test.png)\nFigure on left is the test result on the test set after training and validation.\nRight one the is the segmentation result on one of the test images.\n\n### Thank you! ❤\n\n#### References\n\n1. J. Staal, M. Abramoff, M. Niemeijer, M. Viergever, and B. van Ginneken, “Ridge based vessel segmentation in color\nimages of the retina,” IEEE Transactions on Medical Imaging 23, 501–509 (2004)\n2. O. Ronneberger, P. Fischer, and T. Brox, “U-net: Convolutional networks for biomedical image segmentation,” inMICCAI,(2015)\n3. Dynamic Deep Networks for Retinal Vessel Segmentation, https://arxiv.org/abs/1903.07803\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsraashis%2Fdeepdyn","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsraashis%2Fdeepdyn","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsraashis%2Fdeepdyn/lists"}