brainles-preprocessing 0.3.6__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/PKG-INFO +13 -8
  2. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/README.md +7 -3
  3. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/brain_extraction/brain_extractor.py +6 -6
  4. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/constants.py +3 -2
  5. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/defacing/defacer.py +6 -6
  6. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/defacing/quickshear/quickshear.py +7 -4
  7. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/modality.py +88 -19
  8. brainles_preprocessing-0.5.0/brainles_preprocessing/n4_bias_correction/__init__.py +2 -0
  9. brainles_preprocessing-0.5.0/brainles_preprocessing/n4_bias_correction/n4_bias_corrector.py +13 -0
  10. brainles_preprocessing-0.5.0/brainles_preprocessing/n4_bias_correction/sitk/sitk_n4_bias_corrector.py +82 -0
  11. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/preprocessor.py +113 -16
  12. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/ANTs/ANTs.py +102 -28
  13. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/elastix/elastix.py +15 -0
  14. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/greedy/greedy.py +16 -2
  15. brainles_preprocessing-0.5.0/brainles_preprocessing/registration/niftyreg/__init__.py +0 -0
  16. brainles_preprocessing-0.5.0/brainles_preprocessing/registration/niftyreg/niftyreg.py +266 -0
  17. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/transform.sh +4 -3
  18. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/registrator.py +26 -0
  19. brainles_preprocessing-0.5.0/brainles_preprocessing/transform.py +115 -0
  20. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/pyproject.toml +7 -5
  21. brainles_preprocessing-0.3.6/brainles_preprocessing/registration/niftyreg/niftyreg.py +0 -135
  22. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/LICENSE +0 -0
  23. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/__init__.py +0 -0
  24. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/brain_extraction/__init__.py +0 -0
  25. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/brats/__init__.py +0 -0
  26. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/brats/t1_centric.py +0 -0
  27. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/brats/t1c_centric.py +0 -0
  28. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/cli.py +0 -0
  29. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/defacing/__init__.py +0 -0
  30. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/defacing/quickshear/__init__.py +0 -0
  31. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/defacing/quickshear/nipy_quickshear.py +0 -0
  32. {brainles_preprocessing-0.3.6/brainles_preprocessing/registration/ANTs → brainles_preprocessing-0.5.0/brainles_preprocessing/n4_bias_correction/sitk}/__init__.py +0 -0
  33. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/normalization/__init__.py +0 -0
  34. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/normalization/normalizer_base.py +0 -0
  35. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/normalization/percentile_normalizer.py +0 -0
  36. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/normalization/windowing_normalizer.py +0 -0
  37. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/ANTs/TODO_ANTs_parameters.py +0 -0
  38. {brainles_preprocessing-0.3.6/brainles_preprocessing/registration/elastix → brainles_preprocessing-0.5.0/brainles_preprocessing/registration/ANTs}/__init__.py +0 -0
  39. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/__init__.py +0 -0
  40. {brainles_preprocessing-0.3.6/brainles_preprocessing/registration/greedy → brainles_preprocessing-0.5.0/brainles_preprocessing/registration/elastix}/__init__.py +0 -0
  41. {brainles_preprocessing-0.3.6/brainles_preprocessing/registration/niftyreg → brainles_preprocessing-0.5.0/brainles_preprocessing/registration/greedy}/__init__.py +0 -0
  42. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/groupwise_niftyreg_params.sh +0 -0
  43. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/groupwise_niftyreg_run.sh +0 -0
  44. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_aladin +0 -0
  45. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_average +0 -0
  46. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_f3d +0 -0
  47. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_jacobian +0 -0
  48. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_measure +0 -0
  49. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_resample +0 -0
  50. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_tools +0 -0
  51. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/bin/reg_transform +0 -0
  52. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/AffineDeformationFieldKernel.h +0 -0
  53. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/AladinContent.h +0 -0
  54. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/BlockMatchingKernel.h +0 -0
  55. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUAffineDeformationFieldKernel.h +0 -0
  56. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUBlockMatchingKernel.h +0 -0
  57. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUConvolutionKernel.h +0 -0
  58. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUKernelFactory.h +0 -0
  59. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUOptimiseKernel.h +0 -0
  60. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/CPUResampleImageKernel.h +0 -0
  61. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/ConvolutionKernel.h +0 -0
  62. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/Kernel.h +0 -0
  63. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/KernelFactory.h +0 -0
  64. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/OptimiseKernel.h +0 -0
  65. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/Platform.h +0 -0
  66. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/ResampleImageKernel.h +0 -0
  67. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_ReadWriteImage.h +0 -0
  68. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_ReadWriteMatrix.h +0 -0
  69. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_aladin.cpp +0 -0
  70. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_aladin.h +0 -0
  71. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_aladin_sym.cpp +0 -0
  72. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_aladin_sym.h +0 -0
  73. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_base.h +0 -0
  74. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_blockMatching.h +0 -0
  75. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_dti.h +0 -0
  76. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_f3d.h +0 -0
  77. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_f3d2.h +0 -0
  78. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_f3d_sym.h +0 -0
  79. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_femTrans.h +0 -0
  80. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_globalTrans.h +0 -0
  81. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_kld.h +0 -0
  82. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_lncc.h +0 -0
  83. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_localTrans.h +0 -0
  84. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_localTrans_jac.h +0 -0
  85. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_localTrans_regul.h +0 -0
  86. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_macros.h +0 -0
  87. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_maths.h +0 -0
  88. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_maths_eigen.h +0 -0
  89. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_measure.h +0 -0
  90. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_mind.h +0 -0
  91. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_nmi.h +0 -0
  92. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_optimiser.cpp +0 -0
  93. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_optimiser.h +0 -0
  94. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_resampling.h +0 -0
  95. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_splineBasis.h +0 -0
  96. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_ssd.h +0 -0
  97. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_stringFormat.h +0 -0
  98. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/_reg_tools.h +0 -0
  99. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/nifti1.h +0 -0
  100. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/nifti1_io.h +0 -0
  101. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/png.h +0 -0
  102. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pngconf.h +0 -0
  103. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pngdebug.h +0 -0
  104. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pnginfo.h +0 -0
  105. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pnglibconf.h +0 -0
  106. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pngpriv.h +0 -0
  107. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/pngstruct.h +0 -0
  108. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/readpng.h +0 -0
  109. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/reg_png.h +0 -0
  110. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/zlib.h +0 -0
  111. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/znzlib.h +0 -0
  112. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/niftyreg_1.5.68/include/zutil.h +0 -0
  113. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/reg_aladin +0 -0
  114. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/reg_resample +0 -0
  115. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/registration/niftyreg/niftyreg_scripts/rigid_reg.sh +0 -0
  116. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/utils/__init__.py +0 -0
  117. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/utils/generic.py +0 -0
  118. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/utils/logging_utils.py +0 -0
  119. {brainles_preprocessing-0.3.6 → brainles_preprocessing-0.5.0}/brainles_preprocessing/utils/zenodo.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: brainles_preprocessing
