├── .gitignore ├── LICENSE.md ├── README.md ├── demo.ipynb ├── docs ├── AUGMENTATION.md ├── DATASET_ADAPTER.md ├── NEW_METHOD.md ├── NEW_METRIC.md ├── OOD_STRATEGY.md └── datasets │ ├── BCSS.md │ └── DATASET_OVERVIEW.md ├── examples ├── demo.py ├── eval.py ├── evaluation.py ├── model.pth ├── optimizer.pth ├── scheduler.pth └── train.py ├── froodo ├── __init__.py ├── data │ ├── __init__.py │ ├── container │ │ ├── __init__.py │ │ ├── container.py │ │ ├── metadata_container.py │ │ └── requirements.py │ ├── datasets │ │ ├── __init__.py │ │ ├── adapter │ │ │ ├── __init__.py │ │ │ ├── adapter.py │ │ │ └── utils.py │ │ ├── examples │ │ │ ├── __init__.py │ │ │ ├── endoscopy │ │ │ │ └── ksavir.py │ │ │ ├── pathology │ │ │ │ ├── bcss.py │ │ │ │ └── path_mnist.py │ │ │ └── xray │ │ │ │ └── pneumonia.py │ │ ├── interfaces │ │ │ ├── __init__.py │ │ │ ├── augmentation_dataset.py │ │ │ ├── class_leftout_dataset.py │ │ │ ├── concat.py │ │ │ ├── multi_file_overlapping_tiles_dataset.py │ │ │ ├── ood_dataset.py │ │ │ └── sample_dataset.py │ │ └── utils.py │ ├── datatypes.py │ ├── metadata │ │ ├── __init__.py │ │ ├── batch.py │ │ ├── metadata.py │ │ ├── types.py │ │ └── utils.py │ ├── samples │ │ ├── __init__.py │ │ ├── batch.py │ │ └── sample.py │ └── utils.py ├── experiment │ ├── __init__.py │ ├── artifacts │ │ ├── __init__.py │ │ ├── artifact.py │ │ ├── container_artifact.py │ │ ├── keywords.py │ │ ├── metric_artifact.py │ │ └── storage.py │ └── components │ │ ├── __init__.py │ │ ├── component.py │ │ ├── examples │ │ ├── __init__.py │ │ ├── augmentation_ood_eval.py │ │ └── dataset_ood_eval.py │ │ ├── interfaces │ │ ├── __init__.py │ │ └── ood_strategy_component.py │ │ └── metadata.py ├── models │ ├── __init__.py │ ├── classification │ │ ├── __init__.py │ │ └── examples │ │ │ └── resnet50.py │ ├── model.py │ └── segmentation │ │ ├── __init__.py │ │ ├── examples │ │ ├── __init__.py │ │ └── unet.py │ │ ├── segmentation_model.py │ │ └── utils.py ├── ood │ ├── __init__.py │ ├── augmentations │ │ ├── __init__.py │ │ ├── builder.py │ │ ├── endoscopy │ │ │ ├── artifacts │ │ │ │ └── imgs │ │ │ │ │ ├── chili │ │ │ │ │ ├── chili_bright_seed_front.png │ │ │ │ │ ├── chili_bright_seed_side.png │ │ │ │ │ ├── chili_bright_skin_front.png │ │ │ │ │ ├── chili_bright_skin_side.png │ │ │ │ │ ├── chili_dark_seed_front.png │ │ │ │ │ ├── chili_dark_seed_side.png │ │ │ │ │ ├── chili_dark_skin_front.png │ │ │ │ │ └── chili_dark_skin_side.png │ │ │ │ │ ├── coin v2 │ │ │ │ │ ├── coin_bright_1cent_back.png │ │ │ │ │ ├── coin_bright_1cent_front.png │ │ │ │ │ ├── coin_bright_1cent_front_side.png │ │ │ │ │ ├── coin_bright_1euro_front.png │ │ │ │ │ ├── coin_bright_1euro_front_side.png │ │ │ │ │ ├── coin_bright_20cent_front.png │ │ │ │ │ ├── coin_bright_2cent_back.png │ │ │ │ │ ├── coin_bright_2cent_back_side.png │ │ │ │ │ ├── coin_bright_2cent_front.png │ │ │ │ │ ├── coin_dark_1cent_front_side.png │ │ │ │ │ ├── coin_dark_1euro_front.png │ │ │ │ │ ├── coin_dark_1euro_front_side.png │ │ │ │ │ ├── coin_dark_2cent_back.png │ │ │ │ │ └── coin_dark_2cent_back_side.png │ │ │ │ │ ├── coins │ │ │ │ │ ├── 100_Back.png │ │ │ │ │ ├── 100_Front.png │ │ │ │ │ ├── 10_Back.png │ │ │ │ │ ├── 10_Front.png │ │ │ │ │ ├── 1_Back.png │ │ │ │ │ ├── 1_Front.png │ │ │ │ │ ├── 200_Back.png │ │ │ │ │ ├── 200_Front.png │ │ │ │ │ ├── 20_Back.png │ │ │ │ │ ├── 20_Front.png │ │ │ │ │ ├── 2_Back.png │ │ │ │ │ ├── 2_Front.png │ │ │ │ │ ├── 50_Back.png │ │ │ │ │ ├── 50_Front.png │ │ │ │ │ ├── 5_Back.png │ │ │ │ │ └── 5_Front.png │ │ │ │ │ ├── corn │ │ │ │ │ ├── dry │ │ │ │ │ │ ├── corn_dry_1_1.png │ │ │ │ │ │ ├── corn_dry_1_2.png │ │ │ │ │ │ ├── corn_dry_2_1.png │ │ │ │ │ │ ├── corn_dry_2_2.png │ │ │ │ │ │ ├── corn_dry_3_1.png │ │ │ │ │ │ └── corn_dry_3_2.png │ │ │ │ │ ├── mashed │ │ │ │ │ │ ├── corn_mashed_1_1.png │ │ │ │ │ │ └── corn_mashed_1_2.png │ │ │ │ │ └── wet │ │ │ │ │ │ ├── corn_wet_1_1.png │ │ │ │ │ │ └── corn_wet_1_2.png │ │ │ │ │ ├── green onion │ │ │ │ │ ├── go_bright_front.png │ │ │ │ │ ├── go_bright_side.png │ │ │ │ │ ├── go_dark_front.png │ │ │ │ │ └── go_dark_side.png │ │ │ │ │ ├── kidney bean │ │ │ │ │ ├── kb_bright_half1.png │ │ │ │ │ ├── kb_bright_half2.png │ │ │ │ │ ├── kb_bright_half3.png │ │ │ │ │ ├── kb_bright_smashed1.png │ │ │ │ │ ├── kb_bright_smashed2.png │ │ │ │ │ ├── kb_bright_whole.png │ │ │ │ │ ├── kb_dark_half1.png │ │ │ │ │ ├── kb_dark_smashed1.png │ │ │ │ │ └── kb_dark_smashed2.png │ │ │ │ │ ├── melon seed │ │ │ │ │ ├── ms_bright_front.png │ │ │ │ │ ├── ms_bright_side.png │ │ │ │ │ ├── ms_dark_front.png │ │ │ │ │ └── ms_dark_side.png │ │ │ │ │ ├── oats │ │ │ │ │ ├── oats_bright_front.png │ │ │ │ │ ├── oats_bright_side.png │ │ │ │ │ ├── oats_dark_front.png │ │ │ │ │ └── oats_dark_side.png │ │ │ │ │ ├── pill v2 │ │ │ │ │ ├── mg_bright_half_front.png │ │ │ │ │ ├── mg_bright_half_side.png │ │ │ │ │ ├── mg_bright_whole_front.png │ │ │ │ │ ├── mg_bright_whole_side.png │ │ │ │ │ ├── mg_dark_half_front.png │ │ │ │ │ ├── mg_dark_half_side.png │ │ │ │ │ ├── mg_dark_whole_front.png │ │ │ │ │ ├── mg_dark_whole_side.png │ │ │ │ │ ├── vb_bright_half_front.png │ │ │ │ │ ├── vb_bright_half_side.png │ │ │ │ │ ├── vb_bright_whole_front.png │ │ │ │ │ ├── vb_bright_whole_side.png │ │ │ │ │ ├── vb_dark_half_front.png │ │ │ │ │ ├── vb_dark_half_side.png │ │ │ │ │ ├── vb_dark_whole_front.png │ │ │ │ │ └── vb_dark_whole_side.png │ │ │ │ │ ├── pills │ │ │ │ │ └── 20230122_200856.png │ │ │ │ │ └── pumpkin seed │ │ │ │ │ ├── ps_bright_front.png │ │ │ │ │ ├── ps_bright_side.png │ │ │ │ │ ├── ps_dark_front.png │ │ │ │ │ └── ps_dark_side.png │ │ │ ├── blood.py │ │ │ ├── chili.py │ │ │ ├── coin_v2.py │ │ │ ├── coins.py │ │ │ ├── corn.py │ │ │ ├── green_onion.py │ │ │ ├── kidney_bean.py │ │ │ ├── melon_seed.py │ │ │ ├── oats.py │ │ │ ├── pill.py │ │ │ ├── pill_v2.py │ │ │ ├── pumpkin_seed.py │ │ │ ├── random_hue_shifts.py │ │ │ ├── random_value_shifts.py │ │ │ └── vignette.py │ │ ├── indistribution │ │ │ ├── __init__.py │ │ │ ├── crop.py │ │ │ └── resize.py │ │ ├── patchwise │ │ │ ├── __init__.py │ │ │ ├── brightness.py │ │ │ ├── crop.py │ │ │ └── gauss_blur.py │ │ ├── pathology │ │ │ ├── __init__.py │ │ │ ├── artifacts │ │ │ │ ├── __init__.py │ │ │ │ ├── artifacts.py │ │ │ │ ├── blood_cell.py │ │ │ │ ├── blood_group.py │ │ │ │ ├── bubble.py │ │ │ │ ├── dark_spots.py │ │ │ │ ├── fat.py │ │ │ │ ├── imgs │ │ │ │ │ ├── bubble │ │ │ │ │ │ ├── b1.png │ │ │ │ │ │ ├── b10.png │ │ │ │ │ │ ├── b11.png │ │ │ │ │ │ ├── b2.png │ │ │ │ │ │ └── b4.png │ │ │ │ │ ├── cell │ │ │ │ │ │ ├── TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300_1.tif │ │ │ │ │ │ ├── TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300_2.tif │ │ │ │ │ │ ├── TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.2300_1.tif │ │ │ │ │ │ ├── TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300_1.tif │ │ │ │ │ │ ├── TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300_2.tif │ │ │ │ │ │ ├── TCGA-EW-A1P1-DX1_xmin50567_ymin38988_MPP-0.2300_1.tif │ │ │ │ │ │ ├── TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.23001.tif │ │ │ │ │ │ ├── TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.2300_2.tif │ │ │ │ │ │ └── TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.2300_3.tif │ │ │ │ │ ├── dark_spots │ │ │ │ │ │ ├── SP1.png │ │ │ │ │ │ ├── SP2.png │ │ │ │ │ │ ├── SP3.png │ │ │ │ │ │ ├── SP4.png │ │ │ │ │ │ ├── med_spot.png │ │ │ │ │ │ ├── med_spot_2.png │ │ │ │ │ │ ├── med_spot_2_2x.png │ │ │ │ │ │ └── small_spot.png │ │ │ │ │ ├── fat │ │ │ │ │ │ └── fat.png │ │ │ │ │ ├── group │ │ │ │ │ │ ├── TCGA-A7-A26F-DX1_xmin72969_ymin11489_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300.tif │ │ │ │ │ │ ├── TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.23001.tif │ │ │ │ │ │ ├── TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AO-A0J6-DX1_xmin40548_ymin11135_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AQ-A54N-DX1_xmin32440_ymin26558_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AR-A0U1-DX1_xmin63681_ymin24922_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AR-A1AI-DX1_xmin38671_ymin10616_MPP-0.2300.tif │ │ │ │ │ │ ├── TCGA-AR-A1AR-DX1_xmin12708_ymin29100_MPP-0.2300.tif │ │ │ │ │ │ └── TCGA-AR-A1AR-DX1_xmin12708_ymin29100_MPP-0.23001.tif │ │ │ │ │ ├── squamous │ │ │ │ │ │ ├── sq1.png │ │ │ │ │ │ ├── sq10.png │ │ │ │ │ │ ├── sq10s.png │ │ │ │ │ │ ├── sq11.png │ │ │ │ │ │ ├── sq11s.png │ │ │ │ │ │ ├── sq12.png │ │ │ │ │ │ ├── sq12s.png │ │ │ │ │ │ ├── sq13.png │ │ │ │ │ │ ├── sq13s.png │ │ │ │ │ │ ├── sq14.png │ │ │ │ │ │ ├── sq14s.png │ │ │ │ │ │ ├── sq15.png │ │ │ │ │ │ ├── sq15s.png │ │ │ │ │ │ ├── sq16.png │ │ │ │ │ │ ├── sq16s.png │ │ │ │ │ │ ├── sq17.png │ │ │ │ │ │ ├── sq17s.png │ │ │ │ │ │ ├── sq18.png │ │ │ │ │ │ ├── sq18s.png │ │ │ │ │ │ ├── sq19.png │ │ │ │ │ │ ├── sq19s.png │ │ │ │ │ │ ├── sq1s.png │ │ │ │ │ │ ├── sq2.png │ │ │ │ │ │ ├── sq20.png │ │ │ │ │ │ ├── sq20s.png │ │ │ │ │ │ ├── sq2s.png │ │ │ │ │ │ ├── sq3.png │ │ │ │ │ │ ├── sq3s.png │ │ │ │ │ │ ├── sq4.png │ │ │ │ │ │ ├── sq4s.png │ │ │ │ │ │ ├── sq5.png │ │ │ │ │ │ ├── sq5s.png │ │ │ │ │ │ ├── sq6.png │ │ │ │ │ │ ├── sq6s.png │ │ │ │ │ │ ├── sq7.png │ │ │ │ │ │ ├── sq7s.png │ │ │ │ │ │ ├── sq8.png │ │ │ │ │ │ ├── sq8s.png │ │ │ │ │ │ ├── sq9.png │ │ │ │ │ │ └── sq9s.png │ │ │ │ │ └── threads │ │ │ │ │ │ ├── thread_1.png │ │ │ │ │ │ ├── thread_10.png │ │ │ │ │ │ ├── thread_10s.png │ │ │ │ │ │ ├── thread_1s.png │ │ │ │ │ │ ├── thread_2.png │ │ │ │ │ │ ├── thread_2s.png │ │ │ │ │ │ ├── thread_3.png │ │ │ │ │ │ ├── thread_32.png │ │ │ │ │ │ ├── thread_4.png │ │ │ │ │ │ ├── thread_4s.png │ │ │ │ │ │ ├── thread_5.png │ │ │ │ │ │ ├── thread_5s.png │ │ │ │ │ │ ├── thread_6.png │ │ │ │ │ │ ├── thread_6s.png │ │ │ │ │ │ ├── thread_7.png │ │ │ │ │ │ ├── thread_7s.png │ │ │ │ │ │ ├── thread_8.png │ │ │ │ │ │ ├── thread_8s.png │ │ │ │ │ │ ├── thread_9.png │ │ │ │ │ │ └── thread_9s.png │ │ │ │ ├── squamos.py │ │ │ │ └── threads.py │ │ │ └── deforming │ │ │ │ ├── __init__.py │ │ │ │ ├── deformation.py │ │ │ │ ├── imgs │ │ │ │ ├── 7.png │ │ │ │ ├── squeeze │ │ │ │ │ ├── 5.png │ │ │ │ │ └── 6.png │ │ │ │ └── stretch │ │ │ │ │ ├── 5.png │ │ │ │ │ ├── 6.png │ │ │ │ │ └── 7.png │ │ │ │ └── overlap.py │ │ ├── types.py │ │ ├── utility │ │ │ ├── __init__.py │ │ │ ├── composites.py │ │ │ ├── partial.py │ │ │ ├── pipeline.py │ │ │ ├── sampling.py │ │ │ └── util_aug.py │ │ ├── utils.py │ │ └── xray │ │ │ ├── __init__.py │ │ │ ├── artifacts │ │ │ ├── __init__.py │ │ │ ├── coin.py │ │ │ ├── foreign_bodies.py │ │ │ ├── imgs │ │ │ │ ├── coin │ │ │ │ │ ├── coin1.png │ │ │ │ │ └── coin2.png │ │ │ │ ├── foreign │ │ │ │ │ └── nut.png │ │ │ │ ├── nails │ │ │ │ │ └── nail.png │ │ │ │ └── tubes │ │ │ │ │ ├── test1.png │ │ │ │ │ └── test2.png │ │ │ ├── nails.py │ │ │ └── tubes.py │ │ │ ├── gauss_noise.py │ │ │ └── motion_blur.py │ ├── methods │ │ ├── __init__.py │ │ ├── baselines.py │ │ ├── custom.py │ │ ├── energy.py │ │ ├── g_odin.py │ │ ├── max_output.py │ │ ├── mc_dropout.py │ │ ├── odin.py │ │ ├── ood_methods.py │ │ ├── react.py │ │ ├── temp.py │ │ ├── temperature_scaling.py │ │ └── utils.py │ ├── metrics │ │ ├── __init__.py │ │ ├── auroc.py │ │ └── metrics.py │ ├── severity │ │ ├── __init__.py │ │ ├── severity.py │ │ └── utils.py │ └── strategies │ │ ├── __init__.py │ │ ├── augmentation.py │ │ ├── class_leftout.py │ │ ├── ood_dataset.py │ │ └── strategy.py ├── quickstart │ └── __init__.py └── utils │ ├── __init__.py │ └── helper.py ├── imgs ├── FrOoDo.PNG ├── FrOoDo_Logo.png ├── augmentations.png ├── metric.png ├── metric2.png └── samples.png ├── main.ipynb ├── main.py └── requirements.txt /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | 4 | venv 5 | 6 | .idea 7 | mlruns/ 8 | experiments/ 9 | imgs/blood_group_bcss_dice_severity.svg 10 | imgs/bright_bcss_dice_severity.svg 11 | imgs/blood_cell_bcss_dice_severity.svg 12 | imgs/cont_bcss_dice_severity.svg 13 | imgs/dark_bcss_dice_severity.svg 14 | imgs/data_samples_BCSS.pdf 15 | imgs/data_samples_bcss.pdf 16 | imgs/data_samples_PathMNIST.pdf 17 | imgs/data_samples.pdf 18 | imgs/fat_bcss_dice_severity.svg 19 | imgs/gauss_bcss_dice_severity_fcn.svg 20 | imgs/gauss_bcss_dice_severity.svg 21 | imgs/OOD_detection_per_artefact_bcss.svg 22 | imgs/OOD_detection_per_artefact_pathmnist.svg 23 | imgs/OOD_detection_per_artefact.svg 24 | imgs/OOD_detection_per_severity_pathmnist.svg 25 | imgs/OODaug_bcss_dice_severity_fcn.svg 26 | imgs/OODaug_bcss_dice_severity_fcn2.svg 27 | imgs/OODaug_PathMNIST_Acc_severity.svg 28 | imgs/OODaug_pathmnist_dice_severity2.svg 29 | imgs/squam_bcss_dice_severity.svg 30 | imgs/thre_bcss_dice_severity.svg 31 | froodo/ood/methods/ow_mahalanobis.py 32 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Moritz Fuchs and Jonathan Stieber 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /docs/DATASET_ADAPTER.md: -------------------------------------------------------------------------------- 1 | # Dataset adaptation 2 | 3 | To make FrOoDo flexible and able to handle your specific problem with your dataset, it is possible to use any dataset as long as you use a dataset adapter. 4 | 5 | ## SampleDataset 6 | To use own datasets you need to adapt your dataset to a SampleDataset. This can be done by a dataset adapter which is essentially an own dataset with only the purpose to translate the dataset output from your dataset to the SampleDataset. 7 | 8 | A SampleDataset is a FrOoDo specific dataset which returns an object of the class Sample. A Sample consist out of three objects: 9 | 10 | - The image: Image tensor. All augmentations will be applied on the image 11 | - The label_dict: Default dictionary that contains information abut the labels e.g. the segmentation mask, the ood mask or the class label 12 | - The metadata: The metadata object is like a default dict and saves relevant information about an image e.g. OOD status, ignore index, OOD reason 13 | 14 | 15 | 16 | ## Built-In Adapters 17 | 18 | The easiest way to adapt your dataset is to use the GeneralDatasetAdapter and provide a remapping if necessary. 19 | 20 | ```python 21 | # create remapping with helper function 22 | remapping = create_mapping_dict(image=0, segmentation_mask=1) 23 | 24 | # use GeneralDatasetAdapter and remapping to adapt any dataset 25 | adapter = GeneralDatasetAdapter(my_dataset, remapping=remapping) 26 | 27 | # test if adaptation worked 28 | dataset.sample() 29 | ``` 30 | 31 | The GeneralAdapter will try to find the best adapter according to your inputs and your remapping. Of course you can also use one of the specialized Adapters: 32 | 33 | ```python 34 | # use this if your dataset already returns a tuple of image, a label dictionary and optionally metadata 35 | adapter = ImageLabelMetaAdapter(my_dataset) 36 | 37 | # use this adapter if your dataset returns a tuple of tensors 38 | adapter = PositionalAdapter(my_dataset, remapping = {"image": 0, "segmentation_mask": 1}) 39 | 40 | # use this adapter if your dataset returns a dictionary 41 | adapter = DatasetWithAllInOneDictAdapter(my_dataset, remapping= { 42 | "image": "img", 43 | "segmentation_mask": "mask" 44 | }) 45 | ``` 46 | 47 | ## Remapping 48 | 49 | FrOoDo already has some standard remapping keys which should not be changed. 50 | 51 | Keywords | Type | Function | Usage in Component 52 | -- | -- | -- | -- 53 | image | torch.Tensor | image tensor | [OOD Evaluation](../froodo/experiment/components/interfaces/ood_strategy_component.py), Segmentation Performance 54 | segmantation_mask | torch.Tensor |segmentation mask of the image | Segmentation Performance 55 | ood_mask | torch.Tensor |OOD mask for the image (contains only 0,1 and ignore index) | [OOD Evaluation](../froodo/experiment/components/interfaces/ood_strategy_component.py) 56 | class_label | | | [OOD Evaluation](../froodo/experiment/components/interfaces/ood_strategy_component.py), Classification Performance 57 | metadata | froodo.SampleMetadata | metadata object to save meta information about the image | [OOD Evaluation](../froodo/experiment/components/interfaces/ood_strategy_component.py) 58 | 59 | 60 | ## Create your own adapter 61 | 62 | If none of the predefined Adapters should suit your dataset you can easily create an own adapter. The Adapter Class looks like this: 63 | 64 | 65 | ```python 66 | # Adapter 67 | class DatasetAdapter(Dataset, SampleDataset): 68 | def __init__(self, dataset, **kwargs) -> None: 69 | self.dataset = dataset 70 | self.metadata_args = kwargs 71 | 72 | def _add_metadata_args(self, sample: Sample) -> Sample: 73 | sample.metadata.data.update(self.metadata_args) 74 | return sample 75 | 76 | def __len__(self): 77 | return len(self.dataset) 78 | 79 | def __getitem__(self, index) -> Sample: 80 | raise NotImplementedError("Please Implement this method") 81 | ``` -------------------------------------------------------------------------------- /docs/NEW_METHOD.md: -------------------------------------------------------------------------------- 1 | 2 | # Add new Method 3 | 4 | A new Method for OOD Detection needs to be an instance of Class OODMethod. As shown below the only methods that must be specified is the calculate_ood_score method which returns a batch of scores (classification) or masks of scores (Segmentation) for a Sample Batch. 5 | ```python 6 | class OODMethod: 7 | def __init__(self, hyperparams={}) -> None: 8 | pass 9 | 10 | def get_params(self, dict=False): 11 | return "no params" if not dict else {} 12 | 13 | def display_name(self) -> str: 14 | return f"{type(self).__name__}" 15 | 16 | def modify_net(self, net): 17 | return net 18 | 19 | def remodify_net(self, net): 20 | return net 21 | 22 | def calculate_ood_score(self, imgs, net, batch=None): 23 | raise NotImplementedError("Please Implement this method") 24 | 25 | def _set_metadata(self, batch: Batch, scores) -> Batch: 26 | batch["metadata"].append_to_keyed_dict( 27 | SampleMetadataCommonTypes.OOD_SCORE.name, 28 | self.display_name(), 29 | scores, 30 | ) 31 | return batch 32 | 33 | def __call__( 34 | self, 35 | batch: Batch, 36 | net, 37 | task_type: TaskType = TaskType.SEGMENTATION, 38 | remove_ignore_index: bool = True, 39 | score_reduction_method: Callable = np.mean, 40 | ) -> Sample: 41 | # modify network if needed 42 | net = self.modify_net(net) 43 | 44 | scores = self.calculate_ood_score(batch.image, net, batch).numpy() 45 | 46 | ########################## 47 | # POSTPROCESSING removed # 48 | ########################## 49 | 50 | # save scores in metadata to later be accessed by the metrics 51 | batch = self._set_metadata(batch, scores) 52 | 53 | # always remodify network so it works properly for other mothods 54 | self.remodify_net(net) 55 | 56 | return batch 57 | 58 | 59 | ``` -------------------------------------------------------------------------------- /docs/NEW_METRIC.md: -------------------------------------------------------------------------------- 1 | 2 | # Add new MetricGroup 3 | 4 | ```python 5 | class MetricGroup: 6 | def __init__(self) -> None: 7 | pass 8 | 9 | def requires(self) -> List[Container]: 10 | raise NotImplementedError("Please Implement this method") 11 | 12 | def __call__(self, data_container: List[Container], experiment_metadata: dict): 13 | raise NotImplementedError("Please Implement this method") 14 | 15 | def present(self, **kwargs): 16 | pass 17 | ``` 18 | -------------------------------------------------------------------------------- /docs/OOD_STRATEGY.md: -------------------------------------------------------------------------------- 1 | # FrOoDo's Out-of-Distribution Strategies 2 | 3 | An OOD Strategy is the way how the OOD Data is generated or determined. It is therefore a important building block of OOD experiments that rely on both In and OOD data. 4 | 5 | Strategy | OOD Data origin | Description 6 | :-- | :-- | :-- 7 | Augmentation Strategy | OODAugmentation, that corrupts an In-Distribution image into an OOD image e.g. tissue artifacts | The augmentation strategy creates an AugmentationDataset that determines by chance which image is augmented and which is left unchanged. 8 | OOD Dataset Strategy | A whole Dataset is being used as OOD data | In the OOD Dataset strategy the type of data (OOD or IN) is only defined by the dataset from which an image is being taken. All data from the OOD Dataset will be marked as OOD Data. Warning: The Data of the In distribution dataset will not be checked whether the images are truly In-Distribution. 9 | 10 | ## Build an own strategy 11 | 12 | To build an own strategy you just need to implement a class that inherits the OODStrategy class: 13 | 14 | ```python 15 | class OODStrategy: 16 | def get_dataloader(self, **dataloader_kwargs): 17 | return DataLoader(self.dataset, collate_fn=sample_collate, **dataloader_kwargs) 18 | ``` 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/datasets/BCSS.md: -------------------------------------------------------------------------------- 1 | # How to setup BCSS dataset for FrOoDo's build-in BCSS interface 2 | 3 | ## Disclaimer 4 | It is **not mandatory to use the built-in dataset class** to use it within the framework. Therefore, you can write your own dataset and use a dataset adapter. This docu is meant to quickly set up BCSS dataset to run the demo on it. 5 | 6 | ## Let's start 7 | 8 | Please download the BCSS dataset [1] files following the instructions of the github repository: https://github.com/PathologyDataScience/BCSS. 9 | 10 | To use the built-in BCSS Dataset classes the files need to be converted into tif files. You can use the static method of the MultiFileOverlappingTilesDataset to do that. 11 | 12 | ```python 13 | from froodo.quickstart import * 14 | 15 | MultiFileOverlappingTilesDataset.save_as_tif( 16 | raw_folder = "folder to downloaded raw files", 17 | tif_folder = "folder where you want the tif images" 18 | ) 19 | ``` 20 | 21 | Now that you have the files in the correct format, you can use the MultiFileOverlappingTileDataset Class to load the BCSS Dataset. 22 | 23 | ```python 24 | bcss_dataset = MultiFileOverlappingTilesDataset( 25 | folder="path to tif folder", 26 | tile_folder="path where tile config is saved", 27 | size=(620, 620), 28 | dataset_name="bcss", 29 | mode=["mask", "full_ood"], 30 | overlap=0.2, 31 | map_classes=[], 32 | ignore_classes=[0, 7, 17], 33 | ood_classes=[5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21], 34 | remain_classes=[1, 2, 3, 4], 35 | ignore_index=5, 36 | non_ignore_threshold=0.9 37 | ) 38 | ``` 39 | 40 | The class also has a function to split the Dataset into train/val/test dataset by splitting the whole WSIs to ensure that no data appears in two splits at the same time. 41 | 42 | ```python 43 | # split dataset along whole slide images 44 | train_set, val_set, test_set = bcss_dataset.get_train_val_test_set() 45 | 46 | # use an dataset adapter to use the dataset in the framework 47 | bcss_adapted_test_set = GeneralDatasetAdapter(test_set) 48 | 49 | # view samples 50 | bcss_adapted_test_set.sample() 51 | ``` 52 | 53 | If you want to crop or resize the images you can use an Augmentation Pipeline: 54 | 55 | ```python 56 | # build augmentation pipeline 57 | pipeline = SizeInOODPipeline(in_augmentations=[ 58 | InCrop((600, 600)), 59 | InResize(resize_size=(300, 300)) 60 | ]) 61 | 62 | # create dataset that applies augmentations on samples 63 | cropped_resized_bcss_set = OODAugmentationDataset(bcss_adapted_test_set, pipeline) 64 | 65 | cropped_resized_bcss_set.sample() 66 | ``` 67 | 68 | ## FAQ 69 | Question | Answer 70 | :-- | -- 71 | Why does it **take so long** to load the dataset the **first time**? | When you first load the Dataset class it will produce a file that contains all valid regions satisfying your parameters. With this file the dataset will lazy load all tile regions which is much faster than loading in the whole WSI and more flexible that saving all tiles individually 72 | 73 | 74 | ## References 75 | 76 | [1] Amgad, M., Elfandy, H., Hussein, H., Atteya, L.A., Elsebaie, M.A., Abo Elnasr, L.S., Sakr, R.A., Salem, H.S., Ismail, A.F., Saad, A.M., et al.: Structured crowd- sourcing enables convolutional segmentation of histology images. Bioinformatics (2019) -------------------------------------------------------------------------------- /docs/datasets/DATASET_OVERVIEW.md: -------------------------------------------------------------------------------- 1 | # Build-in datasets and how to install them 2 | 3 | Dataset | Domain | Description | Link 4 | -- | -- | -- | -- 5 | Breast Cancer Semantic Segmentation (BCSS) [1] | Digital Pathology| | [here](BCSS.md) 6 | 7 | 8 | 9 | ## References 10 | 11 | [1] Amgad, M., Elfandy, H., Hussein, H., Atteya, L.A., Elsebaie, M.A., Abo Elnasr, L.S., Sakr, R.A., Salem, H.S., Ismail, A.F., Saad, A.M., et al.: Structured crowd- sourcing enables convolutional segmentation of histology images. Bioinformatics (2019) 12 | 13 | -------------------------------------------------------------------------------- /examples/demo.py: -------------------------------------------------------------------------------- 1 | from copy import deepcopy 2 | import matplotlib.pyplot as plt 3 | from froodo import ( 4 | PneumoniaDataSetAdapter, 5 | TubesAugmentation, 6 | ForeignBodiesAugmentation, 7 | CoinAugmentation, 8 | NailsAugmentation, 9 | GaussianNoiseAugmentation, 10 | MotionBlurAugmentation, 11 | ) 12 | 13 | 14 | # Download the dataset from https://www.kaggle.com/datasets/paultimothymooney/chest-xray-pneumonia 15 | # and pass the base path to the adapter here 16 | dataset_adapter = PneumoniaDataSetAdapter("~/Downloads/chest_xray/", split="test") 17 | sampleIndex = 100 18 | sample = dataset_adapter[sampleIndex] 19 | 20 | # single = GaussianNoiseAugmentation(sigma=0.01)(sample) 21 | # print(single["metadata"][SampleMetadataCommonTypes.OOD_SEVERITY.name]) 22 | # sample = xray_dataset[sampleIndex] 23 | 24 | augmentations = [ 25 | [ 26 | TubesAugmentation(amount=1, keep_ignored=False), 27 | TubesAugmentation(amount=6, keep_ignored=False), 28 | ], 29 | [ 30 | ForeignBodiesAugmentation(amount=1, keep_ignored=False), 31 | ForeignBodiesAugmentation(amount=6, keep_ignored=False), 32 | ], 33 | [ 34 | CoinAugmentation(amount=1, keep_ignored=False), 35 | CoinAugmentation(amount=2, keep_ignored=False), 36 | ], 37 | [ 38 | NailsAugmentation(amount=1, keep_ignored=False), 39 | NailsAugmentation(amount=3, keep_ignored=False), 40 | ], 41 | [ 42 | GaussianNoiseAugmentation(sigma=0.001, keep_ignored=False), 43 | GaussianNoiseAugmentation(sigma=0.01, keep_ignored=False), 44 | ], 45 | [ 46 | MotionBlurAugmentation(motion=5, keep_ignored=False), 47 | MotionBlurAugmentation(motion=20, keep_ignored=False), 48 | ], 49 | ] 50 | 51 | titles = ["Tubes", "Foreign Bodies", "Coin", "Nails", "Noise", "Motion"] 52 | 53 | f, ax = plt.subplots(4, len(augmentations), figsize=(5 * len(augmentations), 20)) 54 | 55 | ax[0, 0].set_ylabel("Image", fontsize=35) 56 | ax[1, 0].set_ylabel("OOD Mask", fontsize=35) 57 | ax[2, 0].set_ylabel("Image", fontsize=35) 58 | ax[3, 0].set_ylabel("OOD Mask", fontsize=35) 59 | 60 | for i in range(len(augmentations)): 61 | for j in range(len(augmentations[i])): 62 | if j == 0: 63 | ax[0, i].set_title(titles[i], fontsize=35) 64 | s = deepcopy(sample) 65 | s = augmentations[i][j](s) 66 | ax[2 * j, i].imshow(s.image.permute(1, 2, 0)) 67 | ax[2 * j + 1, i].imshow(s["ood_mask"], vmin=0, vmax=1) 68 | ax[2 * j, i].set_yticks([]) 69 | ax[2 * j, i].set_xticks([]) 70 | ax[2 * j + 1, i].set_yticks([]) 71 | ax[2 * j + 1, i].set_xticks([]) 72 | plt.show() 73 | -------------------------------------------------------------------------------- /examples/eval.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.utils.data import Dataset 3 | from tqdm import trange 4 | from froodo import PneumoniaDataSetAdapter 5 | 6 | """ 7 | This model evaluation script was kindly provided by the other project group and adapted to the pneumonia data set. 8 | """ 9 | 10 | # Download the dataset from https://www.kaggle.com/datasets/paultimothymooney/chest-xray-pneumonia 11 | # and pass the base path to the adapter here 12 | adapter = PneumoniaDataSetAdapter("~/Downloads/chest_xray/", split="test") 13 | dataloader = torch.utils.data.DataLoader( 14 | adapter.dataset, batch_size=16, shuffle=True, num_workers=0 15 | ) 16 | 17 | dataloader = iter(dataloader) 18 | 19 | model = torch.hub.load( 20 | "pytorch/vision:v0.10.0", "mobilenet_v2", pretrained=False, num_classes=2 21 | ) 22 | model.load_state_dict(torch.load("./model.pth")) 23 | model = model.cuda() 24 | model = model.eval() 25 | 26 | all_correct_classifications = 0 27 | all_classifications = 0 28 | 29 | with torch.no_grad(): 30 | with trange(len(dataloader)) as tbar: 31 | for b in tbar: 32 | image, label = next(dataloader) 33 | B = image.shape[0] 34 | image = image.cuda() 35 | label = label.cuda() 36 | 37 | out = model(image) 38 | binary_labels = torch.argmax(out, dim=1) 39 | correct_classifications = torch.sum(binary_labels == label) 40 | tbar.set_postfix(loss=correct_classifications / B) 41 | 42 | all_correct_classifications += correct_classifications 43 | all_classifications += B 44 | 45 | print("accuracy: ", all_correct_classifications / all_classifications) 46 | -------------------------------------------------------------------------------- /examples/evaluation.py: -------------------------------------------------------------------------------- 1 | from froodo import * 2 | 3 | # Download the dataset from https://www.kaggle.com/datasets/paultimothymooney/chest-xray-pneumonia 4 | # and pass the base path to the adapter here 5 | dataset_adapter = PneumoniaDataSetAdapter("~/Downloads/chest_xray/", split="test") 6 | 7 | # init network 8 | model = torch.hub.load( 9 | "pytorch/vision:v0.10.0", "mobilenet_v2", pretrained=False, num_classes=2 10 | ) 11 | model.load_state_dict(torch.load("./model.pth")) 12 | model = model.cuda() 13 | 14 | # choose metrics 15 | metrics = [ 16 | OODAuRoC(bin_by="OOD_SEVERITY", num_bins=100), 17 | OODAuRoC(), 18 | ] 19 | 20 | # choose post-hoc OOD methods 21 | methods = [MaxClassBaseline(), ODIN(), EnergyBased()] 22 | 23 | # create experiment component 24 | experiment = AugmentationOODEvaluationComponent( 25 | data_adapter=dataset_adapter, 26 | augmentation=SampledAugmentation(TubesAugmentation(keep_ignored=False)), 27 | model=model, 28 | metrics=metrics, 29 | methods=methods, 30 | seed=4321, 31 | task_type=TaskType.CLASSIFICATION, 32 | batch_size=64, 33 | num_workers=0, 34 | ) 35 | 36 | # run experiment 37 | experiment() 38 | -------------------------------------------------------------------------------- /examples/model.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/examples/model.pth -------------------------------------------------------------------------------- /examples/optimizer.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/examples/optimizer.pth -------------------------------------------------------------------------------- /examples/scheduler.pth: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/examples/scheduler.pth -------------------------------------------------------------------------------- /examples/train.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset 2 | from froodo import * 3 | from tqdm import trange 4 | import numpy as np 5 | 6 | import matplotlib.pyplot as plt 7 | 8 | from froodo import PneumoniaDataSetAdapter 9 | 10 | """ 11 | This model training script was kindly provided by the other project group and adapted to the pneumonia data set. 12 | """ 13 | 14 | # Download the dataset from https://www.kaggle.com/datasets/paultimothymooney/chest-xray-pneumonia 15 | # and pass the base path to the adapter here 16 | adapter = PneumoniaDataSetAdapter("~/Downloads/chest_xray/", split="train") 17 | dataloader = torch.utils.data.DataLoader( 18 | adapter.dataset, batch_size=16, shuffle=True, num_workers=0 19 | ) 20 | 21 | model = torch.hub.load( 22 | "pytorch/vision:v0.10.0", "mobilenet_v2", pretrained=False, num_classes=2 23 | ) 24 | model = model.cuda() 25 | model = model.train() 26 | 27 | optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9) 28 | lr_scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, verbose=True) 29 | loss_func = torch.nn.CrossEntropyLoss() 30 | 31 | # train 32 | num_epochs = 50 33 | num_samples_per_epoch = 100 34 | 35 | 36 | assert num_samples_per_epoch <= len(dataloader) 37 | all_losses = [] 38 | 39 | 40 | for epoch in range(num_epochs): 41 | epoch_losses = [] 42 | print( 43 | "start epoch {epoch} using LR: {lr:.4f}".format( 44 | epoch=epoch, lr=optimizer.param_groups[0]["lr"] 45 | ) 46 | ) 47 | 48 | with trange(num_samples_per_epoch) as tbar: 49 | for b in tbar: 50 | tbar.set_description("Epoch {}/{}".format(epoch + 1, num_epochs)) 51 | 52 | image, label = next(iter(dataloader)) 53 | image = image.cuda() 54 | label = label.cuda() 55 | optimizer.zero_grad() 56 | 57 | out = model(image) 58 | 59 | loss = loss_func(out, label) 60 | 61 | loss.backward() 62 | optimizer.step() 63 | 64 | loss = loss.detach().cpu().numpy() 65 | 66 | tbar.set_postfix(loss=loss) 67 | epoch_losses.append(loss) 68 | mean = np.mean(epoch_losses) 69 | all_losses.append(mean) 70 | print("mean loss: ", mean) 71 | lr_scheduler.step(mean) 72 | 73 | plt.plot(all_losses) 74 | plt.title("Training Loss") 75 | plt.xlabel("epochs") 76 | plt.ylabel("loss") 77 | plt.show() 78 | 79 | torch.save(model.state_dict(), "./model.pth") 80 | torch.save(optimizer.state_dict(), "./optimizer.pth") 81 | torch.save(lr_scheduler.state_dict(), "./scheduler.pth") 82 | -------------------------------------------------------------------------------- /froodo/__init__.py: -------------------------------------------------------------------------------- 1 | from .ood import * 2 | from .data import * 3 | from .experiment.components import * 4 | from .data import datasets as datasets 5 | from .models import SegmentationModel, ResNet18, ResNet50, UNet 6 | -------------------------------------------------------------------------------- /froodo/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .samples import * 2 | from .metadata import * 3 | from .container import * 4 | from .datasets import * 5 | from .datatypes import * 6 | from .utils import * 7 | -------------------------------------------------------------------------------- /froodo/data/container/__init__.py: -------------------------------------------------------------------------------- 1 | from .container import Container 2 | from .metadata_container import MetadataContainer 3 | -------------------------------------------------------------------------------- /froodo/data/container/container.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | 4 | class Container: 5 | def data_requirements(self) -> List[str]: 6 | raise NotImplementedError("Please Implement this method") 7 | 8 | def append(self, data: dict): 9 | raise NotImplementedError("Please Implement this method") 10 | 11 | def process(self): 12 | raise NotImplementedError("Please Implement this method") 13 | -------------------------------------------------------------------------------- /froodo/data/container/metadata_container.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | 3 | from typing import List 4 | 5 | from .container import Container 6 | 7 | 8 | class MetadataContainer(Container): 9 | def __init__(self) -> None: 10 | super().__init__() 11 | self.metadata = [] 12 | 13 | def data_requirements(self) -> List[str]: 14 | return ["BATCH"] 15 | 16 | def append(self, data: dict): 17 | for key, val in data.items(): 18 | if key == "BATCH": 19 | self.metadata.extend(val.metadata.batch) 20 | 21 | def process(self): 22 | self.metaframe = pd.json_normalize([m.data for m in self.metadata]) 23 | -------------------------------------------------------------------------------- /froodo/data/container/requirements.py: -------------------------------------------------------------------------------- 1 | def container_requirements_helper(): 2 | pass 3 | -------------------------------------------------------------------------------- /froodo/data/datasets/__init__.py: -------------------------------------------------------------------------------- 1 | from .examples import * 2 | from .adapter import * 3 | from .interfaces import * 4 | -------------------------------------------------------------------------------- /froodo/data/datasets/adapter/__init__.py: -------------------------------------------------------------------------------- 1 | from .adapter import ( 2 | DatasetAdapter, 3 | AlreadyASampleAdapter, 4 | DatasetWithAllInOneDictAdapter, 5 | ImageLabelMetaAdapter, 6 | PositionalAdapter, 7 | GeneralDatasetAdapter, 8 | ) 9 | from .utils import * 10 | -------------------------------------------------------------------------------- /froodo/data/datasets/adapter/utils.py: -------------------------------------------------------------------------------- 1 | def create_mapping_dict( 2 | image, ood_mask=None, segmentation_mask=None, class_vector=None, **kwargs 3 | ): 4 | d = {"image": image} 5 | if ood_mask != None: 6 | d["ood_mask"] = ood_mask 7 | if segmentation_mask != None: 8 | d["segmentation_mask"] = segmentation_mask 9 | if class_vector != None: 10 | d["class"] = class_vector 11 | for k, v in kwargs.items(): 12 | d[k] = v 13 | return d 14 | -------------------------------------------------------------------------------- /froodo/data/datasets/examples/__init__.py: -------------------------------------------------------------------------------- 1 | from .pathology.bcss import ( 2 | BCSS_Adapted_Cropped_Resized_Datasets, 3 | BCSS_Adapted_Datasets, 4 | BCSS_Base_Dataset, 5 | BCSS_OOD_Dataset, 6 | ) 7 | 8 | from .xray.pneumonia import PneumoniaDataSetAdapter 9 | 10 | from .pathology.path_mnist import * 11 | -------------------------------------------------------------------------------- /froodo/data/datasets/examples/endoscopy/ksavir.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | import torch 4 | from torch.utils.data import Dataset 5 | from torchvision import transforms 6 | from PIL import Image 7 | 8 | from froodo import Sample 9 | from froodo import SampleDataset 10 | 11 | 12 | class KsavirDataset(Dataset, SampleDataset): 13 | def __init__(self, root_path: str, crop=False) -> None: 14 | super().__init__() 15 | self.root_path = root_path 16 | # self.images = glob.glob(root_path + "/*/") 17 | self.images = [] 18 | for folder in os.listdir(root_path): 19 | self.images += [ 20 | folder + "/" + file for file in os.listdir(root_path + "/" + folder) 21 | ] 22 | self.convert_to_tensor = transforms.PILToTensor() 23 | 24 | self.crop = crop 25 | 26 | def __len__(self): 27 | return len(self.images) 28 | 29 | def __getitem__(self, index) -> torch.Tensor: 30 | img = Image.open(self.root_path + "/" + self.images[index]) 31 | image = self.convert_to_tensor(img) / 255 32 | if self.crop: 33 | WIDTH = 720 34 | HEIGHT = 576 35 | print(image.shape) 36 | 37 | _, H, W = image.shape 38 | assert H >= HEIGHT 39 | assert W >= WIDTH 40 | 41 | top = (H - HEIGHT) // 2 42 | left = (W - WIDTH) // 2 43 | 44 | image = transforms.functional.crop(image, top, left, HEIGHT, WIDTH) 45 | return Sample(image) 46 | -------------------------------------------------------------------------------- /froodo/data/datasets/examples/pathology/bcss.py: -------------------------------------------------------------------------------- 1 | from torchvision.transforms.functional import InterpolationMode 2 | from torchvision.transforms import Resize 3 | 4 | from ...interfaces import ( 5 | AugmentationDataset, 6 | SampleDataset, 7 | MultiFileOverlappingTilesDataset, 8 | ) 9 | from .....ood.augmentations import OODAugmentation, InCrop, InResize, SizeInOODPipeline 10 | from ...adapter.adapter import AlreadyASampleAdapter, ImageLabelMetaAdapter 11 | 12 | 13 | class BCSS_Base_Dataset(MultiFileOverlappingTilesDataset): 14 | def __init__( 15 | self, 16 | folder="", 17 | resize_size=(300, 300), 18 | tile_folder="", 19 | size=(620, 620), 20 | dataset_name="bcss", 21 | mode=["mask", "full_ood"], 22 | overlap=0.2, 23 | map_classes=[], 24 | ignore_classes=[0, 7, 17], 25 | ood_classes=[5, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20, 21], 26 | remain_classes=[1, 2, 3, 4], 27 | ignore_index=5, 28 | non_ignore_threshold=0.9, 29 | files=None, 30 | force_overwrite=False, 31 | ): 32 | super().__init__( 33 | folder, 34 | tile_folder, 35 | size, 36 | dataset_name, 37 | mode, 38 | overlap, 39 | map_classes, 40 | ignore_classes, 41 | ood_classes, 42 | remain_classes, 43 | ignore_index, 44 | non_ignore_threshold, 45 | files, 46 | force_overwrite, 47 | ) 48 | self.resize_size = resize_size 49 | self.resize = Resize(self.resize_size, interpolation=InterpolationMode.NEAREST) 50 | 51 | def __getitem__(self, index): 52 | img, masks = super().__getitem__(index) 53 | return img, masks 54 | 55 | 56 | class BCSS_Adapted_Datasets: 57 | def __init__(self, size=(700, 700), split=(0.10, 0.20), **kwargs): 58 | train, val, test = BCSS_Base_Dataset(size=size).get_train_val_test_set(*split) 59 | self.train = ImageLabelMetaAdapter(train, ignore_index=5, name="BCSS", **kwargs) 60 | self.val = ImageLabelMetaAdapter(val, ignore_index=5, name="BCSS", **kwargs) 61 | self.test = ImageLabelMetaAdapter(test, ignore_index=5, name="BCSS", **kwargs) 62 | 63 | 64 | class BCSS_Adapted_Cropped_Resized_Datasets: 65 | def __init__(self, size=(700, 700), split=(0.10, 0.20), **kwargs): 66 | train, val, test = BCSS_Base_Dataset(size=size).get_train_val_test_set(*split) 67 | pipeline = SizeInOODPipeline( 68 | in_augmentations=[InCrop((600, 600)), InResize(resize_size=(300, 300))] 69 | ) 70 | self.train = AugmentationDataset( 71 | ImageLabelMetaAdapter(train, ignore_index=5, name="BCSS", **kwargs), 72 | pipeline, 73 | ) 74 | 75 | self.val = AugmentationDataset( 76 | ImageLabelMetaAdapter(val, ignore_index=5, name="BCSS", **kwargs), pipeline 77 | ) 78 | 79 | self.test = AugmentationDataset( 80 | ImageLabelMetaAdapter(test, ignore_index=5, name="BCSS", **kwargs), pipeline 81 | ) 82 | 83 | 84 | class BCSS_OOD_Dataset(AugmentationDataset, SampleDataset): 85 | def __init__( 86 | self, 87 | bcss_base: BCSS_Base_Dataset = None, 88 | augmentation: OODAugmentation = None, 89 | seed=None, 90 | ) -> None: 91 | super().__init__( 92 | BCSS_Base_Dataset() if bcss_base == None else bcss_base, augmentation, seed 93 | ) 94 | -------------------------------------------------------------------------------- /froodo/data/datasets/examples/pathology/path_mnist.py: -------------------------------------------------------------------------------- 1 | from torchvision import transforms 2 | import torch 3 | from medmnist import PathMNIST, DermaMNIST, BloodMNIST, RetinaMNIST, TissueMNIST 4 | from torchvision.transforms import Compose, ToTensor 5 | 6 | from typing import Union 7 | 8 | from ...adapter import DatasetAdapter 9 | from ....samples import Sample 10 | 11 | 12 | class MedMNISTAdapter(DatasetAdapter): 13 | def __init__(self, dataset_class, split="test", transform=None, **kwargs) -> None: 14 | super().__init__( 15 | dataset_class( 16 | split=split, 17 | as_rgb=True, 18 | transform=ToTensor() if transform == None else transform, 19 | ), 20 | dataset_class.__name__, 21 | **kwargs 22 | ) 23 | 24 | def __getitem__(self, index) -> Sample: 25 | image, label = self.dataset[index] 26 | return Sample(image, {"class_label": torch.tensor(label[0])}) 27 | 28 | 29 | class PathMNIST_Adapted(MedMNISTAdapter): 30 | def __init__(self, split="test", transform=None, **kwargs) -> None: 31 | super().__init__(PathMNIST, split, transform, **kwargs) 32 | 33 | 34 | class DermaMNIST_Adapted(MedMNISTAdapter): 35 | def __init__(self, split="test", transform=None, **kwargs) -> None: 36 | super().__init__(DermaMNIST, split, transform, **kwargs) 37 | 38 | 39 | class BloodMNIST_Adapted(MedMNISTAdapter): 40 | def __init__(self, split="test", transform=None, **kwargs) -> None: 41 | super().__init__(BloodMNIST, split, transform, **kwargs) 42 | 43 | 44 | class RetinaMNIST_Adapted(MedMNISTAdapter): 45 | def __init__(self, split="test", transform=None, **kwargs) -> None: 46 | super().__init__(RetinaMNIST, split, transform, **kwargs) 47 | 48 | 49 | class TissueMNIST_Adapted(MedMNISTAdapter): 50 | def __init__(self, split="test", transform=None, **kwargs) -> None: 51 | super().__init__(TissueMNIST, split, transform, **kwargs) 52 | -------------------------------------------------------------------------------- /froodo/data/datasets/examples/xray/pneumonia.py: -------------------------------------------------------------------------------- 1 | from os import path 2 | import torchvision as tv 3 | import torch 4 | from ...adapter.adapter import DatasetAdapter, Sample 5 | 6 | """ 7 | Uses the chest xray pneumonia dataset from: https://www.kaggle.com/datasets/paultimothymooney/chest-xray-pneumonia 8 | """ 9 | 10 | 11 | class PneumoniaDataSetAdapter(DatasetAdapter): 12 | def __init__(self, dir_path, split="test", **kwargs) -> None: 13 | transform = tv.transforms.Compose( 14 | [ 15 | tv.transforms.Resize(255), 16 | tv.transforms.CenterCrop(224), 17 | tv.transforms.ToTensor(), 18 | ] 19 | ) 20 | dataset = tv.datasets.ImageFolder( 21 | path.join(dir_path, split), transform=transform 22 | ) 23 | super().__init__(dataset, *kwargs) 24 | 25 | def _add_metadata_args(self, sample: Sample) -> Sample: 26 | sample.metadata.data.update(self.metadata_args) 27 | return sample 28 | 29 | def __len__(self): 30 | return len(self.dataset) 31 | 32 | def __getitem__(self, index) -> Sample: 33 | sample = self.dataset[index] 34 | return Sample(sample[0], {"class_label": torch.Tensor([[sample[1]]])}) 35 | -------------------------------------------------------------------------------- /froodo/data/datasets/interfaces/__init__.py: -------------------------------------------------------------------------------- 1 | from .sample_dataset import SampleDataset 2 | from .augmentation_dataset import AugmentationDataset 3 | from .multi_file_overlapping_tiles_dataset import MultiFileOverlappingTilesDataset 4 | from .ood_dataset import OODDataset 5 | from .concat import ConcatSampleDataset 6 | -------------------------------------------------------------------------------- /froodo/data/datasets/interfaces/augmentation_dataset.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset 2 | import numpy as np 3 | 4 | import random 5 | 6 | 7 | from ...samples import Sample 8 | 9 | from ....ood.augmentations import Augmentation, Nothing 10 | from ..adapter.adapter import DatasetAdapter 11 | from . import SampleDataset 12 | from ..adapter import DatasetAdapter 13 | 14 | 15 | class AugmentationDataset(Dataset, SampleDataset): 16 | def __init__( 17 | self, dataset: SampleDataset, augmentation: Augmentation = None, seed=None 18 | ) -> None: 19 | super().__init__() 20 | self.dataset = dataset 21 | self.set_augmentation(augmentation) 22 | if seed == None: 23 | self.pseudo_random = False 24 | else: 25 | self.init_seeds(seed) 26 | 27 | def init_seeds(self, seed=42): 28 | self.pseudo_random = True 29 | np.random.seed(seed) 30 | self.seeds = (np.random.random(len(self)) * 10000).astype(np.int64) 31 | np.random.seed() 32 | 33 | def set_augmentation(self, augmentation: Augmentation): 34 | if augmentation == None: 35 | self.augmentation = Nothing() 36 | return 37 | assert isinstance(augmentation, Augmentation) 38 | self.augmentation = augmentation 39 | 40 | def _apply_augmentations(self, sample: Sample): 41 | sample = self.augmentation(sample) 42 | return sample 43 | 44 | def __getitem__(self, index): 45 | if self.pseudo_random: 46 | random.seed(self.seeds[index]) 47 | np.random.seed(self.seeds[index]) 48 | return self._apply_augmentations(self.dataset.__getitem__(index)) 49 | 50 | def __len__(self): 51 | return len(self.dataset) 52 | -------------------------------------------------------------------------------- /froodo/data/datasets/interfaces/class_leftout_dataset.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset 2 | 3 | from typing import List 4 | 5 | from ...metadata.types import SampleMetadataCommonTypes 6 | from ...samples import Sample 7 | from ....ood.augmentations import Augmentation, Nothing 8 | from ..adapter.adapter import DatasetAdapter 9 | from . import SampleDataset 10 | from ..adapter import DatasetAdapter 11 | from ...datatypes import DistributionSampleType, TaskType, OODReason 12 | 13 | 14 | class OODAugmentationDataset(Dataset, SampleDataset): 15 | def __init__( 16 | self, 17 | dataset: SampleDataset, 18 | class_leftout: List, 19 | task_type: TaskType.CLASSIFICATION, 20 | ) -> None: 21 | super().__init__() 22 | self.dataset = dataset 23 | self.class_leftout = class_leftout 24 | self.task_type = task_type 25 | 26 | def __getitem__(self, index): 27 | sample: Sample = self.dataset.__getitem__(index) 28 | if self.task_type is TaskType.CLASSIFICATION: 29 | if sample["class_vector"] != None: 30 | pass 31 | elif sample["class_number"] != None: 32 | if sample["class_number"] in self.class_leftout: 33 | sample.metadata.type = DistributionSampleType.OOD_DATA 34 | sample.metadata[ 35 | SampleMetadataCommonTypes.OOD_REASON.name 36 | ] = OODReason.UNSEEN_CLASSES_OOD.name 37 | else: 38 | raise NotImplementedError() 39 | elif self.task_type is TaskType.SEGMENTATION: 40 | pass 41 | 42 | def __len__(self): 43 | return len(self.dataset) 44 | -------------------------------------------------------------------------------- /froodo/data/datasets/interfaces/concat.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset, ConcatDataset 2 | 3 | from typing import List 4 | 5 | from . import SampleDataset 6 | from ...samples import Sample 7 | from ....ood.augmentations import Augmentation 8 | 9 | 10 | class ConcatSampleDataset(Dataset, SampleDataset): 11 | def __init__( 12 | self, datasets: List[SampleDataset], transform: Augmentation = None 13 | ) -> None: 14 | super(ConcatSampleDataset, self).__init__() 15 | self.common_label_set = None 16 | for d in datasets: 17 | sample: Sample = d[0] 18 | label_set = sample.label_dict.keys() 19 | if self.common_label_set == None: 20 | self.common_label_set = set(label_set) 21 | else: 22 | self.common_label_set = self.common_label_set.intersection( 23 | set(label_set) 24 | ) 25 | self.transform = transform 26 | self.dataset = ConcatDataset(datasets) 27 | 28 | def __len__(self) -> int: 29 | return len(self.dataset) 30 | 31 | def __getitem__(self, index) -> Sample: 32 | sample: Sample = self.dataset[index] 33 | unwanted = set(sample.label_dict.keys()) - set(self.common_label_set) 34 | for unwanted_key in unwanted: 35 | del sample.label_dict[unwanted_key] 36 | if self.transform != None: 37 | return self.transform(sample) 38 | return sample 39 | -------------------------------------------------------------------------------- /froodo/data/datasets/interfaces/ood_dataset.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import Dataset 2 | import numpy as np 3 | 4 | import random 5 | 6 | 7 | from ...samples import Sample 8 | from ...datatypes import DistributionSampleType 9 | from ..adapter.adapter import DatasetAdapter 10 | from .sample_dataset import SampleDataset 11 | 12 | 13 | class OODDataset(Dataset, SampleDataset): 14 | def __init__(self, dataset: SampleDataset, num=None) -> None: 15 | super().__init__() 16 | assert isinstance(dataset, SampleDataset) 17 | self.dataset = dataset 18 | self.num = num 19 | 20 | def __len__(self): 21 | return len(self.dataset) 22 | 23 | def __getitem__(self, index) -> Sample: 24 | sample = self.dataset.__getitem__(index) 25 | sample.metadata.type = DistributionSampleType.OOD_DATA 26 | sample.metadata["OOD_REASON"] = "OOD_DATASET" 27 | sample.metadata["OOD_DATASET"] = ( 28 | type(self.dataset) if self.num == None else self.num 29 | ) 30 | return sample 31 | -------------------------------------------------------------------------------- /froodo/data/datasets/interfaces/sample_dataset.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | from torch.utils.data import DataLoader 4 | 5 | from typing import Union 6 | 7 | from ...utils import sample_collate 8 | from ...datatypes import DistributionSampleType 9 | 10 | 11 | class SampleDataset: 12 | 13 | name: Union[str, None] = None 14 | 15 | def find_base_name(self, default=None): 16 | if self.name != None: 17 | return self.name 18 | 19 | if hasattr(self, "dataset") and isinstance(self.dataset, SampleDataset): 20 | return self.dataset.find_base_name(default) 21 | 22 | return default 23 | 24 | def get_dataloader( 25 | self, 26 | batch_size: int = 16, 27 | num_workers: Union[int, None] = 10, 28 | shuffle: bool = False, 29 | pin_memory: bool = False, 30 | persistent_workers: bool = False, 31 | **dataloader_kwargs, 32 | ) -> DataLoader: 33 | return DataLoader( 34 | self, 35 | collate_fn=sample_collate, 36 | batch_size=batch_size, 37 | pin_memory=pin_memory, 38 | num_workers=num_workers, 39 | shuffle=shuffle, 40 | persistent_workers=persistent_workers, 41 | **dataloader_kwargs, 42 | ) 43 | 44 | def sample(self, n=8, show=True, random=True): 45 | if random: 46 | ids = np.random.choice( 47 | range(len(self)), 48 | n, 49 | ) 50 | else: 51 | ids = [i + 50 for i in range(n)] 52 | data = [self[i] for i in ids] 53 | 54 | keys = data[0].label_dict.keys() 55 | mask_overlap = set(keys).intersection( 56 | { 57 | "segmentation_mask", 58 | "ood_mask", 59 | } 60 | ) 61 | n_masks = len(mask_overlap) 62 | 63 | if show: 64 | f, axes = plt.subplots(1 + n_masks, n, figsize=(n * 4, (n_masks + 1) * 4)) 65 | 66 | # expand dims if no mask is found 67 | if n_masks == 0: 68 | axes = np.expand_dims(axes, axis=0) 69 | 70 | axes[0, 0].set_ylabel("image", rotation=90, size=20) 71 | axes[0, 0].yaxis.set_label_coords(-0.1, 0.5) 72 | for i, sample in enumerate(data): 73 | axes[0, i].imshow(sample["image"].numpy().transpose((1, 2, 0))) 74 | axes[0, i].set_yticks([]) 75 | axes[0, i].set_xticks([]) 76 | j = 0 77 | axes[0, i].set_title( 78 | sample.metadata.type.name, 79 | fontsize=25, 80 | c="red" 81 | if sample.metadata.type is DistributionSampleType.OOD_DATA 82 | else "black", 83 | ) 84 | for (k, v) in sample.label_dict.items(): 85 | if k in mask_overlap: 86 | axes[j + 1, i].imshow(v.numpy(), vmin=0, vmax=5) 87 | axes[j + 1, i].set_yticks([]) 88 | axes[j + 1, i].set_xticks([]) 89 | if i == 0: 90 | axes[j + 1, i].set_ylabel(k, rotation=90, size=20) 91 | axes[j + 1, i].yaxis.set_label_coords(-0.1, 0.5) 92 | j += 1 93 | elif k == "class_label": 94 | axes[0, i].set_title( 95 | f"Class {int(v.item())}", 96 | fontsize=25, 97 | c="red" 98 | if sample.metadata.type is DistributionSampleType.OOD_DATA 99 | else "black", 100 | ) 101 | 102 | plt.show() 103 | -------------------------------------------------------------------------------- /froodo/data/datasets/utils.py: -------------------------------------------------------------------------------- 1 | import tifffile as tiff 2 | import zarr 3 | import numpy as np 4 | import torch 5 | 6 | import random 7 | from os.path import join 8 | 9 | 10 | def read_tif_region(file, from_x=None, to_x=None, from_y=None, to_y=None): 11 | store = tiff.imread(file, aszarr=True) 12 | out_labels_slide = zarr.open(store, mode="r") 13 | 14 | if from_x == None: 15 | return out_labels_slide 16 | return out_labels_slide[from_y:to_y, from_x:to_x] 17 | 18 | 19 | def random_crop(img, mask, height, width): 20 | x = random.randint(0, img.shape[2] - width) 21 | y = random.randint(0, img.shape[1] - height) 22 | img = img[:, y : y + height, x : x + width] 23 | mask = mask[y : y + height, x : x + width] 24 | return (img, mask) 25 | 26 | 27 | def get_valid_regions_of_image( 28 | folder, 29 | image, 30 | size, 31 | overlap, 32 | ignore_classes, 33 | non_ignore_threshold=0.9, 34 | ): 35 | 36 | img = read_tif_region(join(folder, image)) 37 | 38 | ov_y = size[0] - int(size[0] * overlap) 39 | ov_x = size[1] - int(size[1] * overlap) 40 | 41 | num_pixel = size[0] * size[1] 42 | img_size = img.shape 43 | 44 | tiles = [] 45 | num_valid = 0 46 | num_invalid = 0 47 | 48 | y = size[0] 49 | x = size[1] 50 | 51 | while y <= img_size[0]: 52 | 53 | x = size[1] 54 | while x < img_size[1]: 55 | mask = img[y - size[0] : y, x - size[1] : x] 56 | perc = np.sum(np.in1d(mask, [ignore_classes])) / num_pixel 57 | 58 | if mask.shape[0] != size[0] or mask.shape[1] != size[1]: 59 | print("falsch") 60 | 61 | if perc <= non_ignore_threshold: 62 | tiles.append([x - size[1], x, y - size[0], y]) 63 | num_valid += 1 64 | else: 65 | num_invalid += 1 66 | 67 | x += ov_x 68 | 69 | y += ov_y 70 | 71 | return tiles, [num_valid, num_invalid] 72 | 73 | 74 | def to_tensor(array, mask=False): 75 | if not mask: 76 | return torch.from_numpy(array).permute(2, 0, 1) 77 | else: 78 | return torch.from_numpy(array) 79 | 80 | 81 | def apply_mask_changes( 82 | mask, 83 | ignore_classes, 84 | ood_classes, 85 | ignore_index, 86 | remain_classes, 87 | map_classes, 88 | mode=["mask"], 89 | ): 90 | masks = {} 91 | if "mask" in mode: 92 | _mask = mask.copy() 93 | for f, t in map_classes: 94 | _mask[_mask == f] = t 95 | _mask[np.in1d(_mask, ignore_classes + ood_classes).reshape(_mask.shape)] = ( 96 | ignore_index + 1 97 | ) 98 | _mask = _mask - 1 99 | masks["segmentation_mask"] = to_tensor(_mask.astype(np.longlong), True) 100 | 101 | if "ood" in mode or "full_ood" in mode: 102 | _mask = mask.copy() 103 | for f, t in map_classes: 104 | _mask[_mask == f] = t 105 | remain_indices = np.in1d(_mask, remain_classes).reshape(_mask.shape) 106 | ood_indices = np.in1d(_mask, ood_classes).reshape(_mask.shape) 107 | ignore_indices = np.in1d(_mask, ignore_classes).reshape(_mask.shape) 108 | _mask[remain_indices] = 1 109 | _mask[ood_indices] = 0 if "ood" in mode else ignore_index 110 | _mask[ignore_indices] = ignore_index 111 | masks["ood_mask"] = to_tensor(_mask.astype(np.longlong), True) 112 | return masks 113 | -------------------------------------------------------------------------------- /froodo/data/datatypes.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class DistributionSampleType(Enum): 5 | UNDEFINED = auto() 6 | IN_DATA = auto() 7 | OOD_DATA = auto() 8 | 9 | 10 | class OODReason(Enum): 11 | AUGMENTATION_OOD = auto() 12 | UNSEEN_CLASSES_OOD = auto() 13 | DATASET_OOD = auto() 14 | 15 | 16 | class TaskType(Enum): 17 | SEGMENTATION = auto() 18 | CLASSIFICATION = auto() 19 | -------------------------------------------------------------------------------- /froodo/data/metadata/__init__.py: -------------------------------------------------------------------------------- 1 | from .metadata import SampleMetadata 2 | from .batch import * 3 | from .utils import * 4 | from .types import SampleMetadataCommonTypes 5 | -------------------------------------------------------------------------------- /froodo/data/metadata/batch.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from .metadata import SampleMetadata 4 | 5 | 6 | class SampleMetdadataBatch: 7 | def __init__(self, batch: List[SampleMetadata]) -> None: 8 | self.batch = batch 9 | # only the created keys are saved here 10 | self.created = [] 11 | 12 | def __len__(self): 13 | return len(self.batch) 14 | 15 | def __getitem__(self, index): 16 | return self.batch[index] 17 | 18 | def __getitem__(self, arg): 19 | return [m[arg] for m in self.batch] 20 | 21 | def __setitem__(self, idx, value): 22 | for m in self.batch: 23 | m[idx] = value 24 | 25 | def init_as_dict(self, key): 26 | for m in self.batch: 27 | if key not in m.data: 28 | m[key] = {} 29 | 30 | def append_to_keyed_dict(self, key, dict_key, items): 31 | if key not in self.created: 32 | self.init_as_dict(key) 33 | if len(self) == len(items): 34 | for i, m in enumerate(self.batch): 35 | m[key][dict_key] = items[i] 36 | -------------------------------------------------------------------------------- /froodo/data/metadata/metadata.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | from ..datatypes import DistributionSampleType 4 | from ...utils import dict_default 5 | 6 | 7 | class SampleMetadata: 8 | def __init__( 9 | self, type=DistributionSampleType.IN_DATA, data_dict: defaultdict = None 10 | ) -> None: 11 | if data_dict == None: 12 | self.data = defaultdict(dict_default) 13 | else: 14 | assert isinstance(data_dict, defaultdict) 15 | self.data = data_dict 16 | self.type = type 17 | 18 | @property 19 | def type(self): 20 | return self._type 21 | 22 | @property 23 | def data(self): 24 | return self._data 25 | 26 | @type.setter 27 | def type(self, sample_type: DistributionSampleType): 28 | assert isinstance( 29 | sample_type, DistributionSampleType 30 | ), f"Metadata Type needs to be a DistributionSampleType ({type(sample_type)} is invalid)" 31 | self._type = sample_type 32 | self._data["type"] = sample_type 33 | 34 | @data.setter 35 | def data(self, data_dict: defaultdict): 36 | assert isinstance( 37 | data_dict, defaultdict 38 | ), "Metadata Data needs to be a dictionary" 39 | self._data = data_dict 40 | 41 | def __getitem__(self, arg): 42 | if arg == "type": 43 | return self.type 44 | return self.data[arg] 45 | 46 | def __setitem__(self, idx, value): 47 | if idx == "type": 48 | self.type = value 49 | return 50 | self.data[idx] = value 51 | 52 | def __delitem__(self, item: str) -> None: 53 | if item == "type": 54 | print("Type cant be deleted") 55 | else: 56 | self._data.__delattr__(item) 57 | 58 | def __repr__(self) -> str: 59 | return f"{self.type} - {self.data.items()}" 60 | -------------------------------------------------------------------------------- /froodo/data/metadata/types.py: -------------------------------------------------------------------------------- 1 | from enum import Enum, auto 2 | 3 | 4 | class SampleMetadataCommonTypes(Enum): 5 | OOD_SCORE = auto() 6 | OOD_SEVERITY = auto() 7 | OOD_REASON = auto() 8 | OOD_AUGMENTATION = auto() 9 | -------------------------------------------------------------------------------- /froodo/data/metadata/utils.py: -------------------------------------------------------------------------------- 1 | from .metadata import SampleMetadata 2 | from .batch import SampleMetdadataBatch 3 | 4 | 5 | def init_sample_metadata(metadata=None): 6 | if metadata == None: 7 | return SampleMetadata() 8 | else: 9 | assert isinstance(metadata, SampleMetadata) or isinstance( 10 | metadata, SampleMetdadataBatch 11 | ), "Metadata needs to be class Metadata or MetdataBatch" 12 | return metadata 13 | -------------------------------------------------------------------------------- /froodo/data/samples/__init__.py: -------------------------------------------------------------------------------- 1 | from .sample import Sample 2 | from .batch import Batch 3 | -------------------------------------------------------------------------------- /froodo/data/samples/batch.py: -------------------------------------------------------------------------------- 1 | from abc import abstractmethod 2 | import torch 3 | from torch.utils.data import _utils 4 | 5 | from typing import List 6 | 7 | from .sample import Sample 8 | from ..metadata import SampleMetdadataBatch 9 | 10 | 11 | class Batch(Sample): 12 | def __init__( 13 | self, 14 | images: torch.Tensor, 15 | labels_dict: dict, 16 | metadata_batch: SampleMetdadataBatch = None, 17 | ) -> None: 18 | super().__init__(images, labels_dict, metadata_batch) 19 | 20 | @staticmethod 21 | def init_from_samples(samples: List[Sample]): 22 | img = [] 23 | labels = [] 24 | meta = SampleMetdadataBatch([]) 25 | for sample in samples: 26 | img.append(sample.image) 27 | labels.append(sample.label_dict) 28 | meta.batch.append(sample.metadata) 29 | return Batch( 30 | _utils.collate.default_collate(img), 31 | _utils.collate.default_collate(labels), 32 | meta, 33 | ) 34 | -------------------------------------------------------------------------------- /froodo/data/samples/sample.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from collections import defaultdict 4 | import matplotlib.pyplot as plt 5 | 6 | from ..datatypes import TaskType 7 | from ...utils import dict_default 8 | from ..metadata import SampleMetadata, init_sample_metadata 9 | 10 | 11 | class Sample: 12 | def __init__(self, image, label_dict: dict = None, metadata=None) -> None: 13 | self.image = image 14 | if label_dict == None: 15 | self.label_dict = defaultdict(dict_default) 16 | else: 17 | self.label_dict = defaultdict(dict_default, label_dict) 18 | self.metadata = init_sample_metadata(metadata) 19 | 20 | def add_labels_dict(self, **kwargs): 21 | for k, v in kwargs.items(): 22 | assert isinstance(v, torch.Tensor) 23 | self.label_dict[k] = v 24 | 25 | def add_segmentation_mask(self, mask: torch.Tensor): 26 | self.label_dict["segmentation_mask"] = mask 27 | 28 | def add_ood_mask(self, mask: torch.Tensor): 29 | self.label_dict["ood_mask"] = mask 30 | 31 | def add_class_label(self, class_label: torch.Tensor): 32 | self.label_dict["class_label"] = class_label 33 | 34 | def get(self): 35 | return self.image, self.label_dict, self.metadata 36 | 37 | def __getitem__(self, arg): 38 | if arg == "image": 39 | return self.image 40 | elif arg == "metadata": 41 | return self.metadata 42 | return self.label_dict[arg] 43 | 44 | def __setitem__(self, idx, value): 45 | if idx == "image": 46 | assert isinstance(value, torch.Tensor) 47 | self.image = value 48 | return 49 | if idx == "metadata": 50 | assert isinstance(value, SampleMetadata) 51 | self.metadata = value 52 | return 53 | assert isinstance(value, torch.Tensor) 54 | self.label_dict[idx] = value 55 | 56 | def cuda(self): 57 | self.image = self.image.cuda() 58 | for k, v in self.label_dict.items(): 59 | self.label_dict[k] = v.cuda() 60 | return self 61 | 62 | def get_label_by_task_type(self, task_type: TaskType) -> torch.Tensor: 63 | return ( 64 | self["segmentation_mask"] 65 | if task_type is TaskType.SEGMENTATION 66 | else self["class_label"] 67 | ) 68 | 69 | def plot(self, print_meta=True): 70 | f, ax = plt.subplots( 71 | 1, 1 + len(self.label_dict), figsize=(4 * (1 + len(self.label_dict)), 4) 72 | ) 73 | ax[0].imshow(self.image.permute(1, 2, 0)) 74 | ax[0].set_title(f"image {list(self.image.size())}") 75 | ax[0].set_xticks([]) 76 | ax[0].set_yticks([]) 77 | """ 78 | for i, (k, v) in enumerate(self.label_dict.items()): 79 | ax[i + 1].imshow(v) 80 | ax[i + 1].set_title(f"{k} {list(v.size())}") 81 | ax[i + 1].set_xticks([]) 82 | ax[i + 1].set_yticks([]) 83 | """ 84 | plt.show() 85 | if print_meta: 86 | print(self.metadata) 87 | -------------------------------------------------------------------------------- /froodo/data/utils.py: -------------------------------------------------------------------------------- 1 | from .samples import Batch 2 | 3 | 4 | def sample_collate(d): 5 | return Batch.init_from_samples(d) 6 | -------------------------------------------------------------------------------- /froodo/experiment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/experiment/__init__.py -------------------------------------------------------------------------------- /froodo/experiment/artifacts/__init__.py: -------------------------------------------------------------------------------- 1 | from .artifact import ComponentArtifact 2 | from .metric_artifact import MetricArtifact 3 | from .container_artifact import ContainerArtifact 4 | -------------------------------------------------------------------------------- /froodo/experiment/artifacts/artifact.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import cloudpickle 3 | from os.path import join 4 | 5 | 6 | class ComponentArtifact: 7 | def __init__(self) -> None: 8 | pass 9 | 10 | def save(self, folder) -> None: 11 | with open(join(folder, f"{type(self).__name__}.pkl"), "wb") as f: 12 | cloudpickle.dump(self, f) 13 | 14 | def recreate(self) -> None: 15 | pass 16 | -------------------------------------------------------------------------------- /froodo/experiment/artifacts/container_artifact.py: -------------------------------------------------------------------------------- 1 | from .artifact import ComponentArtifact 2 | from ...data.container import Container 3 | 4 | 5 | class ContainerArtifact(ComponentArtifact): 6 | def __init__(self, container: Container) -> None: 7 | super().__init__() 8 | self.container = container 9 | -------------------------------------------------------------------------------- /froodo/experiment/artifacts/keywords.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/experiment/artifacts/keywords.py -------------------------------------------------------------------------------- /froodo/experiment/artifacts/metric_artifact.py: -------------------------------------------------------------------------------- 1 | from .artifact import ComponentArtifact 2 | from ...ood.metrics import Metric 3 | 4 | 5 | class MetricArtifact(ComponentArtifact): 6 | def __init__(self, metric: Metric) -> None: 7 | super().__init__() 8 | self.metric = metric 9 | 10 | @staticmethod 11 | def aggregate(artifacts: list, **kwargs): 12 | pass 13 | -------------------------------------------------------------------------------- /froodo/experiment/artifacts/storage.py: -------------------------------------------------------------------------------- 1 | class ArtifactStorage: 2 | def __init__(self) -> None: 3 | pass 4 | 5 | def get_latest(self): 6 | pass 7 | -------------------------------------------------------------------------------- /froodo/experiment/components/__init__.py: -------------------------------------------------------------------------------- 1 | from .component import Component 2 | from .interfaces import * 3 | from .examples import * 4 | -------------------------------------------------------------------------------- /froodo/experiment/components/component.py: -------------------------------------------------------------------------------- 1 | from ..artifacts.storage import ArtifactStorage 2 | 3 | 4 | class Component: 5 | def __init__(self, overwrite_from_artifacts=True) -> None: 6 | self.artifacts = {} 7 | self.overwrite_from_artifacts = overwrite_from_artifacts 8 | 9 | def sanity_check(self) -> bool: 10 | raise NotImplementedError("Please Implement this method") 11 | 12 | def load_from_artifact_storage(self, storage: ArtifactStorage): 13 | raise NotImplementedError("Please Implement this method") 14 | 15 | def __call__(self): 16 | raise NotImplementedError("Please Implement this method") 17 | 18 | def get_artifacts(self): 19 | return self.artifacts 20 | -------------------------------------------------------------------------------- /froodo/experiment/components/examples/__init__.py: -------------------------------------------------------------------------------- 1 | from .augmentation_ood_eval import AugmentationOODEvaluationComponent 2 | from .dataset_ood_eval import DatasetOODEvaluationComponent 3 | -------------------------------------------------------------------------------- /froodo/experiment/components/examples/augmentation_ood_eval.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from .. import OODStreatgyComponent 4 | from ....models import Model 5 | from ....ood.metrics import Metric 6 | from ....ood.methods import OODMethod 7 | from ....ood.strategies import AugmentationStrategy 8 | from ....data.datasets.adapter import DatasetAdapter 9 | from ....ood.augmentations import Augmentation 10 | from ....data.datatypes import TaskType 11 | 12 | 13 | class AugmentationOODEvaluationComponent(OODStreatgyComponent): 14 | def __init__( 15 | self, 16 | data_adapter: DatasetAdapter, 17 | augmentation: Augmentation, 18 | model: Model, 19 | methods: List[OODMethod] = None, 20 | metrics: List[Metric] = None, 21 | task_type=TaskType.SEGMENTATION, 22 | remove_ignore_index=False, 23 | seed: int = None, 24 | show: bool = True, 25 | batch_size: int = 12, 26 | num_workers: int = 8, 27 | shuffle: bool = True, 28 | ) -> None: 29 | super().__init__( 30 | AugmentationStrategy(data_adapter, augmentation, seed=seed), 31 | model, 32 | methods, 33 | metrics, 34 | seed, 35 | task_type=task_type, 36 | remove_ignore_index=remove_ignore_index, 37 | show=show, 38 | batch_size=batch_size, 39 | num_workers=num_workers, 40 | shuffle=shuffle, 41 | ) 42 | -------------------------------------------------------------------------------- /froodo/experiment/components/examples/dataset_ood_eval.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from .. import OODStreatgyComponent 4 | from ....models import Model 5 | from ....ood.metrics import Metric 6 | from ....ood.methods import OODMethod 7 | from ....ood.strategies import OODDatasetsStrategy 8 | from ....data.datasets.adapter import DatasetAdapter 9 | from ....ood.augmentations import Augmentation 10 | from ....data.datatypes import TaskType 11 | 12 | 13 | class DatasetOODEvaluationComponent(OODStreatgyComponent): 14 | def __init__( 15 | self, 16 | in_dataset_list: List[DatasetAdapter], 17 | ood_dataset_list: List[DatasetAdapter], 18 | model: Model, 19 | methods: List[OODMethod] = None, 20 | metrics: List[Metric] = None, 21 | task_type=TaskType.SEGMENTATION, 22 | seed: int = None, 23 | remove_ignore_index: bool = False, 24 | show: bool = True, 25 | batch_size: int = 12, 26 | num_workers: int = 8, 27 | shuffle: bool = True, 28 | ) -> None: 29 | super().__init__( 30 | OODDatasetsStrategy(in_dataset_list, ood_dataset_list), 31 | model, 32 | methods, 33 | metrics, 34 | seed, 35 | task_type=task_type, 36 | remove_ignore_index=remove_ignore_index, 37 | show=show, 38 | batch_size=batch_size, 39 | num_workers=num_workers, 40 | shuffle=shuffle, 41 | ) 42 | -------------------------------------------------------------------------------- /froodo/experiment/components/interfaces/__init__.py: -------------------------------------------------------------------------------- 1 | from .ood_strategy_component import OODStreatgyComponent 2 | -------------------------------------------------------------------------------- /froodo/experiment/components/metadata.py: -------------------------------------------------------------------------------- 1 | from collections import defaultdict 2 | 3 | from ...utils import dict_default 4 | 5 | 6 | class ComponentMetadata: 7 | def __init__(self, data_dict=None) -> None: 8 | if data_dict == None: 9 | self.data = defaultdict(dict_default) 10 | else: 11 | self.data = defaultdict(dict_default, data_dict) 12 | 13 | def __getitem__(self, arg): 14 | return self.data[arg] 15 | 16 | def __setitem__(self, idx, value): 17 | self.data[idx] = value 18 | -------------------------------------------------------------------------------- /froodo/models/__init__.py: -------------------------------------------------------------------------------- 1 | from .model import Model 2 | from .segmentation import UNet, SegmentationModel 3 | from .classification import * 4 | -------------------------------------------------------------------------------- /froodo/models/classification/__init__.py: -------------------------------------------------------------------------------- 1 | from .examples.resnet50 import ResNet18, ResNet50 2 | -------------------------------------------------------------------------------- /froodo/models/model.py: -------------------------------------------------------------------------------- 1 | class Model: 2 | def create(self): 3 | raise NotImplementedError("Please Implement this method") 4 | 5 | def load(self): 6 | raise NotImplementedError("Please Implement this method") 7 | -------------------------------------------------------------------------------- /froodo/models/segmentation/__init__.py: -------------------------------------------------------------------------------- 1 | from .examples import UNet 2 | 3 | from .segmentation_model import SegmentationModel 4 | -------------------------------------------------------------------------------- /froodo/models/segmentation/examples/__init__.py: -------------------------------------------------------------------------------- 1 | from .unet import UNet 2 | -------------------------------------------------------------------------------- /froodo/models/segmentation/segmentation_model.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from .utils import * 4 | from .examples import UNet 5 | from .. import Model 6 | 7 | 8 | class SegmentationModel(Model): 9 | def __init__( 10 | self, 11 | folder="UNet_noExtra_trainable_n16_d4_ADAM_bs16_lr0.0001_s20_g1_21", 12 | net_class=UNet, 13 | net_args={}, 14 | state_dict_modification=rename_state_dict_keys, 15 | ) -> None: 16 | self.folder = folder 17 | self.state_dict_modification = state_dict_modification 18 | self.net_class = net_class 19 | self.net_args = net_args 20 | 21 | def load(self): 22 | net = self.net_class(**self.net_args) 23 | 24 | # rename stat dict 25 | # load dict 26 | correct_dict = self.state_dict_modification(wrong_dict) 27 | net.load_state_dict(correct_dict) 28 | 29 | net.cuda() 30 | net.eval() 31 | return net 32 | -------------------------------------------------------------------------------- /froodo/models/segmentation/utils.py: -------------------------------------------------------------------------------- 1 | from collections import OrderedDict 2 | 3 | 4 | def rename_state_dict_keys(state_dict): 5 | new_state_dict = OrderedDict() 6 | for key, value in state_dict.items(): 7 | new_key = key[7:] 8 | new_state_dict[new_key] = value 9 | return new_state_dict 10 | -------------------------------------------------------------------------------- /froodo/ood/__init__.py: -------------------------------------------------------------------------------- 1 | from .methods import * 2 | from .metrics import * 3 | from .severity import * 4 | from .strategies import * 5 | from .augmentations import * 6 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/__init__.py: -------------------------------------------------------------------------------- 1 | from .types import * 2 | 3 | from .utility import ( 4 | NTimesAugmentation, 5 | AugmentationComposite, 6 | PickNComposite, 7 | ProbabilityAugmentation, 8 | Nothing, 9 | SampledAugmentation, 10 | AugmentationPipeline, 11 | SizeInOODPipeline, 12 | ) 13 | 14 | from .pathology.artifacts import ( 15 | FatAugmentation, 16 | DarkSpotsAugmentation, 17 | SquamousAugmentation, 18 | ThreadAugmentation, 19 | ) 20 | 21 | 22 | from .indistribution import * 23 | 24 | from .patchwise import ( 25 | BrightnessAugmentation, 26 | ZoomInAugmentation, 27 | GaussianBlurAugmentation, 28 | ) 29 | 30 | from .xray import ( 31 | MotionBlurAugmentation, 32 | GaussianNoiseAugmentation, 33 | TubesAugmentation, 34 | NailsAugmentation, 35 | CoinAugmentation, 36 | ForeignBodiesAugmentation, 37 | ) 38 | 39 | from .xray.artifacts import TubesAugmentation 40 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/builder.py: -------------------------------------------------------------------------------- 1 | from . import AllComposite, NTimesAugmentation, PickNComposite 2 | 3 | 4 | class Buildable: 5 | def __init__(self) -> None: 6 | pass 7 | 8 | def build(self): 9 | raise NotImplementedError("Please Implement this method") 10 | 11 | 12 | class AugmentationBuilder(Buildable): 13 | def __init__(self) -> None: 14 | super().__init__() 15 | self.blocks = [] 16 | 17 | def __add__(self, block): 18 | self.blocks.append(block.build() if isinstance(block, Buildable) else block) 19 | return self 20 | 21 | def build(self): 22 | return AllComposite(self.blocks) 23 | 24 | 25 | class N(Buildable): 26 | def __init__(self) -> None: 27 | super().__init__() 28 | self.augmentations = [] 29 | self.n = 1 30 | 31 | def __add__(self, aug): 32 | self.augmentations.append(aug) 33 | return self 34 | 35 | def __mul__(self, times): 36 | self.n *= times 37 | return self 38 | 39 | def build(self): 40 | return NTimesAugmentation(AllComposite(self.augmentations), self.n) 41 | 42 | 43 | class Probability(Buildable): 44 | def __init__(self, replace=False) -> None: 45 | super().__init__() 46 | self.augmentations = [] 47 | self.n = 1 48 | self.replace = replace 49 | self.probabilities = None 50 | 51 | def __add__(self, aug): 52 | self.augmentations.append(aug) 53 | return self 54 | 55 | def __mul__(self, times): 56 | self.n *= times 57 | return self 58 | 59 | def __truediv__(self, probabilities): 60 | self.probabilities = probabilities 61 | return self 62 | 63 | def build(self): 64 | return PickNComposite( 65 | self.augmentations, 66 | n=self.n, 67 | replace=self.replace, 68 | probabilities=self.probabilities, 69 | ) 70 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_seed_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_seed_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_seed_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_seed_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_skin_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_skin_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_skin_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_bright_skin_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_seed_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_seed_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_seed_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_seed_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_skin_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_skin_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_skin_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/chili/chili_dark_skin_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1cent_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1cent_back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1cent_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1cent_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1cent_front_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1cent_front_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1euro_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1euro_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1euro_front_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_1euro_front_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_20cent_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_20cent_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_2cent_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_2cent_back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_2cent_back_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_2cent_back_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_2cent_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_bright_2cent_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_1cent_front_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_1cent_front_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_1euro_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_1euro_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_1euro_front_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_1euro_front_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_2cent_back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_2cent_back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_2cent_back_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coin v2/coin_dark_2cent_back_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/100_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/100_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/100_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/100_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/10_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/10_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/10_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/10_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/1_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/1_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/1_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/1_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/200_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/200_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/200_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/200_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/20_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/20_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/20_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/20_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/2_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/2_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/2_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/2_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/50_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/50_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/50_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/50_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/5_Back.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/5_Back.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/5_Front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/coins/5_Front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_1_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_1_1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_1_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_2_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_2_1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_2_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_2_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_3_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_3_1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_3_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/dry/corn_dry_3_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/mashed/corn_mashed_1_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/mashed/corn_mashed_1_1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/mashed/corn_mashed_1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/mashed/corn_mashed_1_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/wet/corn_wet_1_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/wet/corn_wet_1_1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/wet/corn_wet_1_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/corn/wet/corn_wet_1_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_bright_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_bright_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_bright_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_bright_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_dark_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_dark_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_dark_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/green onion/go_dark_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_half1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_half1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_half2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_half2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_half3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_half3.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_smashed1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_smashed1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_smashed2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_smashed2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_whole.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_bright_whole.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_dark_half1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_dark_half1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_dark_smashed1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_dark_smashed1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_dark_smashed2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/kidney bean/kb_dark_smashed2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_bright_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_bright_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_bright_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_bright_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_dark_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_dark_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_dark_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/melon seed/ms_dark_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_bright_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_bright_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_bright_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_bright_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_dark_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_dark_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_dark_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/oats/oats_dark_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_half_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_half_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_half_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_half_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_whole_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_whole_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_whole_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_bright_whole_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_half_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_half_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_half_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_half_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_whole_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_whole_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_whole_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/mg_dark_whole_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_half_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_half_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_half_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_half_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_whole_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_whole_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_whole_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_bright_whole_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_half_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_half_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_half_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_half_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_whole_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_whole_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_whole_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pill v2/vb_dark_whole_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pills/20230122_200856.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pills/20230122_200856.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_bright_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_bright_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_bright_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_bright_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_dark_front.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_dark_front.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_dark_side.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/endoscopy/artifacts/imgs/pumpkin seed/ps_dark_side.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/blood.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | import os 3 | from os.path import join 4 | import random 5 | from froodo.data.samples.sample import Sample 6 | from froodo.ood.augmentations.types import OODAugmentation 7 | 8 | import imageio 9 | import cv2 as cv 10 | import numpy as np 11 | import torch 12 | 13 | import colorsys 14 | import scipy 15 | 16 | import torchvision 17 | 18 | from froodo.ood.severity.severity import ParameterSeverityMeasurement 19 | 20 | 21 | class BloodAugmentation(OODAugmentation): 22 | def __init__(self) -> None: 23 | super().__init__() 24 | self.severity_class = ParameterSeverityMeasurement( 25 | "saturation_factor", (1, 1.3) 26 | ) 27 | 28 | def _augment(self, sample: Sample) -> Sample: 29 | img = sample.image 30 | img = torchvision.transforms.functional.adjust_hue(img, -20 / 180) 31 | 32 | # find saturation_factor in [1,1.3] 33 | saturation_factor = float(np.random.randint(100, high=130 + 1)) 34 | saturation_factor /= 100 35 | 36 | self.saturation_factor = saturation_factor 37 | 38 | img = torchvision.transforms.functional.adjust_saturation( 39 | img, saturation_factor 40 | ) 41 | 42 | sample["image"] = img 43 | sample["ood_mask"] = torch.zeros_like(sample["ood_mask"]) 44 | return sample 45 | 46 | def _get_parameter_dict(self): 47 | return {"saturation_factor": self.saturation_factor} 48 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/random_hue_shifts.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | import os 3 | from os.path import join 4 | import random 5 | from froodo.data.samples.sample import Sample 6 | from froodo.ood.augmentations.types import OODAugmentation 7 | 8 | import imageio 9 | import cv2 as cv 10 | import numpy as np 11 | import torch 12 | 13 | import colorsys 14 | import scipy 15 | 16 | import torchvision 17 | 18 | from froodo.ood.severity.severity import ParameterSeverityMeasurement 19 | 20 | 21 | class RandomHueShiftAugmentation(OODAugmentation): 22 | def __init__(self) -> None: 23 | super().__init__() 24 | self.EPS = 0.0001 25 | self.severity_class = ParameterSeverityMeasurement("amount", (0, 0.5)) 26 | 27 | def _augment(self, sample: Sample) -> Sample: 28 | 29 | img = sample.image 30 | 31 | # find hue_factor in (-0.5, 0.5) 32 | hue_factor = np.random.normal(0, 0.2) 33 | hue_factor = max(min(hue_factor, 0.5), -0.5) 34 | 35 | self.amount = np.abs(hue_factor) 36 | 37 | img = torchvision.transforms.functional.adjust_hue(img, hue_factor) 38 | 39 | sample["image"] = img 40 | sample["ood_mask"] = torch.zeros_like(sample["ood_mask"]) 41 | return sample 42 | 43 | def _get_parameter_dict(self): 44 | return {"amount": self.amount} 45 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/random_value_shifts.py: -------------------------------------------------------------------------------- 1 | from os import listdir 2 | import os 3 | from os.path import join 4 | import random 5 | from froodo.data.samples.sample import Sample 6 | from froodo.ood.augmentations.types import OODAugmentation 7 | 8 | import imageio 9 | import cv2 as cv 10 | import numpy as np 11 | import torch 12 | 13 | import colorsys 14 | import scipy 15 | 16 | import torchvision 17 | 18 | from froodo.ood.severity.severity import ParameterSeverityMeasurement 19 | 20 | 21 | class RandomValueShiftAugmentation(OODAugmentation): 22 | def __init__(self) -> None: 23 | super().__init__() 24 | self.EPS = 0.0001 25 | self.severity_class = ParameterSeverityMeasurement( 26 | "amount", (self.EPS, 1 - self.EPS) 27 | ) 28 | 29 | def _augment(self, sample: Sample) -> Sample: 30 | 31 | img = sample.image 32 | 33 | # find brightness_factor in (0, infty) 34 | 35 | # amount in (0, 1) where 0 has the highest probability 36 | amount = np.abs(np.random.normal(0, 0.4)) 37 | amount = max(min(amount, 1 - self.EPS), 0 + self.EPS) # clamp to (0, 1) 38 | 39 | self.amount = amount 40 | 41 | direction = np.random.randint(0, 1 + 1) 42 | if direction == 0: 43 | brightness_factor = 1 - amount 44 | else: 45 | x = 1 - amount 46 | brightness_factor = 1 / x 47 | 48 | img = torchvision.transforms.functional.adjust_brightness( 49 | img, brightness_factor 50 | ) 51 | 52 | sample["image"] = img 53 | sample["ood_mask"] = torch.zeros_like(sample["ood_mask"]) 54 | return sample 55 | 56 | def _get_parameter_dict(self): 57 | return {"amount": self.amount} 58 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/endoscopy/vignette.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from froodo.data.samples.sample import Sample 3 | from froodo.ood.augmentations.types import INAugmentation 4 | 5 | import numpy as np 6 | 7 | 8 | class Vignette(INAugmentation): 9 | def __init__(self, percent_vignetting: float = 0) -> None: 10 | assert 0 <= percent_vignetting <= 1 11 | self.p = 1 - percent_vignetting 12 | 13 | # https://stackoverflow.com/questions/44865023/how-can-i-create-a-circular-mask-for-a-numpy-array 14 | 15 | def create_circular_mask(self, h, w, center=None, radius=None): 16 | 17 | if center is None: # use the middle of the image 18 | center = (int(w / 2), int(h / 2)) 19 | if ( 20 | radius is None 21 | ): # use the smallest distance between the center and image walls 22 | radius = min(center[0], center[1], w - center[0], h - center[1]) 23 | 24 | Y, X = np.ogrid[:h, :w] 25 | dist_from_center = np.sqrt((X - center[0]) ** 2 + (Y - center[1]) ** 2) 26 | 27 | mask = dist_from_center <= radius 28 | return torch.tensor(mask) 29 | 30 | def _augment(self, sample: Sample) -> Sample: 31 | img = sample.image.permute(1, 2, 0) # CHW -> HWC 32 | ood_mask = sample["ood_mask"] 33 | 34 | H, W, _ = img.shape 35 | 36 | mask = self.create_circular_mask( 37 | img.shape[0], img.shape[1], radius=self.p * max(H, W) / 2 38 | ) 39 | img[mask == 0] = torch.tensor([0, 0, 0]).float() 40 | ood_mask[mask == 0] = 1 # in distribution 41 | 42 | sample.image = img.permute(2, 0, 1) # HWC -> CHW 43 | return sample 44 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/indistribution/__init__.py: -------------------------------------------------------------------------------- 1 | from .crop import InCrop 2 | from .resize import InResize 3 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/indistribution/crop.py: -------------------------------------------------------------------------------- 1 | from torch import Tensor 2 | 3 | from typing import Tuple 4 | import random 5 | 6 | from .. import INAugmentation 7 | from ....data.samples import Sample 8 | 9 | 10 | class InCrop(INAugmentation): 11 | def __init__(self, crop_size) -> None: 12 | super().__init__() 13 | self.crop_size = crop_size 14 | 15 | def _augment(self, sample: Sample) -> Tuple[Tensor, Tensor]: 16 | _, height, width = sample.image.shape 17 | x = random.randint(0, width - self.crop_size[1]) 18 | y = random.randint(0, height - self.crop_size[0]) 19 | sample.image = sample.image[ 20 | :, y : y + self.crop_size[0], x : x + self.crop_size[1] 21 | ] 22 | required_size_for_resizing = (height, width) 23 | for k, v in sample.label_dict.items(): 24 | if v.shape == required_size_for_resizing: 25 | sample[k] = v[y : y + self.crop_size[0], x : x + self.crop_size[1]] 26 | return sample 27 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/indistribution/resize.py: -------------------------------------------------------------------------------- 1 | from torchvision.transforms import Resize 2 | from torchvision.transforms.functional import InterpolationMode 3 | from torch import Tensor 4 | 5 | from typing import Tuple 6 | 7 | from ..types import INAugmentation 8 | from ....data.samples import Sample 9 | 10 | 11 | class InResize(INAugmentation): 12 | def __init__(self, resize_size: Tuple[int, int]) -> None: 13 | super().__init__() 14 | self.resize_size = resize_size 15 | self.resize = Resize(self.resize_size, interpolation=InterpolationMode.NEAREST) 16 | 17 | def _augment(self, sample: Sample) -> Tuple[Tensor, Tensor]: 18 | img_shape = sample.image.shape 19 | sample.image = self.resize(sample.image.unsqueeze(0)).squeeze() 20 | required_size_for_resizing = (img_shape[1], img_shape[2]) 21 | for k, v in sample.label_dict.items(): 22 | if v.shape == required_size_for_resizing: 23 | sample[k] = self.resize(v.unsqueeze(0).unsqueeze(0)).squeeze() 24 | return sample 25 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/patchwise/__init__.py: -------------------------------------------------------------------------------- 1 | from .crop import ZoomInAugmentation 2 | from .gauss_blur import GaussianBlurAugmentation 3 | from .brightness import BrightnessAugmentation 4 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/patchwise/brightness.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torchvision.transforms import ColorJitter 3 | 4 | import random 5 | 6 | from ...augmentations import ( 7 | OODAugmentation, 8 | ProbabilityAugmentation, 9 | PickNComposite, 10 | SampableAugmentation, 11 | ) 12 | from ...severity import ParameterSeverityMeasurement, SeverityMeasurement 13 | from ....data import Sample 14 | from ..utils import full_image_ood 15 | 16 | 17 | class BrightnessAugmentation(OODAugmentation, SampableAugmentation): 18 | def __init__( 19 | self, 20 | brightness=1.5, 21 | sample_intervals=None, 22 | severity: SeverityMeasurement = None, 23 | keep_ignorred=True, 24 | ) -> None: 25 | super().__init__() 26 | self.brightness = brightness 27 | if sample_intervals == None: 28 | self.sample_intervals = [(0.2, 0.8), (1.2, 2)] 29 | else: 30 | self.sample_intervals = sample_intervals 31 | self.severity_class = ( 32 | ParameterSeverityMeasurement( 33 | "brightness", 34 | (self.sample_intervals[0][0], self.sample_intervals[-1][1]), 35 | ) 36 | if severity == None 37 | else severity 38 | ) 39 | self.keep_ignorred = keep_ignorred 40 | 41 | @property 42 | def brightness(self): 43 | return self._brightness 44 | 45 | @brightness.setter 46 | def brightness(self, value): 47 | if type(value) == tuple: 48 | self._brightness = value 49 | elif type(value) == float or type(value) == int: 50 | assert value > 0 51 | self._brightness = (value, value) 52 | self.jitter = ColorJitter(brightness=self.brightness) 53 | 54 | def _get_parameter_dict(self): 55 | return {"brightness": self.brightness[0]} 56 | 57 | def _apply_sampling(self): 58 | return super()._set_attr_to_uniform_samples_from_intervals( 59 | {"brightness": self.sample_intervals} 60 | ) 61 | 62 | def _augment(self, sample: Sample) -> Sample: 63 | sample["image"] = self.jitter(sample["image"]) 64 | sample = full_image_ood(sample, self.keep_ignorred) 65 | return sample 66 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/patchwise/crop.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torchvision.transforms import RandomCrop, Resize 3 | 4 | import random 5 | 6 | from ...augmentations import OODAugmentation, SampableAugmentation, InCrop, InResize 7 | from ....data import Sample 8 | from ...severity import ParameterSeverityMeasurement, SeverityMeasurement 9 | from ..utils import full_image_ood 10 | 11 | 12 | class ZoomInAugmentation(OODAugmentation, SampableAugmentation): 13 | def __init__( 14 | self, 15 | crop=0.5, 16 | sample_intervals=None, 17 | severity: SeverityMeasurement = None, 18 | keep_ignorred=True, 19 | ) -> None: 20 | super().__init__() 21 | assert crop > 0 and crop <= 1 22 | self.crop = crop 23 | if sample_intervals == None: 24 | self.sample_intervals = [(0.2, 0.9)] 25 | else: 26 | self.sample_intervals = sample_intervals 27 | self.severity_class = ( 28 | ParameterSeverityMeasurement( 29 | "crop", (self.sample_intervals[0][0], self.sample_intervals[-1][1]) 30 | ) 31 | if severity == None 32 | else severity 33 | ) 34 | self.keep_ignorred = keep_ignorred 35 | 36 | def _get_parameter_dict(self): 37 | return {"crop": self.crop} 38 | 39 | def _apply_sampling(self): 40 | return super()._set_attr_to_uniform_samples_from_intervals( 41 | {"crop": self.sample_intervals} 42 | ) 43 | 44 | def _augment(self, sample: Sample) -> Sample: 45 | 46 | _, h, w = sample.image.shape 47 | sample = InCrop((round(self.crop * h), round(self.crop * w)))(sample) 48 | sample = InResize((h, w))(sample) 49 | 50 | sample = full_image_ood(sample, self.keep_ignorred) 51 | return sample 52 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/patchwise/gauss_blur.py: -------------------------------------------------------------------------------- 1 | from numpy import full 2 | from torchvision.transforms import GaussianBlur 3 | import torch 4 | 5 | from copy import deepcopy 6 | 7 | from ...augmentations import OODAugmentation, SampableAugmentation 8 | from ....data import Sample 9 | from ...severity import ParameterSeverityMeasurement, SeverityMeasurement 10 | from ..utils import full_image_ood 11 | 12 | 13 | class GaussianBlurAugmentation(OODAugmentation, SampableAugmentation): 14 | def __init__( 15 | self, 16 | kernel_size=(19, 19), 17 | sigma=2, 18 | sample_intervals=None, 19 | severity: SeverityMeasurement = None, 20 | keep_ignorred=True, 21 | ) -> None: 22 | super().__init__() 23 | self.kernel_size = kernel_size 24 | self.sigma = sigma 25 | if sample_intervals == None: 26 | self.sample_intervals = [(1.2, 2.5)] 27 | else: 28 | self.sample_intervals = sample_intervals 29 | self.severity_class = ( 30 | ParameterSeverityMeasurement( 31 | "sigma", (self.sample_intervals[0][0], self.sample_intervals[-1][1]) 32 | ) 33 | if severity == None 34 | else severity 35 | ) 36 | self.keep_ignorred = keep_ignorred 37 | 38 | @property 39 | def sigma(self): 40 | return self._sigma 41 | 42 | @sigma.setter 43 | def sigma(self, value): 44 | self._sigma = value 45 | self.augmentation = GaussianBlur(kernel_size=self.kernel_size, sigma=self.sigma) 46 | 47 | def _apply_sampling(self): 48 | return super()._set_attr_to_uniform_samples_from_intervals( 49 | {"sigma": self.sample_intervals} 50 | ) 51 | 52 | def _get_parameter_dict(self): 53 | return {"sigma": self.sigma} 54 | 55 | def _augment(self, sample: Sample) -> Sample: 56 | sample["image"] = self.augmentation(sample["image"]) 57 | sample = full_image_ood(sample, self.keep_ignorred) 58 | return sample 59 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/__init__.py -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/__init__.py: -------------------------------------------------------------------------------- 1 | from .artifacts import ArtifactAugmentation 2 | from .squamos import SquamousAugmentation 3 | from .dark_spots import DarkSpotsAugmentation 4 | from .threads import ThreadAugmentation 5 | from .fat import FatAugmentation 6 | from .blood_group import BloodGroupAugmentation 7 | from .blood_cell import BloodCellAugmentation 8 | from .bubble import BubbleAugmentation -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/artifacts.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import numpy as np 3 | import cv2 as cv 4 | from scipy import ndimage 5 | 6 | import imageio 7 | from random import randint 8 | import os 9 | 10 | from .....data.metadata import * 11 | 12 | this_dir, this_filename = os.path.split(__file__) 13 | data_folder = os.path.join(this_dir, "imgs") 14 | 15 | 16 | class ArtifactAugmentation: 17 | def transparentOverlay( 18 | self, 19 | src, 20 | mask, 21 | scale=2, 22 | mask_threshold=0.3, 23 | overlay_path="imgs/dark_spots/small_spot.png", 24 | width_slack=(0.3, 0.3), 25 | height_slack=(0.3, 0.3), 26 | ignore_index=None, 27 | ): 28 | src = src.permute(1, 2, 0) 29 | overlay = imageio.imread(overlay_path) / 255.0 30 | overlay = cv.resize(overlay, (0, 0), fx=scale, fy=scale) 31 | index = np.round(ndimage.measurements.center_of_mass(overlay[..., 3])).astype( 32 | np.int64 33 | ) 34 | h_overlay, w_overlay, _ = overlay.shape 35 | h_img, w_img, _ = src.shape 36 | 37 | min_vert = -int(h_overlay * height_slack[0]) 38 | max_vert = max(min_vert + 1, h_img + int(h_overlay * height_slack[1])) 39 | 40 | he = randint( 41 | min_vert, 42 | max_vert, 43 | ) 44 | 45 | min_hor = -int(w_overlay * width_slack[0]) 46 | max_hor = max(min_hor + 1, w_img + int(w_overlay * width_slack[1])) 47 | 48 | wi = randint(min_hor, max_hor) 49 | pos = (he - index[0], wi - index[1]) 50 | 51 | assert pos[0] + h_overlay > 0 and pos[0] - h_overlay - h_img < 0 52 | assert pos[1] + w_overlay > 0 and pos[1] - w_overlay - w_img < 0 53 | 54 | from_y_art = max(-pos[0], 0) 55 | from_x_art = max(-pos[1], 0) 56 | from_y = -min(-pos[0], 0) 57 | from_x = -min(-pos[1], 0) 58 | until_y = min(h_overlay - from_y_art + from_y, h_img) 59 | until_x = min(w_overlay - from_x_art + from_x, w_img) 60 | until_y_art = from_y_art + until_y - from_y 61 | until_x_art = from_x_art + until_x - from_x 62 | 63 | alpha = torch.from_numpy(overlay[:, :, 3]) 64 | overlayed = ( 65 | alpha[from_y_art:until_y_art, from_x_art:until_x_art, np.newaxis] 66 | * overlay[from_y_art:until_y_art, from_x_art:until_x_art, :3] 67 | + (1 - alpha[from_y_art:until_y_art, from_x_art:until_x_art, np.newaxis]) 68 | * src[from_y:until_y, from_x:until_x, :] 69 | ) 70 | src[from_y:until_y, from_x:until_x, :] = overlayed 71 | 72 | ood_indices = torch.from_numpy( 73 | overlay[from_y_art:until_y_art, from_x_art:until_x_art, 3] > mask_threshold 74 | ) 75 | 76 | if ignore_index != None: 77 | ignore_mask = mask == ignore_index 78 | 79 | mask[from_y:until_y, from_x:until_x][ood_indices] = 0 80 | 81 | if ignore_index != None: 82 | mask[ignore_mask] = ignore_index 83 | 84 | return src.permute(2, 0, 1), mask 85 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/blood_cell.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os import listdir 3 | from os.path import join 4 | 5 | from typing import Optional, Tuple 6 | 7 | 8 | from ....augmentations import OODAugmentation, SampableAugmentation 9 | from .artifacts import ArtifactAugmentation, data_folder 10 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 11 | from .....data.metadata import * 12 | from ...utils import * 13 | from .....data.samples import Sample 14 | 15 | 16 | class BloodCellAugmentation( 17 | ArtifactAugmentation, OODAugmentation, SampableAugmentation 18 | ): 19 | def __init__( 20 | self, 21 | num_cells: int = 10, 22 | scale=1, 23 | severity: SeverityMeasurement = None, 24 | path=None, 25 | mask_threshold: float = 0.5, 26 | sample_intervals: Optional[List[Tuple[float, float]]] = None, 27 | scale_sample_intervals: Optional[List[Tuple[float, float]]] = None, 28 | keep_ignorred: bool = True, 29 | ) -> None: 30 | super().__init__() 31 | self.scale = scale 32 | self.num_cells = num_cells 33 | self.path = path 34 | self.mask_threshold = mask_threshold 35 | self.severity_class: SeverityMeasurement = ( 36 | PixelPercentageSeverityMeasurement() if severity == None else severity 37 | ) 38 | if sample_intervals == None: 39 | self.sample_intervals = [(1, 50)] 40 | else: 41 | self.sample_intervals = sample_intervals 42 | 43 | self.scale_sample_intervals = scale_sample_intervals 44 | self.keep_ignorred = keep_ignorred 45 | 46 | def _apply_sampling(self): 47 | super()._set_attr_to_uniform_samples_from_intervals( 48 | {"num_cells": self.sample_intervals} 49 | ) 50 | 51 | def _augment(self, sample: Sample) -> Sample: 52 | for i in range(int(self.num_cells)): 53 | if self.scale_sample_intervals != None: 54 | super()._set_attr_to_uniform_samples_from_intervals( 55 | {"scale": self.scale_sample_intervals} 56 | ) 57 | img, mask = super().transparentOverlay( 58 | sample["image"], 59 | sample["ood_mask"], 60 | scale=self.scale, 61 | mask_threshold=self.mask_threshold, 62 | overlay_path=join( 63 | data_folder, 64 | f"cell/{random.choice(listdir(join(data_folder,'cell')))}", 65 | ) 66 | if self.path == None 67 | else self.path, 68 | width_slack=(-0.1, -0.1), 69 | height_slack=(-0.1, -0.1), 70 | ignore_index=None 71 | if not self.keep_ignorred 72 | else sample.metadata["ignore_index"], 73 | ) 74 | sample["image"] = img 75 | sample["ood_mask"] = mask 76 | 77 | return sample 78 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/blood_group.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os import listdir 3 | from os.path import join 4 | from copy import deepcopy 5 | 6 | from ....augmentations import OODAugmentation, SampableAugmentation 7 | from .artifacts import ArtifactAugmentation, data_folder 8 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 9 | from .....data.datatypes import DistributionSampleType 10 | from .....data.samples import Sample 11 | 12 | 13 | class BloodGroupAugmentation( 14 | OODAugmentation, ArtifactAugmentation, SampableAugmentation 15 | ): 16 | def __init__( 17 | self, 18 | scale=1, 19 | num_groups=None, 20 | path=None, 21 | severity: SeverityMeasurement = None, 22 | mask_threshold=0.5, 23 | sample_intervals=None, 24 | keep_ignorred=True, 25 | ) -> None: 26 | super().__init__() 27 | self.scale = scale 28 | self.path = path 29 | self.mask_threshold = mask_threshold 30 | self.num_groups = 1 31 | if num_groups == None: 32 | self.num_groups_sample_intervals = [(1.0,1.1)] 33 | else: 34 | self.num_groups_sample_intervals = num_groups 35 | if sample_intervals == None: 36 | self.sample_intervals = [(0.1, 2)] 37 | else: 38 | self.sample_intervals = sample_intervals 39 | self.severity_class: SeverityMeasurement = ( 40 | PixelPercentageSeverityMeasurement() if severity == None else severity 41 | ) 42 | self.keep_ignorred = keep_ignorred 43 | 44 | def _apply_sampling(self): 45 | return super()._set_attr_to_uniform_samples_from_intervals( 46 | {"scale": self.sample_intervals, 47 | "num_groups": self.num_groups_sample_intervals} 48 | ) 49 | 50 | def _augment(self, sample: Sample) -> Sample: 51 | for i in range(int(self.num_groups)): 52 | img, mask = super().transparentOverlay( 53 | sample["image"], 54 | sample["ood_mask"], 55 | scale=self.scale, 56 | mask_threshold=self.mask_threshold, 57 | overlay_path=join( 58 | data_folder, 59 | f"group/{random.choice(listdir(join(data_folder,'group')))}", 60 | ) 61 | if self.path == None 62 | else self.path, 63 | width_slack=(-0.1, -0.1), 64 | height_slack=(-0.1, -0.1), 65 | ignore_index=None 66 | if not self.keep_ignorred 67 | else sample.metadata["ignore_index"], 68 | ) 69 | sample["image"] = img 70 | sample["ood_mask"] = mask 71 | 72 | return sample 73 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/bubble.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os import listdir 3 | from os.path import join 4 | 5 | import cv2 6 | from PIL import Image 7 | import torchvision.transforms as T 8 | from torchvision.transforms import GaussianBlur 9 | from copy import deepcopy 10 | 11 | from ....augmentations import OODAugmentation 12 | from .artifacts import ArtifactAugmentation, data_folder 13 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 14 | from .....data.metadata import * 15 | from ...utils import * 16 | from .....data.samples import Sample 17 | 18 | 19 | #op100, hard98 20 | #op51, hard44 3 times! 21 | class BubbleAugmentation(ArtifactAugmentation, OODAugmentation): 22 | def __init__( 23 | self, 24 | base_augmentation = GaussianBlur(kernel_size=(19, 19),sigma=5), 25 | scale=1, 26 | severity: SeverityMeasurement = None, 27 | path=None, 28 | mask_threshold=0.1, 29 | sample_range=None, 30 | keep_ignorred=True, 31 | ) -> None: 32 | super().__init__() 33 | self.scale = scale 34 | self.path = path 35 | self.base_augmentation = base_augmentation 36 | self.mask_threshold = mask_threshold 37 | self.severity_class: SeverityMeasurement = ( 38 | PixelPercentageSeverityMeasurement() if severity == None else severity 39 | ) 40 | if sample_range == None: 41 | self.sample_range = {"scale": (0.5, 0.9)} 42 | else: 43 | self.sample_range = sample_range 44 | self.keep_ignorred = keep_ignorred 45 | 46 | def param_range(self): 47 | return self.sample_range 48 | 49 | def _augment(self, sample: Sample) -> Sample: 50 | 51 | #sample["image2"] = sample.image.clone().permute(1,2,0) 52 | 53 | #set up transforms 54 | _, h, w = sample.image.shape 55 | toPIL = T.ToPILImage() 56 | toTensor = T.ToTensor() 57 | 58 | #get overlay (should have alpha value) 59 | overlay_path=join( 60 | "froodo/ood/augmentations/pathology/artifacts/imgs/bubble", 61 | random.choice( 62 | listdir("froodo/ood/augmentations/pathology/artifacts/imgs/bubble") 63 | )) 64 | overlay = Image.open(overlay_path) 65 | 66 | #resize overlay to image size and add to base image 67 | overlay = overlay.resize((h,w)) 68 | img = toPIL(sample["image"]) 69 | img.paste(overlay,(0,0),overlay) 70 | img = toTensor(img) 71 | 72 | #prepare further computation 73 | overlay = toTensor(overlay) 74 | copied_img = deepcopy(img) 75 | 76 | #coinflip on wether to apply the augmentation inside or outside of bubble 77 | if bool(random.getrandbits(1)) == 1: 78 | img[:,overlay[3,:,:] > self.mask_threshold] = self.base_augmentation(copied_img)[:,overlay[3,:,:] > self.mask_threshold] 79 | else: 80 | img[:,overlay[3,:,:] < self.mask_threshold] = self.base_augmentation(copied_img)[:,overlay[3,:,:] < self.mask_threshold] 81 | 82 | #set sample 83 | sample["image"] = img 84 | sample["ood_mask"][overlay[3,:,:] > self.mask_threshold] = 0 85 | 86 | return sample -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/dark_spots.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os import listdir 3 | from os.path import join 4 | 5 | 6 | from ....augmentations import OODAugmentation, SampableAugmentation 7 | from .artifacts import ArtifactAugmentation, data_folder 8 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 9 | from .....data.metadata import * 10 | from ...utils import * 11 | from .....data.samples import Sample 12 | 13 | 14 | class DarkSpotsAugmentation( 15 | ArtifactAugmentation, OODAugmentation, SampableAugmentation 16 | ): 17 | def __init__( 18 | self, 19 | scale=1, 20 | severity: SeverityMeasurement = None, 21 | path=join(data_folder, "dark_spots/small_spot.png"), 22 | mask_threshold=0.5, 23 | sample_intervals=None, 24 | keep_ignorred=True, 25 | ) -> None: 26 | super().__init__() 27 | self.scale = scale 28 | self.path = path 29 | self.mask_threshold = mask_threshold 30 | self.severity_class: SeverityMeasurement = ( 31 | PixelPercentageSeverityMeasurement() if severity == None else severity 32 | ) 33 | if sample_intervals == None: 34 | self.sample_intervals = [(0.1, 5)] 35 | else: 36 | self.sample_intervals = sample_intervals 37 | self.keep_ignorred = keep_ignorred 38 | 39 | def _apply_sampling(self): 40 | return super()._set_attr_to_uniform_samples_from_intervals( 41 | {"scale": self.sample_intervals} 42 | ) 43 | 44 | def _augment(self, sample: Sample) -> Sample: 45 | img, mask = super().transparentOverlay( 46 | sample["image"], 47 | sample["ood_mask"], 48 | scale=self.scale, 49 | mask_threshold=self.mask_threshold, 50 | overlay_path=join( 51 | data_folder, 52 | f"dark_spots/{random.choice(listdir(join(data_folder,'dark_spots')))}", 53 | ) 54 | if self.path == None 55 | else self.path, 56 | width_slack=(-0.1, -0.1), 57 | height_slack=(-0.1, -0.1), 58 | ignore_index=None 59 | if not self.keep_ignorred 60 | else sample.metadata["ignore_index"], 61 | ) 62 | sample["image"] = img 63 | sample["ood_mask"] = mask 64 | 65 | return sample 66 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/fat.py: -------------------------------------------------------------------------------- 1 | from os.path import join 2 | from copy import deepcopy 3 | 4 | from ....augmentations import OODAugmentation, SampableAugmentation 5 | from .artifacts import ArtifactAugmentation, data_folder 6 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 7 | from .....data.datatypes import DistributionSampleType 8 | from .....data.samples import Sample 9 | 10 | 11 | class FatAugmentation(OODAugmentation, ArtifactAugmentation, SampableAugmentation): 12 | def __init__( 13 | self, 14 | scale=1, 15 | severity: SeverityMeasurement = None, 16 | mask_threshold=0.4, 17 | sample_intervals=None, 18 | keep_ignorred=True, 19 | ) -> None: 20 | super().__init__() 21 | self.scale = scale 22 | self.mask_threshold = mask_threshold 23 | if sample_intervals == None: 24 | self.sample_intervals = [(0.1, 5)] 25 | else: 26 | self.sample_intervals = sample_intervals 27 | self.severity_class: SeverityMeasurement = ( 28 | PixelPercentageSeverityMeasurement() if severity == None else severity 29 | ) 30 | self.keep_ignorred = keep_ignorred 31 | 32 | def _apply_sampling(self): 33 | return super()._set_attr_to_uniform_samples_from_intervals( 34 | {"scale": self.sample_intervals} 35 | ) 36 | 37 | def _augment(self, sample: Sample) -> Sample: 38 | img, mask = super().transparentOverlay( 39 | sample["image"], 40 | sample["ood_mask"], 41 | scale=self.scale, 42 | mask_threshold=self.mask_threshold, 43 | overlay_path=join(data_folder, "fat", "fat.png"), 44 | width_slack=(-0.1, -0.1), 45 | height_slack=(-0.1, -0.1), 46 | ignore_index=None 47 | if not self.keep_ignorred 48 | else sample.metadata["ignore_index"], 49 | ) 50 | sample["image"] = img 51 | sample["ood_mask"] = mask 52 | 53 | return sample 54 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b10.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b11.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/bubble/b4.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300_1.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300_2.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.2300_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.2300_1.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300_1.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300_2.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P1-DX1_xmin50567_ymin38988_MPP-0.2300_1.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P1-DX1_xmin50567_ymin38988_MPP-0.2300_1.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.23001.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.23001.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.2300_2.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.2300_2.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.2300_3.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/cell/TCGA-EW-A1P8-DX1_xmin15520_ymin26381_MPP-0.2300_3.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP3.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/SP4.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/med_spot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/med_spot.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/med_spot_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/med_spot_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/med_spot_2_2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/med_spot_2_2x.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/small_spot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/dark_spots/small_spot.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/fat/fat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/fat/fat.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-A7-A26F-DX1_xmin72969_ymin11489_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-A7-A26F-DX1_xmin72969_ymin11489_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AC-A2QH-DX1_xmin42173_ymin16859_MPP-01.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.23001.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AN-A0AL-DX1_xmin15698_ymin29806_MPP-0.23001.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AN-A0G0-DX1_xmin32741_ymin14546_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AO-A0J6-DX1_xmin40548_ymin11135_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AO-A0J6-DX1_xmin40548_ymin11135_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AQ-A54N-DX1_xmin32440_ymin26558_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AQ-A54N-DX1_xmin32440_ymin26558_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A0U1-DX1_xmin63681_ymin24922_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A0U1-DX1_xmin63681_ymin24922_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A1AI-DX1_xmin38671_ymin10616_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A1AI-DX1_xmin38671_ymin10616_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A1AR-DX1_xmin12708_ymin29100_MPP-0.2300.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A1AR-DX1_xmin12708_ymin29100_MPP-0.2300.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A1AR-DX1_xmin12708_ymin29100_MPP-0.23001.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/group/TCGA-AR-A1AR-DX1_xmin12708_ymin29100_MPP-0.23001.tif -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq10.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq10s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq10s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq11.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq11.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq11s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq11s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq12.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq12s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq12s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq13.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq13s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq13s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq14.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq14.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq14s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq14s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq15.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq15.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq15s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq15s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq16.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq16s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq16s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq17.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq17.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq17s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq17s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq18.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq18.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq18s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq18s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq19.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq19s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq19s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq1s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq1s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq20.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq20s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq20s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq2s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq2s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq3.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq3s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq3s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq4.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq4s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq4s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq5.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq5s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq5s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq6.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq6s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq6s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq7.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq7s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq7s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq8.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq8s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq8s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq9.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq9s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/squamous/sq9s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_10.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_10s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_10s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_1s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_1s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_2s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_2s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_3.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_32.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_4.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_4s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_4s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_5.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_5s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_5s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_6.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_6s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_6s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_7.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_7s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_7s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_8.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_8s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_8s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_9.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_9s.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/artifacts/imgs/threads/thread_9s.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/squamos.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os import listdir 3 | from os.path import join 4 | from copy import deepcopy 5 | 6 | from ....augmentations import OODAugmentation, SampableAugmentation 7 | from .artifacts import ArtifactAugmentation, data_folder 8 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 9 | from .....data.datatypes import DistributionSampleType 10 | from .....data.samples import Sample 11 | 12 | 13 | class SquamousAugmentation(OODAugmentation, ArtifactAugmentation, SampableAugmentation): 14 | def __init__( 15 | self, 16 | scale=1, 17 | path=None, 18 | severity: SeverityMeasurement = None, 19 | mask_threshold=0.3, 20 | sample_intervals=None, 21 | keep_ignorred=True, 22 | ) -> None: 23 | super().__init__() 24 | self.scale = scale 25 | self.path = path 26 | self.mask_threshold = mask_threshold 27 | if sample_intervals == None: 28 | self.sample_intervals = [(0.1, 4)] 29 | else: 30 | self.sample_intervals = sample_intervals 31 | self.severity_class: SeverityMeasurement = ( 32 | PixelPercentageSeverityMeasurement() if severity == None else severity 33 | ) 34 | self.keep_ignorred = keep_ignorred 35 | 36 | def _apply_sampling(self): 37 | return super()._set_attr_to_uniform_samples_from_intervals( 38 | {"scale": self.sample_intervals} 39 | ) 40 | 41 | def _augment(self, sample: Sample) -> Sample: 42 | img, mask = super().transparentOverlay( 43 | sample["image"], 44 | sample["ood_mask"], 45 | scale=self.scale, 46 | overlay_path=join( 47 | data_folder, 48 | f"squamous/{random.choice(listdir(join(data_folder,'squamous')))}", 49 | ) 50 | if self.path == None 51 | else self.path, 52 | mask_threshold=self.mask_threshold, 53 | width_slack=(-0.1, -0.1), 54 | height_slack=(-0.1, -0.1), 55 | ignore_index=None 56 | if not self.keep_ignorred 57 | else sample.metadata["ignore_index"], 58 | ) 59 | sample["image"] = img 60 | sample["ood_mask"] = mask 61 | 62 | return sample 63 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/artifacts/threads.py: -------------------------------------------------------------------------------- 1 | import random 2 | from os import listdir 3 | from os.path import join 4 | from copy import deepcopy 5 | 6 | from ....augmentations import OODAugmentation, SampableAugmentation 7 | from .artifacts import ArtifactAugmentation, data_folder 8 | from .....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 9 | from .....data.datatypes import DistributionSampleType 10 | from .....data.samples import Sample 11 | 12 | 13 | class ThreadAugmentation(OODAugmentation, ArtifactAugmentation, SampableAugmentation): 14 | def __init__( 15 | self, 16 | scale=1, 17 | path=None, 18 | severity: SeverityMeasurement = None, 19 | mask_threshold=0.3, 20 | sample_intervals=None, 21 | keep_ignorred=True, 22 | ) -> None: 23 | super().__init__() 24 | self.scale = scale 25 | self.path = path 26 | self.mask_threshold = mask_threshold 27 | if sample_intervals == None: 28 | self.sample_intervals = [(0.1, 9)] 29 | else: 30 | self.sample_intervals = sample_intervals 31 | self.severity_class: SeverityMeasurement = ( 32 | PixelPercentageSeverityMeasurement() if severity == None else severity 33 | ) 34 | self.keep_ignorred = keep_ignorred 35 | 36 | def _apply_sampling(self): 37 | return super()._set_attr_to_uniform_samples_from_intervals( 38 | {"scale": self.sample_intervals} 39 | ) 40 | 41 | def _augment(self, sample: Sample) -> Sample: 42 | img, mask = super().transparentOverlay( 43 | sample["image"], 44 | sample["ood_mask"], 45 | scale=self.scale, 46 | overlay_path=join( 47 | data_folder, 48 | f"threads/{random.choice(listdir(join(data_folder,'threads')))}", 49 | ) 50 | if self.path == None 51 | else self.path, 52 | mask_threshold=self.mask_threshold, 53 | width_slack=(0, 0), 54 | height_slack=(0, 0), 55 | ignore_index=None 56 | if not self.keep_ignorred 57 | else sample.metadata["ignore_index"], 58 | ) 59 | sample["image"] = img 60 | sample["ood_mask"] = mask 61 | 62 | return sample 63 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/__init__.py: -------------------------------------------------------------------------------- 1 | from .overlap import OverlapAugmentation, FoldingAugmentation 2 | from .deformation import Deformation -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/imgs/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/deforming/imgs/7.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/imgs/squeeze/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/deforming/imgs/squeeze/5.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/imgs/squeeze/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/deforming/imgs/squeeze/6.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/imgs/stretch/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/deforming/imgs/stretch/5.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/imgs/stretch/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/deforming/imgs/stretch/6.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/pathology/deforming/imgs/stretch/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/pathology/deforming/imgs/stretch/7.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/utility/__init__.py: -------------------------------------------------------------------------------- 1 | from .composites import * 2 | from .util_aug import * 3 | from .sampling import * 4 | from .pipeline import * 5 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/utility/composites.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | from ..types import OODAugmentation 4 | from ...augmentations import AugmentationComposite 5 | from ....data import Sample 6 | from ....data import SampleMetadataCommonTypes 7 | 8 | 9 | class PickNComposite(AugmentationComposite): 10 | def __init__( 11 | self, augmentations, n=1, replace=False, probabilities=None, keep_severity=False 12 | ) -> None: 13 | super().__init__(augmentations) 14 | self.n = n 15 | self.replace = replace 16 | self.keep_severity = keep_severity 17 | if probabilities == None: 18 | self.probabilities = np.ones(len(self.augmentations)) / len( 19 | self.augmentations 20 | ) 21 | else: 22 | self.probabilities = probabilities 23 | 24 | def _set_metadata(self, sample: Sample) -> Sample: 25 | if not self.keep_severity: 26 | sample.metadata[SampleMetadataCommonTypes.OOD_SEVERITY.name] = None 27 | return sample 28 | 29 | def _augment(self, sample: Sample) -> Sample: 30 | for augmentation in np.random.choice( 31 | self.augmentations, self.n, replace=self.replace, p=self.probabilities 32 | ): 33 | sample = augmentation(sample) 34 | return sample 35 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/utility/partial.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import random 3 | import numpy as np 4 | 5 | from copy import deepcopy 6 | 7 | from ....ood.severity import PixelPercentageSeverityMeasurement, SeverityMeasurement 8 | 9 | from ..types import Augmentation 10 | from ....data.samples import Sample 11 | from ...augmentations import ( 12 | OODAugmentation, 13 | ) 14 | 15 | 16 | class PartialOODAugmentaion(OODAugmentation): 17 | def __init__(self, base_augmentation, mode="linear", severity: SeverityMeasurement = None) -> None: 18 | super().__init__() 19 | self.base_augmentation = base_augmentation 20 | assert mode in ["linear", "axes"] 21 | self.mode = mode 22 | self.severity_class: SeverityMeasurement = ( 23 | PixelPercentageSeverityMeasurement() if severity == None else severity 24 | ) 25 | 26 | def _get_parameter_dict(self): 27 | return {} 28 | 29 | def _augment(self, sample: Sample) -> Sample: 30 | 31 | _, h, w = sample.image.shape 32 | # direction determines direction of mask 33 | direction = random.uniform(0, 1) > 0.5 34 | 35 | grid_y, grid_x = torch.meshgrid(torch.arange(0, h), torch.arange(0, h)) 36 | 37 | # choose direction/mode in which the picture is cut 38 | if self.mode == "axes": 39 | # flip chooses axis of image 40 | flip = random.uniform(0, 1) > 0.5 41 | if direction: 42 | mask = (grid_x if flip else grid_y) > ( 43 | random.randint(0, w) if flip else random.randint(0, h) 44 | ) 45 | else: 46 | mask = (grid_x if flip else grid_y) < ( 47 | random.randint(0, w) if flip else random.randint(0, h) 48 | ) 49 | elif self.mode == "linear": 50 | # calculate random linear functions 51 | wx = random.random() * np.sqrt(2) 52 | wy = random.random() * np.sqrt(2) 53 | b = random.random() * np.sqrt(h * w / 4) * max(wx, wy) 54 | if random.random() > 0.5: 55 | wx *= -1 56 | else: 57 | wy *= -1 58 | 59 | mask = wx * (grid_x - (w / 2)) + wy * (grid_y - (h / 2)) + b > 0 60 | 61 | else: 62 | raise ValueError("Given mode is not valid") 63 | 64 | # apply augmentation 65 | copied_img = deepcopy(sample) 66 | copied_img = self.base_augmentation(copied_img) 67 | sample.image[:, mask] = copied_img.image[:, mask] 68 | sample["ood_mask"][mask] = copied_img["ood_mask"][mask] 69 | sample.metadata = copied_img.metadata 70 | 71 | return sample 72 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/utility/pipeline.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from ..indistribution.crop import InCrop 4 | from ..indistribution.resize import InResize 5 | from ..types import ( 6 | Augmentation, 7 | INAugmentation, 8 | OODAugmentation, 9 | SizeAugmentation, 10 | AugmentationComposite, 11 | ) 12 | from ....data.samples import Sample 13 | 14 | 15 | class AugmentationPipeline(AugmentationComposite): 16 | def __init__(self, Augmentations) -> None: 17 | super().__init__(Augmentations) 18 | 19 | def __call__(self, sample: Sample) -> Sample: 20 | for a in self.augmentations: 21 | sample = a(sample) 22 | return sample 23 | 24 | 25 | class SizeInOODPipeline(AugmentationPipeline): 26 | def __init__( 27 | self, 28 | size_augmentations: List[SizeAugmentation] = None, 29 | in_augmentations: List[INAugmentation] = [ 30 | InCrop((600, 600)), 31 | InResize((300, 300)), 32 | ], 33 | ood_augmentations: List[OODAugmentation] = None, 34 | ) -> None: 35 | super().__init__( 36 | (size_augmentations if size_augmentations != None else []) 37 | + (in_augmentations if in_augmentations != None else []) 38 | + (ood_augmentations if ood_augmentations != None else []) 39 | ) 40 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/utility/sampling.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import random 4 | 5 | from ..types import Augmentation, SampableAugmentation 6 | from ....data.datatypes import DistributionSampleType 7 | from ....data.samples import Sample 8 | from ..utils import init_augmentation 9 | 10 | 11 | class SampledAugmentation(Augmentation): 12 | def __init__(self, augmentation: SampableAugmentation, probability=0.7) -> None: 13 | assert isinstance( 14 | augmentation, SampableAugmentation 15 | ), "Augmentation that should be sampled needs to be instance of SampableAugmentation" 16 | self.augmentation: SampableAugmentation = augmentation 17 | self.probability = probability 18 | 19 | def __call__(self, sample: Sample): 20 | sample = init_augmentation(sample) 21 | self.sample_params() 22 | if self.skip: 23 | return sample 24 | 25 | i = 0 26 | while True: 27 | # if augmentation should be applied, try at most 10 times to get an OOD Sample 28 | # This my be necessary if the artifact is places outside the patch 29 | sample = self.augmentation(sample) 30 | 31 | if sample.metadata["type"] is DistributionSampleType.OOD_DATA or i >= 10: 32 | break 33 | self.sample_params() 34 | i += 1 35 | 36 | return sample 37 | 38 | def sample_params(self): 39 | if random.random() >= self.probability: 40 | self.skip = True 41 | return 42 | else: 43 | self.skip = False 44 | 45 | self.augmentation._apply_sampling() 46 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/utility/util_aug.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from ...augmentations import OODAugmentation 4 | from ....data.samples import Sample 5 | 6 | 7 | class ProbabilityAugmentation(OODAugmentation): 8 | def __init__(self, augmentation, prob=0.5) -> None: 9 | super().__init__() 10 | assert isinstance(augmentation, OODAugmentation) 11 | self.augmentation = augmentation 12 | self.prob = prob 13 | 14 | def __call__(self, sample: Sample) -> Sample: 15 | if random.random() >= self.prob: 16 | return sample 17 | return self.augmentation(sample) 18 | 19 | 20 | class Nothing(OODAugmentation): 21 | def __init__(self) -> None: 22 | super().__init__() 23 | 24 | def __call__(self, sample: Sample) -> Sample: 25 | return sample 26 | 27 | 28 | class NTimesAugmentation(OODAugmentation): 29 | def __init__(self, augmentation, n) -> None: 30 | super().__init__() 31 | self.augmentation = augmentation 32 | self.n = n 33 | 34 | def __call__(self, sample: Sample) -> Sample: 35 | for _ in range(self.n): 36 | sample = self.augmentation(sample) 37 | return sample 38 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/utils.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from ...data.metadata import init_sample_metadata 4 | from ...data.samples import Sample 5 | 6 | 7 | def init_augmentation(sample: Sample) -> Sample: 8 | if sample["ood_mask"] == None: 9 | sample["ood_mask"] = create_pseudo_mask(sample["image"].shape) 10 | sample.metadata = init_sample_metadata(sample.metadata) 11 | return sample 12 | 13 | 14 | def create_pseudo_mask(img_shape): 15 | return torch.ones((img_shape[1], img_shape[2])) 16 | 17 | 18 | def full_image_ood(sample: Sample, keep_ignorred): 19 | if keep_ignorred: 20 | ignore_map = sample["ood_mask"] == sample.metadata["ignore_index"] 21 | sample["ood_mask"] = torch.zeros_like(sample["ood_mask"]) 22 | if keep_ignorred: 23 | sample["ood_mask"][ignore_map] = sample.metadata["ignore_index"] 24 | return sample 25 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/__init__.py: -------------------------------------------------------------------------------- 1 | from .gauss_noise import GaussianNoiseAugmentation 2 | from .motion_blur import MotionBlurAugmentation 3 | from .artifacts import TubesAugmentation 4 | from .artifacts import CoinAugmentation 5 | from .artifacts import ForeignBodiesAugmentation 6 | from .artifacts import NailsAugmentation 7 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/__init__.py: -------------------------------------------------------------------------------- 1 | from .tubes import TubesAugmentation 2 | from .coin import CoinAugmentation 3 | from .nails import NailsAugmentation 4 | from .foreign_bodies import ForeignBodiesAugmentation 5 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/imgs/coin/coin1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/xray/artifacts/imgs/coin/coin1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/imgs/coin/coin2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/xray/artifacts/imgs/coin/coin2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/imgs/foreign/nut.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/xray/artifacts/imgs/foreign/nut.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/imgs/nails/nail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/xray/artifacts/imgs/nails/nail.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/imgs/tubes/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/xray/artifacts/imgs/tubes/test1.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/artifacts/imgs/tubes/test2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/augmentations/xray/artifacts/imgs/tubes/test2.png -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/gauss_noise.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import albumentations as A 3 | from ...augmentations import ( 4 | OODAugmentation, 5 | SampableAugmentation, 6 | ) 7 | from ...severity import ParameterSeverityMeasurement, SeverityMeasurement 8 | from ....data import Sample 9 | from ..utils import full_image_ood 10 | 11 | 12 | class GaussianNoiseAugmentation(OODAugmentation, SampableAugmentation): 13 | def __init__( 14 | self, 15 | sigma=0.005, 16 | sample_intervals=None, 17 | severity: SeverityMeasurement = None, 18 | keep_ignored=True, 19 | ) -> None: 20 | super().__init__() 21 | self.sigma = sigma 22 | if sample_intervals is None: 23 | self.sample_intervals = [(0.001, 0.01)] 24 | else: 25 | self.sample_intervals = sample_intervals 26 | self.severity_class = ( 27 | ParameterSeverityMeasurement( 28 | "sigma", (self.sample_intervals[0][0], self.sample_intervals[-1][1]) 29 | ) 30 | if severity is None 31 | else severity 32 | ) 33 | self.keep_ignored = keep_ignored 34 | 35 | @property 36 | def sigma(self): 37 | return self._sigma 38 | 39 | @sigma.setter 40 | def sigma(self, value): 41 | self._sigma = value 42 | # zero mean noise, variance is configurable 43 | self.transform = A.GaussNoise( 44 | mean=0, var_limit=self._sigma, per_channel=False, p=1 45 | ) 46 | 47 | def _apply_sampling(self): 48 | return super()._set_attr_to_uniform_samples_from_intervals( 49 | {"sigma": self.sample_intervals} 50 | ) 51 | 52 | def _get_parameter_dict(self): 53 | return {"sigma": self.sigma} 54 | 55 | def _augment(self, sample: Sample) -> Sample: 56 | X = sample["image"] 57 | X = X.numpy().transpose((1, 2, 0)) 58 | img = self.transform(image=X) 59 | sample["image"] = torch.from_numpy(img["image"].transpose(2, 0, 1)) 60 | sample = full_image_ood(sample, self.keep_ignored) 61 | return sample 62 | -------------------------------------------------------------------------------- /froodo/ood/augmentations/xray/motion_blur.py: -------------------------------------------------------------------------------- 1 | import torch 2 | import albumentations as A 3 | from ...augmentations import ( 4 | OODAugmentation, 5 | SampableAugmentation, 6 | ) 7 | from ...severity import ParameterSeverityMeasurement, SeverityMeasurement 8 | from ....data import Sample 9 | from ..utils import full_image_ood 10 | 11 | 12 | class MotionBlurAugmentation(OODAugmentation, SampableAugmentation): 13 | def __init__( 14 | self, 15 | motion=5, 16 | sample_intervals=None, 17 | severity: SeverityMeasurement = None, 18 | keep_ignored=True, 19 | ) -> None: 20 | super().__init__() 21 | self.motion = motion 22 | if sample_intervals is None: 23 | self.sample_intervals = [(5, 20)] 24 | else: 25 | self.sample_intervals = sample_intervals 26 | self.severity_class = ( 27 | ParameterSeverityMeasurement( 28 | "motion", 29 | (0, 1), # uses a normalized range 30 | ) 31 | if severity is None 32 | else severity 33 | ) 34 | self.keep_ignored = keep_ignored 35 | 36 | @property 37 | def motion(self): 38 | return self._motion 39 | 40 | @motion.setter 41 | def motion(self, value): 42 | value = int(value) 43 | if value % 2 == 0: 44 | value = value + 1 45 | assert value > 3 46 | self._motion = value 47 | self.transform = A.MotionBlur( 48 | blur_limit=(value, value), allow_shifted=True, p=1 49 | ) 50 | 51 | def _apply_sampling(self): 52 | return super()._set_attr_to_uniform_samples_from_intervals( 53 | {"motion": self.sample_intervals} 54 | ) 55 | 56 | def _get_parameter_dict(self): 57 | return {"motion": self.normalized_param_range(self.motion)} 58 | 59 | def _augment(self, sample: Sample) -> Sample: 60 | X = sample["image"] 61 | X = X.numpy().transpose((1, 2, 0)) 62 | img = self.transform(image=X) 63 | sample["image"] = torch.from_numpy(img["image"].transpose(2, 0, 1)) 64 | sample = full_image_ood(sample, self.keep_ignored) 65 | return sample 66 | 67 | def normalized_param_range(self, value: int): 68 | return (value - self.sample_intervals[0][0]) / ( 69 | self.sample_intervals[-1][1] - self.sample_intervals[0][0] 70 | ) 71 | -------------------------------------------------------------------------------- /froodo/ood/methods/__init__.py: -------------------------------------------------------------------------------- 1 | from .ood_methods import OODMethod 2 | from .odin import ODIN, SuperOdin, SuperDuperOdin 3 | from .max_output import MaxOutput 4 | from .temperature_scaling import TemperatureScaling 5 | from .energy import EnergyScore 6 | from .react import ReAct 7 | from .custom import * 8 | -------------------------------------------------------------------------------- /froodo/ood/methods/baselines.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from .ood_methods import OODMethod 4 | 5 | 6 | class MaxClassBaseline(OODMethod): 7 | def __init__(self, hyperparams={}) -> None: 8 | super().__init__(hyperparams) 9 | 10 | def calculate_ood_score(self, imgs, net, batch=None): 11 | with torch.no_grad(): 12 | outputs = net(imgs.cuda()) 13 | 14 | outputs = self._post_proc_net_output(outputs) 15 | 16 | scores = torch.softmax(outputs[0].data, dim=1) 17 | m, _ = torch.max(scores, dim=1) 18 | return m.detach().cpu() 19 | -------------------------------------------------------------------------------- /froodo/ood/methods/custom.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/froodo/ood/methods/custom.py -------------------------------------------------------------------------------- /froodo/ood/methods/energy.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from .ood_methods import OODMethod 4 | 5 | 6 | class EnergyBased(OODMethod): 7 | def __init__(self, hyperparams={"temperature": 1}) -> None: 8 | super().__init__(hyperparams) 9 | self.temperature = hyperparams["temperature"] 10 | 11 | def get_params(self, dict=False): 12 | if dict: 13 | return {"temperature": self.temperature} 14 | return f"temp: {self.temperature}" 15 | 16 | def calculate_ood_score(self, imgs, net, batch=None): 17 | with torch.no_grad(): 18 | outputs = net(imgs.cuda()) 19 | outputs = self._post_proc_net_output(outputs) 20 | scores = -self.temperature * torch.logsumexp( 21 | outputs[0] / self.temperature, dim=1 22 | ) 23 | return -scores.detach().cpu() 24 | -------------------------------------------------------------------------------- /froodo/ood/methods/g_odin.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from typing import Optional, Dict, Any 4 | 5 | from .ood_methods import OODMethod 6 | from ...data.samples import Batch 7 | 8 | 9 | class GODIN_Max_of_h(OODMethod): 10 | def __init__( 11 | self, 12 | hyperparams: Dict[str, Any] = ..., 13 | rejection_threshold: Optional[float] = None, 14 | ) -> None: 15 | super().__init__(hyperparams, rejection_threshold) 16 | 17 | def calculate_ood_score( 18 | self, imgs: torch.Tensor, net: torch.nn.Module, batch: Optional[Batch] = None 19 | ): 20 | with torch.no_grad(): 21 | outputs = net(imgs.cuda()) 22 | 23 | outputs = self._post_proc_net_output(outputs) 24 | 25 | m, _ = torch.max(outputs[1].data, dim=1) 26 | return m.detach().cpu() 27 | 28 | 29 | class GODIN_d(OODMethod): 30 | def __init__( 31 | self, 32 | hyperparams: Dict[str, Any] = ..., 33 | rejection_threshold: Optional[float] = None, 34 | ) -> None: 35 | super().__init__(hyperparams, rejection_threshold) 36 | 37 | def calculate_ood_score( 38 | self, imgs: torch.Tensor, net: torch.nn.Module, batch: Optional[Batch] = None 39 | ): 40 | with torch.no_grad(): 41 | outputs = net(imgs.cuda()) 42 | 43 | outputs = self._post_proc_net_output(outputs) 44 | 45 | m, _ = torch.max(outputs[2].data, dim=1) 46 | return m.detach().cpu() 47 | -------------------------------------------------------------------------------- /froodo/ood/methods/max_output.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from typing import Optional 4 | 5 | from .ood_methods import OODMethod 6 | from ...data.samples import Batch 7 | 8 | 9 | class MaxOutput(OODMethod): 10 | def __init__( 11 | self, 12 | rejection_threshold: Optional[float] = None, 13 | return_max_logit: bool = False, 14 | ) -> None: 15 | super().__init__({}, rejection_threshold) 16 | self.return_max_logit = return_max_logit 17 | 18 | def display_name(self) -> str: 19 | return ( 20 | f"{super().display_name()}_{'logits' if self.return_max_logit else 'soft'}" 21 | ) 22 | 23 | def calculate_ood_score( 24 | self, imgs: torch.Tensor, net: torch.nn.Module, batch: Optional[Batch] = None 25 | ): 26 | with torch.no_grad(): 27 | outputs = net(imgs.cuda()) 28 | 29 | outputs = self._post_proc_net_output(outputs) 30 | 31 | if self.return_max_logit: 32 | m, _ = torch.max(outputs[0].data, dim=1) 33 | else: 34 | scores = torch.softmax( 35 | outputs[0], 36 | dim=1, 37 | ) 38 | m, _ = torch.max(scores.data, dim=1) 39 | 40 | return m.detach().cpu() 41 | -------------------------------------------------------------------------------- /froodo/ood/methods/mc_dropout.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Variable 3 | from torch import nn, optim 4 | from torch.nn import functional as F 5 | 6 | from .ood_methods import OODMethod 7 | 8 | 9 | class MCDropout(OODMethod): 10 | def __init__(self, hyperparams={"dropout": 0.5, "samples": 50}) -> None: 11 | super().__init__(hyperparams) 12 | self.dropout = hyperparams["dropout"] 13 | self.samples = hyperparams["samples"] 14 | 15 | def get_params(self, dict=False): 16 | if dict: 17 | return {"dropout rate": self.dropout, "number of samples": self.samples} 18 | return f"dropout rate: {self.dropout}, number of samples: {self.samples}" 19 | 20 | def modify_net(self, net): 21 | feats_list = list(net.children()) 22 | if True: # Dropout at the end for inception_resnet_v2 23 | feats_list.insert(-1, nn.Dropout(p=self.dropout, inplace=True)) 24 | net = nn.Sequential(*feats_list) 25 | else: # Dropout after each Convolusion layer 26 | new_feats_list = [] 27 | for feat in feats_list: 28 | new_feats_list.append(feat) 29 | if isinstance(feat, nn.Conv2d): 30 | new_feats_list.append(nn.Dropout(p=self.dropout, inplace=True)) 31 | net = nn.Sequential(*new_feats_list) 32 | 33 | return net 34 | 35 | def _enable_dropout(self, net): 36 | for m in net.modules(): 37 | if m.__class__.__name__.startswith("Dropout"): 38 | m.train() 39 | 40 | def _calculate_mean_of_samples(self, X, net, num_samples): 41 | if True: # Special case for inception_resnet_v2 42 | net_before_dropout = nn.Sequential(*list(net.children())[:-2]) 43 | net_after_dropout = nn.Sequential(*list(net.children())[-2:]) 44 | with torch.no_grad(): 45 | p = net_before_dropout(X.cuda()) 46 | preds = [] 47 | for _ in range(num_samples): 48 | with torch.no_grad(): 49 | res = net_after_dropout(p) 50 | preds.append(res) 51 | else: # Otherwise 52 | preds = [] 53 | for _ in range(num_samples): 54 | with torch.no_grad(): 55 | res = net(p) 56 | preds.append(res) 57 | return torch.stack(preds).mean(axis=0) 58 | 59 | def calculate_ood_score(self, imgs, net, batch=None): 60 | net = self.modify_net(net) 61 | self._enable_dropout(net) 62 | 63 | outputs = self._calculate_mean_of_samples(imgs, net, self.samples) 64 | outputs = self._post_proc_net_output(outputs) 65 | 66 | scores = torch.softmax(outputs[0].data, dim=1) 67 | m, _ = torch.max(scores, dim=1) 68 | return m.detach().cpu() 69 | -------------------------------------------------------------------------------- /froodo/ood/methods/odin.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Variable 3 | 4 | from .ood_methods import OODMethod 5 | 6 | 7 | class ODIN(OODMethod): 8 | def __init__(self, hyperparams={"temperature": 2, "noise": 0.004}) -> None: 9 | super().__init__() 10 | self.temperature = hyperparams.get("temperature", 2) 11 | self.noise = hyperparams.get("noise", 0.004) 12 | self.criterion = torch.nn.CrossEntropyLoss() 13 | 14 | def display_name(self) -> str: 15 | return f"{super().display_name()} {self.get_params()}" 16 | 17 | def get_params(self, dict=False): 18 | if dict: 19 | return {"temperature": self.temperature, "noise": self.noise} 20 | return f"temp: {self.temperature}, noise: {self.noise}" 21 | 22 | def _temp_and_pertubate(self, imgs, net): 23 | inputs = Variable(imgs.cuda(), requires_grad=True) 24 | outputs = net(inputs) 25 | outputs = self._post_proc_net_output(outputs) 26 | 27 | max = torch.max(outputs[0].data, axis=1)[0] 28 | scores = torch.softmax(outputs[0].data - max.unsqueeze(1), dim=1) 29 | 30 | labels = torch.argmax(scores, axis=1) 31 | loss = self.criterion(outputs[0] / self.temperature, labels) 32 | loss.backward() 33 | 34 | gradient = torch.ge(inputs.grad.data, 0) 35 | gradient = (gradient.float() - 0.5) * 2 36 | 37 | tempInputs = torch.add(inputs.data, gradient, alpha=-self.noise) 38 | outputs = net(tempInputs) 39 | outputs = self._post_proc_net_output(outputs) 40 | outputs = outputs[0] / self.temperature 41 | return outputs 42 | 43 | def calculate_ood_score(self, imgs, net, batch=None): 44 | outputs = self._temp_and_pertubate(imgs, net) 45 | outputs = outputs - torch.max(outputs, axis=1)[0].unsqueeze(1) 46 | scores = torch.softmax(outputs.data, dim=1) 47 | m, _ = torch.max(scores, axis=1) 48 | return m.detach().cpu() 49 | -------------------------------------------------------------------------------- /froodo/ood/methods/react.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.utils.data import DataLoader 3 | import tqdm 4 | import numpy as np 5 | 6 | import pickle 7 | 8 | from .ood_methods import OODMethod 9 | 10 | 11 | class ReAct(OODMethod): 12 | def __init__(self, hyperparams={"quantile": 0.95}) -> None: 13 | super().__init__(hyperparams) 14 | self.name = "ReAct" 15 | with open("react.pkl", "rb") as f: 16 | quantiles = pickle.load(f) 17 | self.q = round(hyperparams["quantile"], 2) 18 | self.tensor = quantiles[self.q].cuda() 19 | 20 | def generate_quantiles( 21 | self, dataset, net, range_vals=np.arange(0.7, 1, 0.01), name="react" 22 | ): 23 | loader = DataLoader(dataset, batch_size=16) 24 | data_iter = tqdm.tqdm(loader) 25 | data_iter.set_description(f"Loading") 26 | activations = [] 27 | for i, (images, masks) in enumerate(data_iter): 28 | _, *act = net(images.cuda()) 29 | activations.append( 30 | act[-1].permute(0, 2, 3, 1).reshape(-1, 16).detach().cpu()[::20] 31 | ) 32 | 33 | out = torch.cat(activations, axis=0) 34 | 35 | quantiles = {} 36 | 37 | for q in range_vals: 38 | q = round(q, 2) 39 | quantiles[q] = torch.quantile(out, q, 0) 40 | 41 | with open(f"{name}.pkl", "wb") as f: 42 | pickle.dump(quantiles, f) 43 | 44 | return quantiles 45 | -------------------------------------------------------------------------------- /froodo/ood/methods/temp.py: -------------------------------------------------------------------------------- 1 | import torch 2 | from torch.autograd import Variable 3 | from torch import optim, nn 4 | 5 | from .ood_methods import OODMethod 6 | 7 | 8 | class TemperatureScaling(OODMethod): 9 | def __init__(self, hyperparams={"temperature": 2.0}) -> None: 10 | super().__init__() 11 | self.temperature = nn.Parameter(torch.tensor(hyperparams["temperature"])) 12 | self.criterion = torch.nn.CrossEntropyLoss().cuda() 13 | 14 | def display_name(self) -> str: 15 | return f"{super().display_name()} {self.get_params()}" 16 | 17 | def get_params(self, dict=False): 18 | if dict: 19 | return {"temperature": self.temperature.item()} 20 | return f"temp: {self.temperature.item()}" 21 | 22 | def _temperature_scale(self, logits): 23 | return logits / self.temperature.cuda() 24 | 25 | def _temp(self, imgs, net): 26 | optimizer = optim.Adam([self.temperature], lr=1e-3) 27 | lr_scheduler = optim.lr_scheduler.ReduceLROnPlateau( 28 | optimizer, patience=2, factor=0.1 29 | ) 30 | 31 | optimizer.zero_grad() 32 | outputs = net(imgs.cuda()) 33 | outputs = self._post_proc_net_output(outputs) 34 | 35 | max = torch.max(outputs[0].data, axis=1)[0] 36 | scores = torch.softmax(outputs[0].data - max.unsqueeze(1), dim=1) 37 | labels = torch.argmax(scores, axis=1) 38 | 39 | loss = self.criterion(self._temperature_scale(outputs[0]), labels) 40 | loss.backward() 41 | if loss.item() > 1e-5: 42 | optimizer.step() 43 | lr_scheduler.step(loss) 44 | 45 | outputs = outputs[0] / self.temperature.cuda() 46 | return outputs 47 | 48 | def calculate_ood_score(self, imgs, net, batch=None): 49 | outputs = self._temp(imgs, net) 50 | outputs = outputs - torch.max(outputs, axis=1)[0].unsqueeze(1) 51 | scores = torch.softmax(outputs.data, dim=1) 52 | m, _ = torch.max(scores, axis=1) 53 | return m.detach().cpu() 54 | -------------------------------------------------------------------------------- /froodo/ood/methods/utils.py: -------------------------------------------------------------------------------- 1 | from typing import Type, List, Dict 2 | -------------------------------------------------------------------------------- /froodo/ood/metrics/__init__.py: -------------------------------------------------------------------------------- 1 | from .metrics import infer_container, MetricGroup, Metric 2 | from .auroc import AUROCMetric, OODAuRoC 3 | -------------------------------------------------------------------------------- /froodo/ood/metrics/metrics.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from ...data.container import Container 4 | 5 | 6 | class MetricGroup: 7 | def __init__(self) -> None: 8 | pass 9 | 10 | def requires(self) -> List[Container]: 11 | raise NotImplementedError("Please Implement this method") 12 | 13 | def __call__(self, data_container: List[Container], experiment_metadata: dict): 14 | raise NotImplementedError("Please Implement this method") 15 | 16 | def present(self, **kwargs): 17 | pass 18 | 19 | 20 | class Metric: 21 | def __init__(self) -> None: 22 | pass 23 | 24 | def __call__(self, data_container): 25 | raise NotImplementedError("Please Implement this method") 26 | 27 | def present(self, **kwargs): 28 | pass 29 | 30 | 31 | def infer_container(metrics: List[MetricGroup]): 32 | container_set = set() 33 | for m in metrics: 34 | for c in m.requires(): 35 | container_set.add(c) 36 | container_list = [c() for c in container_set] 37 | return container_list 38 | -------------------------------------------------------------------------------- /froodo/ood/severity/__init__.py: -------------------------------------------------------------------------------- 1 | from .severity import * 2 | -------------------------------------------------------------------------------- /froodo/ood/severity/severity.py: -------------------------------------------------------------------------------- 1 | import torch 2 | 3 | from .utils import * 4 | 5 | 6 | class SeverityMeasurement: 7 | def __init__(self, binning_fn, name): 8 | self.binning_fn = binning_fn 9 | self.name = name 10 | 11 | def calculate_measurement(self, image, mask, params): 12 | raise NotImplementedError("Please Implement this method") 13 | 14 | def get_bin(self, num_bins=None, ignore_true_bin=False): 15 | return self.binning_fn(self.measurement, num_bins, ignore_true_bin) 16 | 17 | def __repr__(self) -> str: 18 | return f"{self.name} [{self.range[0]}-{self.range[1]}]: {self.measurement}" 19 | 20 | 21 | class PixelPercentageSeverityMeasurement(SeverityMeasurement): 22 | def __init__(self): 23 | super().__init__( 24 | binning_fn((0, 1)), 25 | "PixelPercentage", 26 | ) 27 | self.range = (0, 1) 28 | 29 | def calculate_measurement(self, image, mask, params): 30 | self.measurement = ( 31 | torch.sum(mask == 0) / (mask.shape[-1] * mask.shape[-2]) 32 | ).item() 33 | return self.measurement 34 | 35 | 36 | class ParameterSeverityMeasurement(SeverityMeasurement): 37 | def __init__(self, param, param_range, custom_binning_fn=None): 38 | super().__init__( 39 | binning_fn(param_range) if custom_binning_fn == None else custom_binning_fn, 40 | f"Parameter {param}", 41 | ) 42 | self.param = param 43 | self.range = param_range 44 | 45 | def calculate_measurement(self, image, mask, params): 46 | self.measurement = params[self.param] 47 | return self.measurement 48 | -------------------------------------------------------------------------------- /froodo/ood/severity/utils.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import functools 4 | 5 | 6 | def binning_fn(param_range): 7 | return functools.partial(whole_binning, range=param_range) 8 | 9 | 10 | def whole_binning(value, num_bins=None, ignore_true_bin=False, range=None, default=0): 11 | return get_standard_bin( 12 | value, create_bins(range, num_bins), ignore_true_bin, default 13 | ) 14 | 15 | 16 | def create_bins(range, num_bins): 17 | if num_bins == None: 18 | return None 19 | min_value, max_value = range 20 | return np.linspace(min_value + max_value / num_bins, max_value, num_bins) 21 | 22 | 23 | def get_standard_bin(value, bins, ignore_true_bin=False, default=0): 24 | if value == default: 25 | return -1 26 | 27 | # if bins are set to None this means the true bin is not needed and only the information whether the data is IN or OOD is reqiered 28 | if ignore_true_bin: 29 | return True 30 | 31 | return np.digitize([value], bins, right=True)[0] 32 | -------------------------------------------------------------------------------- /froodo/ood/strategies/__init__.py: -------------------------------------------------------------------------------- 1 | from .strategy import OODStrategy 2 | from .augmentation import AugmentationStrategy 3 | from .ood_dataset import OODDatasetsStrategy 4 | -------------------------------------------------------------------------------- /froodo/ood/strategies/augmentation.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import DataLoader 2 | 3 | from ..augmentations import Augmentation 4 | from ...data.datasets.interfaces import AugmentationDataset 5 | from ...data.datasets.interfaces import SampleDataset 6 | from .strategy import OODStrategy 7 | 8 | 9 | class AugmentationStrategy(OODStrategy): 10 | def __init__( 11 | self, dataset: AugmentationDataset, augmentation: Augmentation, seed=None 12 | ) -> None: 13 | assert isinstance(dataset, SampleDataset) 14 | assert isinstance(augmentation, Augmentation) 15 | self.dataset = AugmentationDataset(dataset, augmentation, seed) 16 | -------------------------------------------------------------------------------- /froodo/ood/strategies/class_leftout.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from ...data.datasets.interfaces import SampleDataset 4 | from .strategy import OODStrategy 5 | 6 | 7 | class ClassLeftoutStrategy(OODStrategy): 8 | def __init__(self, dataset: SampleDataset, leftout_classes: List[int]) -> None: 9 | super().__init__() 10 | self.leftout_classes = leftout_classes 11 | self.dataset = dataset 12 | -------------------------------------------------------------------------------- /froodo/ood/strategies/ood_dataset.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | 3 | from .strategy import OODStrategy 4 | from ...data.datasets import SampleDataset 5 | from ...data.datasets.interfaces import OODDataset, ConcatSampleDataset 6 | 7 | 8 | class OODDatasetsStrategy(OODStrategy): 9 | def __init__( 10 | self, 11 | in_dataset_list: List[SampleDataset], 12 | ood_dataset_list: List[SampleDataset], 13 | ) -> None: 14 | super().__init__() 15 | self.dataset = ConcatSampleDataset( 16 | in_dataset_list 17 | + [ 18 | OODDataset(d, d.find_base_name(default=i)) 19 | for i, d in enumerate(ood_dataset_list) 20 | ] 21 | ) 22 | -------------------------------------------------------------------------------- /froodo/ood/strategies/strategy.py: -------------------------------------------------------------------------------- 1 | from torch.utils.data import DataLoader 2 | 3 | from ...data.utils import sample_collate 4 | 5 | 6 | class OODStrategy: 7 | def get_dataloader(self, **dataloader_kwargs): 8 | return DataLoader(self.dataset, collate_fn=sample_collate, **dataloader_kwargs) 9 | -------------------------------------------------------------------------------- /froodo/quickstart/__init__.py: -------------------------------------------------------------------------------- 1 | from ..data import * 2 | from ..ood import * 3 | from ..experiment.components import * 4 | from ..data.datasets.examples.pathology.bcss import ( 5 | BCSS_Adapted_Cropped_Resized_Datasets, 6 | ) 7 | from ..models.segmentation import SegmentationModel 8 | -------------------------------------------------------------------------------- /froodo/utils/__init__.py: -------------------------------------------------------------------------------- 1 | from .helper import * 2 | -------------------------------------------------------------------------------- /froodo/utils/helper.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | 3 | import random 4 | 5 | 6 | def dict_default(): 7 | return None 8 | 9 | 10 | def sample_from_intervals(intervals): 11 | """ 12 | sample one value from one of the given intervals 13 | :param intervals: 14 | :return: a single value 15 | """ 16 | weights = np.array([i[1] - i[0] for i in intervals]) 17 | interval_index = np.random.choice( 18 | list(range(len(intervals))), p=weights / weights.sum() 19 | ) 20 | return random.uniform(intervals[interval_index][0], intervals[interval_index][1]) 21 | -------------------------------------------------------------------------------- /imgs/FrOoDo.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/imgs/FrOoDo.PNG -------------------------------------------------------------------------------- /imgs/FrOoDo_Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/imgs/FrOoDo_Logo.png -------------------------------------------------------------------------------- /imgs/augmentations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/imgs/augmentations.png -------------------------------------------------------------------------------- /imgs/metric.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/imgs/metric.png -------------------------------------------------------------------------------- /imgs/metric2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/imgs/metric2.png -------------------------------------------------------------------------------- /imgs/samples.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MECLabTUDA/FrOoDo/5bf94767ef14a59316fa3f4021191a20351a3a26/imgs/samples.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | torch 2 | numpy 3 | pandas 4 | tqdm 5 | scipy 6 | tabulate 7 | scikit-learn 8 | matplotlib 9 | zarr 10 | tifffile 11 | medmnist 12 | cloudpickle 13 | opencv-python 14 | torchio 15 | torchvision 16 | 17 | scikit-learn 18 | albumentations 19 | imageio --------------------------------------------------------------------------------