3
- Version: 0.3.6
3
+ Version: 0.5.0
4
4
  Summary: Tool for preprocessing tasks in biomedical imaging, with a focus on (but not limited to) multi-modal brain MRI
5
5
  License: Apache-2.0
6
6
  Keywords: brain tumor,glioma,BraTS,skullstripping,brain extraction
@@ -19,17 +19,18 @@ Classifier: Programming Language :: Python :: 3.13
19
19
  Provides-Extra: all
20
20
  Provides-Extra: itk-elastix
21
21
  Provides-Extra: picsl-greedy
22
- Requires-Dist: antspyx (>=0.4.2,<0.5.0)
23
- Requires-Dist: auxiliary (>=0.0.42)
22
+ Requires-Dist: antspyx (>=0.5.4,<1.0.0)
23
+ Requires-Dist: auxiliary (>=0.3.1)
24
24
  Requires-Dist: black (>=22.1.0,<23.0.0)
25
- Requires-Dist: brainles_hd_bet (>=0.0.10)
25
+ Requires-Dist: brainles_hd_bet (>=0.0.10,<1.0.0)
26
26
  Requires-Dist: itk-elastix (>=0.20.0,<0.21.0) ; extra == "all" or extra == "itk-elastix"
27
27
  Requires-Dist: nibabel (>=3.2.1)
28
28
  Requires-Dist: numpy (>=1.23.0,<2.0.0)
29
- Requires-Dist: path (>=16.10.0,<17.0.0)
30
29
  Requires-Dist: pathlib (>=1.0.1,<2.0.0)
31
30
  Requires-Dist: picsl_greedy (>=0.0.6,<0.0.7) ; extra == "all" or extra == "picsl-greedy"
32
31
  Requires-Dist: rich (>=13.6.0,<14.0.0)
32
+ Requires-Dist: scipy (<1.14)
33
+ Requires-Dist: simpleitk (>=2.2.1)
33
34
  Requires-Dist: tqdm (>=4.64.1,<5.0.0)
34
35
  Requires-Dist: ttictoc (>=0.5.6,<0.6.0)
35
36
  Requires-Dist: typer (>=0.15.0,<0.16.0)
@@ -48,9 +49,10 @@ Description-Content-Type: text/markdown
48
49
 
49
50
  `BrainLes preprocessing` is a comprehensive tool for preprocessing tasks in biomedical imaging, with a focus on (but not limited to) multi-modal brain MRI. It can be used to build modular preprocessing pipelines:
50
51
 
51
- This includes **normalization**, **co-registration**, **atlas registration** and **skulstripping / brain extraction**.
52
+ This includes **normalization**, **co-registration**, **atlas registration**, **skullstripping / brain extraction**, **N4 Bias correction** and **defacing**.
53
+ We provide means to transform images and segmentations in both directions between native and atlas space.
52
54
 
53
- BrainLes is written `backend-agnostic` meaning it allows to swap the registration, brain extraction tools and defacing tools.
55
+ BrainLes is written modular and `backend-agnostic` meaning it allows to skip or swap registration, brain extraction, N4 bias correction and defacing tools.
54
56
 
55
57
  <!-- TODO include image here -->
56
58
 
@@ -124,7 +126,7 @@ moving_modalities = [
124
126
  )
125
127
  ]
126
128
 
127
- # instantiate and run the preprocessor using defaults for registration/ brain extraction/ defacing backends
129
+ # instantiate and run the preprocessor using defaults for backends (registration, brain extraction, bias correction, defacing)
128
130
  preprocessor = Preprocessor(
129
131
  center_modality=center,
130
132
  moving_modalities=moving_modalities,
@@ -165,6 +167,9 @@ We currently provide support for [ANTs](https://github.com/ANTsX/ANTs) (default)
165
167
  We provide the SRI-24 atlas from this [publication](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2915788/).
166
168
  However, custom atlases in NIfTI format are supported.
167
169
 
170
+ ### N4 Bias correction
171
+ We currently provide support for N4 Bias correction based on [SimpleITK](https://simpleitk.org/)
172
+
168
173
  ### Brain extraction
169
174
  We currently provide support for [HD-BET](https://github.com/MIC-DKFZ/HD-BET).
170
175
 
@@ -10,9 +10,10 @@
10
10
 
11
11
  `BrainLes preprocessing` is a comprehensive tool for preprocessing tasks in biomedical imaging, with a focus on (but not limited to) multi-modal brain MRI. It can be used to build modular preprocessing pipelines:
12
12
 
13
- This includes **normalization**, **co-registration**, **atlas registration** and **skulstripping / brain extraction**.
13
+ This includes **normalization**, **co-registration**, **atlas registration**, **skullstripping / brain extraction**, **N4 Bias correction** and **defacing**.
14
+ We provide means to transform images and segmentations in both directions between native and atlas space.
14
15
 
15
- BrainLes is written `backend-agnostic` meaning it allows to swap the registration, brain extraction tools and defacing tools.
16
+ BrainLes is written modular and `backend-agnostic` meaning it allows to skip or swap registration, brain extraction, N4 bias correction and defacing tools.
16
17
 
17
18
  <!-- TODO include image here -->
18
19
 
@@ -86,7 +87,7 @@ moving_modalities = [
86
87
  )
87
88
  ]
88
89
 
89
- # instantiate and run the preprocessor using defaults for registration/ brain extraction/ defacing backends
90
+ # instantiate and run the preprocessor using defaults for backends (registration, brain extraction, bias correction, defacing)
90
91
  preprocessor = Preprocessor(
91
92
  center_modality=center,
92
93
  moving_modalities=moving_modalities,
@@ -127,6 +128,9 @@ We currently provide support for [ANTs](https://github.com/ANTsX/ANTs) (default)
127
128
  We provide the SRI-24 atlas from this [publication](https://www.ncbi.nlm.nih.gov/pmc/articles/PMC2915788/).
128
129
  However, custom atlases in NIfTI format are supported.
129
130
 
131
+ ### N4 Bias correction
132
+ We currently provide support for N4 Bias correction based on [SimpleITK](https://simpleitk.org/)
133
+
130
134
  ### Brain extraction
131
135
  We currently provide support for [HD-BET](https://github.com/MIC-DKFZ/HD-BET).
132
136
 
@@ -5,7 +5,7 @@ from pathlib import Path
5
5
  from typing import Optional, Union
6
6
  from enum import Enum
7
7
 
8
- from auxiliary.nifti.io import read_nifti, write_nifti
8
+ from auxiliary.io import read_image, write_image
9
9
  from brainles_hd_bet import run_hd_bet
10
10
 
11
11
 
@@ -55,8 +55,8 @@ class BrainExtractor:
55
55
 
56
56
  try:
57
57
  # Read data
58
- input_data = read_nifti(str(input_image_path))
59
- mask_data = read_nifti(str(mask_path))
58
+ input_data = read_image(str(input_image_path))
59
+ mask_data = read_image(str(mask_path))
60
60
  except FileNotFoundError as e:
61
61
  raise FileNotFoundError(f"File not found: {e.filename}") from e
62
62
  except Exception as e:
@@ -70,10 +70,10 @@ class BrainExtractor:
70
70
  masked_data = input_data * mask_data
71
71
 
72
72
  try:
73
- write_nifti(
73
+ write_image(
74
74
  input_array=masked_data,
75
- output_nifti_path=str(bet_image_path),
76
- reference_nifti_path=str(input_image_path),
75
+ output_path=str(bet_image_path),
76
+ reference_path=str(input_image_path),
77
77
  create_parent_directory=True,
78
78
  )
79
79
  except Exception as e:
@@ -6,8 +6,9 @@ class PreprocessorSteps(IntEnum):
6
6
  COREGISTERED = 1
7
7
  ATLAS_REGISTERED = 2
8
8
  ATLAS_CORRECTED = 3
9
- BET = 4
10
- DEFACED = 5
9
+ N4_BIAS_CORRECTED = 4
10
+ BET = 5
11
+ DEFACED = 6
11
12
 
12
13
 
13
14
  class Atlas(str, Enum):
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
2
2
  from pathlib import Path
3
3
  from typing import Union
4
4
 
5
- from auxiliary.nifti.io import read_nifti, write_nifti
5
+ from auxiliary.io import read_image, write_image
6
6
 
7
7
 
8
8
  class Defacer(ABC):
@@ -52,8 +52,8 @@ class Defacer(ABC):
52
52
 
53
53
  try:
54
54
  # Read data
55
- input_data = read_nifti(str(input_image_path))
56
- mask_data = read_nifti(str(mask_path))
55
+ input_data = read_image(str(input_image_path))
56
+ mask_data = read_image(str(mask_path))
57
57
  except Exception as e:
58
58
  raise RuntimeError(
59
59
  f"An error occurred while reading input files: {e}"
@@ -67,9 +67,9 @@ class Defacer(ABC):
67
67
  masked_data = input_data * mask_data
68
68
 
69
69
  # Save the defaced image
70
- write_nifti(
70
+ write_image(
71
71
  input_array=masked_data,
72
- output_nifti_path=str(defaced_image_path),
73
- reference_nifti_path=str(input_image_path),
72
+ output_path=str(defaced_image_path),
73
+ reference_path=str(input_image_path),
74
74
  create_parent_directory=True,
75
75
  )
@@ -2,10 +2,10 @@ from pathlib import Path
2
2
  from typing import Union
3
3
 
4
4
  import nibabel as nib
5
+ from auxiliary.io import read_image, write_image
5
6
 
6
7
  from brainles_preprocessing.defacing.defacer import Defacer
7
8
  from brainles_preprocessing.defacing.quickshear.nipy_quickshear import run_quickshear
8
- from auxiliary.nifti.io import write_nifti
9
9
 
10
10
 
11
11
  class QuickshearDefacer(Defacer):
@@ -56,8 +56,11 @@ class QuickshearDefacer(Defacer):
56
56
 
57
57
  bet_img = nib.load(str(input_image_path))
58
58
  mask = run_quickshear(bet_img=bet_img, buffer=self.buffer)
59
- write_nifti(
59
+
60
+ # transpose to match simpletik order
61
+ mask = mask.transpose(2, 1, 0)
62
+ write_image(
60
63
  input_array=mask,
61
- output_nifti_path=str(mask_image_path),
62
- reference_nifti_path=str(input_image_path),
64
+ output_path=str(mask_image_path),
65
+ reference_path=str(input_image_path),
63
66
  )
@@ -2,13 +2,18 @@ import logging
2
2
  import shutil
3
3
  import warnings
4
4
  from pathlib import Path
5
- from typing import Optional, Union
5
+ from typing import Dict, Optional, Union
6
+
7
+ from auxiliary.io import read_image, write_image
6
8
 
7
- from auxiliary.nifti.io import read_nifti, write_nifti
8
9
  from brainles_preprocessing.brain_extraction.brain_extractor import BrainExtractor
9
10
  from brainles_preprocessing.constants import PreprocessorSteps
10
11
  from brainles_preprocessing.defacing import Defacer, QuickshearDefacer
11
12
  from brainles_preprocessing.normalization.normalizer_base import Normalizer
13
+ from brainles_preprocessing.registration import ( # TODO: this will throw warnings if ANTs or NiftyReg are not installed, not ideal
14
+ ANTsRegistrator,
15
+ NiftyRegRegistrator,
16
+ )
12
17
  from brainles_preprocessing.registration.registrator import Registrator
13
18
 
14
19
  logger = logging.getLogger(__name__)
@@ -29,6 +34,7 @@ class Modality:
29
34
  normalized_skull_output_path (str or Path, optional): Path to save the normalized modality data with skull. Requires a normalizer.
30
35
  normalized_defaced_output_path (str or Path, optional): Path to save the normalized defaced modality data. Requires a normalizer.
31
36
  atlas_correction (bool, optional): Indicates whether atlas correction should be performed.
37
+ n4_bias_correction (bool, optional): Indicates whether N4 bias correction should be performed.
32
38
 
33
39
  Attributes:
34
40
  modality_name (str): Name of the modality.
@@ -42,6 +48,8 @@ class Modality:
42
48
  normalized_defaced_output_path (str or Path, optional): Path to save the normalized defaced modality data. Requires a normalizer.
43
49
  bet (bool): Indicates whether brain extraction is enabled.
44
50
  atlas_correction (bool): Indicates whether atlas correction should be performed.
51
+ n4_bias_correction (bool): Indicates whether N4 bias correction should be performed.
52
+ coregistration_transform_path (str or None): Path to the coregistration transformation matrix, will be set after coregistration.
45
53
 
46
54
  Example:
47
55
  >>> t1_modality = Modality(
@@ -66,6 +74,7 @@ class Modality:
66
74
  normalized_skull_output_path: Optional[Union[str, Path]] = None,
67
75
  normalized_defaced_output_path: Optional[Union[str, Path]] = None,
68
76
  atlas_correction: bool = True,
77
+ n4_bias_correction: bool = False,
69
78
  ) -> None:
70
79
  # Basics
71
80
  self.modality_name = modality_name
@@ -73,6 +82,8 @@ class Modality:
73
82
  self.current = self.input_path
74
83
  self.normalizer = normalizer
75
84
  self.atlas_correction = atlas_correction
85
+ self.n4_bias_correction = n4_bias_correction
86
+ self.transformation_paths: Dict[PreprocessorSteps, Path | None] = {}
76
87
 
77
88
  # Check that atleast one output is generated
78
89
  if not any(
@@ -128,6 +139,7 @@ class Modality:
128
139
  self.normalized_defaced_output_path = None
129
140
 
130
141
  self.steps = {k: None for k in PreprocessorSteps}
142
+ self.steps[PreprocessorSteps.INPUT] = self.input_path
131
143
 
132
144
  @property
133
145
  def bet(self) -> bool:
@@ -187,16 +199,36 @@ class Modality:
187
199
 
188
200
  # Normalize the image
189
201
  if self.normalizer:
190
- image = read_nifti(str(self.current))
202
+ image = read_image(str(self.current))
191
203
  normalized_image = self.normalizer.normalize(image=image)
192
- write_nifti(
204
+ write_image(
193
205
  input_array=normalized_image,
194
- output_nifti_path=str(self.current),
195
- reference_nifti_path=str(self.current),
206
+ output_path=str(self.current),
207
+ reference_path=str(self.current),
196
208
  )
197
209
  else:
198
210
  logger.info("No normalizer specified; skipping normalization.")
199
211
 
212
+ def _find_transformation_matrix(
213
+ self, transform_incomplete_path: Path
214
+ ) -> Optional[Path]:
215
+ possible_Files = list(
216
+ transform_incomplete_path.parent.glob(f"{transform_incomplete_path.stem}.*")
217
+ )
218
+ if len(possible_Files) == 0:
219
+ logger.warning(
220
+ f"No transformation matrix found for {transform_incomplete_path}. "
221
+ "Returning None."
222
+ )
223
+ return None
224
+ elif len(possible_Files) > 1:
225
+ # TODO: Handle this case more gracefully, e.g., try to find proper extension based on the registrator
226
+ logger.warning(
227
+ f"Multiple transformation matrices found for {transform_incomplete_path}. "
228
+ "Returning the first one."
229
+ )
230
+ return possible_Files[0]
231
+
200
232
  def register(
201
233
  self,
202
234
  registrator: Registrator,
@@ -213,6 +245,7 @@ class Modality:
213
245
  fixed_image_path (str or Path): Path to the fixed image.
214
246
  registration_dir (str or Path): Directory to store registration results.
215
247
  moving_image_name (str): Name of the moving image.
248
+ step (PreprocessorSteps): The current preprocessing step.
216
249
 
217
250
  Returns:
218
251
  Path: Path to the registration matrix.
@@ -224,7 +257,7 @@ class Modality:
224
257
  registered_log = registration_dir / f"{moving_image_name}.log"
225
258
 
226
259
  # Note, add file ending depending on registration backend!
227
- registered_matrix = registration_dir / f"{moving_image_name}"
260
+ registered_matrix = registration_dir / f"M_{moving_image_name}"
228
261
 
229
262
  registrator.register(
230
263
  fixed_image_path=fixed_image_path,
@@ -235,6 +268,11 @@ class Modality:
235
268
  )
236
269
  self.current = registered
237
270
  self.steps[step] = registered
271
+
272
+ self.transformation_paths[step] = self._find_transformation_matrix(
273
+ transform_incomplete_path=registered_matrix
274
+ )
275
+
238
276
  return registered_matrix
239
277
 
240
278
  def apply_bet_mask(
@@ -320,7 +358,7 @@ class Modality:
320
358
  registration_dir_path (str or Path): Directory to store transformation results.
321
359
  moving_image_name (str): Name of the moving image.
322
360
  transformation_matrix_path (str or Path): Path to the transformation matrix.
323
-
361
+ step (PreprocessorSteps): The current preprocessing step.
324
362
  Returns:
325
363
  None
326
364
  """
@@ -331,15 +369,42 @@ class Modality:
331
369
  transformed = registration_dir_path / f"{moving_image_name}.nii.gz"
332
370
  transformed_log = registration_dir_path / f"{moving_image_name}.log"
333
371
 
334
- registrator.transform(
335
- fixed_image_path=fixed_image_path,
336
- moving_image_path=self.current,
337
- transformed_image_path=transformed,
338
- matrix_path=transformation_matrix_path,
339
- log_file_path=transformed_log,
340
- )
372
+ if (
373
+ isinstance(registrator, (ANTsRegistrator, NiftyRegRegistrator))
374
+ and step == PreprocessorSteps.ATLAS_REGISTERED
375
+ ):
376
+ # we test uniting transforms for these registrators
377
+ assert (
378
+ self.transformation_paths.get(PreprocessorSteps.COREGISTERED, None)
379
+ is not None
380
+ ), "Coregistration must be performed before applying atlas registration."
381
+
382
+ registrator.transform(
383
+ fixed_image_path=fixed_image_path,
384
+ moving_image_path=self.steps[PreprocessorSteps.INPUT],
385
+ transformed_image_path=transformed,
386
+ matrix_path=[
387
+ self.transformation_paths[
388
+ PreprocessorSteps.COREGISTERED
389
+ ], # coregistration matrix
390
+ transformation_matrix_path, # atlas registration matrix
391
+ ],
392
+ log_file_path=transformed_log,
393
+ )
394
+ else:
395
+ registrator.transform(
396
+ fixed_image_path=fixed_image_path,
397
+ moving_image_path=self.current,
398
+ transformed_image_path=transformed,
399
+ matrix_path=transformation_matrix_path,
400
+ log_file_path=transformed_log,
401
+ )
402
+
341
403
  self.current = transformed
342
404
  self.steps[step] = transformed
405
+ self.transformation_paths[step] = self._find_transformation_matrix(
406
+ transform_incomplete_path=transformation_matrix_path
407
+ )
343
408
 
344
409
  def extract_brain_region(
345
410
  self,
@@ -444,12 +509,12 @@ class Modality:
444
509
  if normalization:
445
510
  if self.normalizer is None:
446
511
  raise ValueError("Normalizer is required for normalization.")
447
- image = read_nifti(str(self.current))
512
+ image = read_image(str(self.current))
448
513
  normalized_image = self.normalizer.normalize(image=image)
449
- write_nifti(
514
+ write_image(
450
515
  input_array=normalized_image,
451
- output_nifti_path=str(output_path),
452
- reference_nifti_path=str(self.current),
516
+ output_path=str(output_path),
517
+ reference_path=str(self.current),
453
518
  )
454
519
  else:
455
520
  shutil.copyfile(
@@ -473,6 +538,7 @@ class CenterModality(Modality):
473
538
  normalized_skull_output_path (str or Path, optional): Path to save the normalized modality data with skull. Requires a normalizer.
474
539
  normalized_defaced_output_path (str or Path, optional): Path to save the normalized defaced modality data. Requires a normalizer.
475
540
  atlas_correction (bool, optional): Indicates whether atlas correction should be performed.
541
+ n4_bias_correction (bool, optional): Indicates whether N4 bias correction should be performed.
476
542
  bet_mask_output_path (str or Path, optional): Path to save the brain extraction mask.
477
543
  defacing_mask_output_path (str or Path, optional): Path to save the defacing mask.
478
544
 
@@ -488,6 +554,7 @@ class CenterModality(Modality):
488
554
  normalized_defaced_output_path (str or Path, optional): Path to save the normalized defaced modality data. Requires a normalizer.
489
555
  bet (bool): Indicates whether brain extraction is enabled.
490
556
  atlas_correction (bool): Indicates whether atlas correction should be performed.
557
+ n4_bias_correction (bool): Indicates whether N4 bias correction should be performed.
491
558
  bet_mask_output_path (Path, optional): Path to save the brain extraction mask.
492
559
  defacing_mask_output_path (Path, optional): Path to save the defacing mask.
493
560
 
@@ -514,6 +581,7 @@ class CenterModality(Modality):
514
581
  normalized_skull_output_path: Optional[Union[str, Path]] = None,
515
582
  normalized_defaced_output_path: Optional[Union[str, Path]] = None,
516
583
  atlas_correction: bool = True,
584
+ n4_bias_correction: bool = False,
517
585
  bet_mask_output_path: Optional[Union[str, Path]] = None,
518
586
  defacing_mask_output_path: Optional[Union[str, Path]] = None,
519
587
  ) -> None:
@@ -528,6 +596,7 @@ class CenterModality(Modality):
528
596
  normalized_skull_output_path=normalized_skull_output_path,
529
597
  normalized_defaced_output_path=normalized_defaced_output_path,
530
598
  atlas_correction=atlas_correction,
599
+ n4_bias_correction=n4_bias_correction,
531
600
  )
532
601
  # Only for CenterModality
533
602
  self.bet_mask_output_path = (
@@ -0,0 +1,2 @@
1
+ from .n4_bias_corrector import N4BiasCorrector
2
+ from .sitk.sitk_n4_bias_corrector import SitkN4BiasCorrector
@@ -0,0 +1,13 @@
1
+ from abc import ABC, abstractmethod
2
+ from typing import Any
3
+
4
+
5
+ class N4BiasCorrector(ABC):
6
+
7
+ @abstractmethod
8
+ def correct(
9
+ self,
10
+ input_img_path: Any,
11
+ output_img_path: Any,
12
+ ) -> None:
13
+ pass
@@ -0,0 +1,82 @@
1
+ from pathlib import Path
2
+ from typing import Callable, Optional, Union
3
+
4
+ import SimpleITK as sitk
5
+ from auxiliary.io import write_image
6
+
7
+ from brainles_preprocessing.n4_bias_correction.n4_bias_corrector import N4BiasCorrector
8
+
9
+
10
+ class SitkN4BiasCorrector(N4BiasCorrector):
11
+
12
+ def __init__(
13
+ self,
14
+ mask_func: Optional[Callable[[sitk.Image], sitk.Image]] = None,
15
+ n_max_iterations: Optional[int] = None,
16
+ n_fitting_levels: int = 3,
17
+ ) -> None:
18
+ """
19
+ N4 Bias Corrector using SimpleITK.
20
+
21
+ Args:
22
+ mask_func (Optional[Callable[[sitk.Image], sitk.Image]], optional):
23
+ Function that generates a mask from an image.
24
+ Defaults to: `lambda img_itk: sitk.OtsuThreshold(img_itk, 0, 1, 200)`.
25
+ n_max_iterations (Optional[int], optional):
26
+ Maximum number of iterations for bias field correction.
27
+ n_fitting_levels (int, optional):
28
+ Number of fitting levels. Default is 3.
29
+ """
30
+
31
+ if mask_func is None:
32
+ mask_func = lambda img_itk: sitk.OtsuThreshold(img_itk, 0, 1, 200)
33
+ self.mask_func = mask_func
34
+ self.n_max_iterations = n_max_iterations
35
+ self.n_fitting_levels = n_fitting_levels
36
+
37
+ def compute_mask(self, img_itk: sitk.Image) -> sitk.Image:
38
+ """
39
+ Compute the mask for the input image using the provided mask function.
40
+
41
+ Args:
42
+ img_itk (SimpleITK.Image): The input image in SimpleITK format.
43
+
44
+ Returns:
45
+ SimpleITK.Image: The computed mask.
46
+ """
47
+
48
+ return self.mask_func(img_itk)
49
+
50
+ def correct(
51
+ self,
52
+ input_img_path: Union[str, Path],
53
+ output_img_path: Union[str, Path],
54
+ ) -> None:
55
+ """
56
+ Correct the bias field of the input image using SimpleITK.
57
+
58
+ Args:
59
+ input_img_path (Union[str, Path]): Path to the input image.
60
+ output_img_path (Union[str, Path]): Path where the corrected image will be saved.
61
+
62
+ Returns:
63
+ None
64
+ """
65
+ img_itk = sitk.ReadImage(str(input_img_path))
66
+
67
+ mask_itk = self.compute_mask(img_itk)
68
+
69
+ corrector = sitk.N4BiasFieldCorrectionImageFilter()
70
+ if self.n_max_iterations is not None:
71
+ corrector.SetMaximumNumberOfIterations(
72
+ [self.n_max_iterations] * self.n_fitting_levels
73
+ )
74
+
75
+ corrected_img = corrector.Execute(img_itk, mask_itk)
76
+ corrected_img = sitk.GetArrayFromImage(corrected_img)
77
+
78
+ write_image(
79
+ input_array=corrected_img,
80
+ output_path=str(output_img_path),
81
+ reference_path=str(input_img_path),
82
+ )