melage 0.0.65__py3-none-any.whl

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 (501) hide show
  1. melage/__init__.py +16 -0
  2. melage/cli.py +4 -0
  3. melage/graphics/GLGraphicsItem.py +286 -0
  4. melage/graphics/GLViewWidget.py +595 -0
  5. melage/graphics/Transform3D.py +55 -0
  6. melage/graphics/__init__.py +8 -0
  7. melage/graphics/functions.py +101 -0
  8. melage/graphics/items/GLAxisItem.py +149 -0
  9. melage/graphics/items/GLGridItem.py +178 -0
  10. melage/graphics/items/GLPolygonItem.py +77 -0
  11. melage/graphics/items/GLScatterPlotItem.py +135 -0
  12. melage/graphics/items/GLVolumeItem.py +280 -0
  13. melage/graphics/items/GLVolumeItem_b.py +237 -0
  14. melage/graphics/items/__init__.py +0 -0
  15. melage/graphics/shaders.py +202 -0
  16. melage/main.py +270 -0
  17. melage/requirements22.txt +25 -0
  18. melage/requirements_old.txt +28 -0
  19. melage/resource/0circle.png +0 -0
  20. melage/resource/0circle_faded.png +0 -0
  21. melage/resource/3d.png +0 -0
  22. melage/resource/3d.psd +0 -0
  23. melage/resource/3dFaded.png +0 -0
  24. melage/resource/Eraser.png +0 -0
  25. melage/resource/EraserFaded.png +0 -0
  26. melage/resource/EraserX.png +0 -0
  27. melage/resource/EraserXFaded.png +0 -0
  28. melage/resource/Eraser_icon.svg +79 -0
  29. melage/resource/Hand.png +0 -0
  30. melage/resource/HandIcons_0.png +0 -0
  31. melage/resource/Hand_IX.png +0 -0
  32. melage/resource/Hand_IXFaded.png +0 -0
  33. melage/resource/Handsqueezed.png +0 -0
  34. melage/resource/Handwriting (copy).png +0 -0
  35. melage/resource/Handwriting.png +0 -0
  36. melage/resource/HandwritingMinus.png +0 -0
  37. melage/resource/HandwritingMinusX.png +0 -0
  38. melage/resource/HandwritingPlus.png +0 -0
  39. melage/resource/HandwritingPlusX.png +0 -0
  40. melage/resource/Move_icon.svg +8 -0
  41. melage/resource/PngItem_2422924.png +0 -0
  42. melage/resource/about.png +0 -0
  43. melage/resource/about_logo.png +0 -0
  44. melage/resource/about_logo0.png +0 -0
  45. melage/resource/action_check.png +0 -0
  46. melage/resource/action_check_OFF.png +0 -0
  47. melage/resource/arrow).png +0 -0
  48. melage/resource/arrow.png +0 -0
  49. melage/resource/arrowFaded.png +0 -0
  50. melage/resource/arrow_org.png +0 -0
  51. melage/resource/arrow_org.png.png +0 -0
  52. melage/resource/arrows.png +0 -0
  53. melage/resource/authors.mp4 +0 -0
  54. melage/resource/box.png +0 -0
  55. melage/resource/check-image-icon-0.jpg +0 -0
  56. melage/resource/circle.png +0 -0
  57. melage/resource/circle_faded.png +0 -0
  58. melage/resource/circle_or.png +0 -0
  59. melage/resource/close.png +0 -0
  60. melage/resource/close_bg.png +0 -0
  61. melage/resource/color/Simple.txt +18 -0
  62. melage/resource/color/Tissue.txt +24 -0
  63. melage/resource/color/Tissue12.txt +27 -0
  64. melage/resource/color/albert_LUT.txt +102 -0
  65. melage/resource/color/mcrib_LUT.txt +102 -0
  66. melage/resource/color/pediatric1.txt +29 -0
  67. melage/resource/color/pediatric1_old.txt +27 -0
  68. melage/resource/color/pediatric2.txt +87 -0
  69. melage/resource/color/pediatric3.txt +29 -0
  70. melage/resource/color/pediatrics (copy).csv +103 -0
  71. melage/resource/color/tissue_seg.txt +4 -0
  72. melage/resource/contour.png +0 -0
  73. melage/resource/contour.svg +2 -0
  74. melage/resource/contourFaded.png +0 -0
  75. melage/resource/contourX.png +0 -0
  76. melage/resource/contourXFaded.png +0 -0
  77. melage/resource/dti.png +0 -0
  78. melage/resource/dti0.png +0 -0
  79. melage/resource/dti222.png +0 -0
  80. melage/resource/dti_or.png +0 -0
  81. melage/resource/eco.png +0 -0
  82. melage/resource/eco22.png +0 -0
  83. melage/resource/eco_old.png +0 -0
  84. melage/resource/eco_or.png +0 -0
  85. melage/resource/eco_or2.png +0 -0
  86. melage/resource/eco_seg.png +0 -0
  87. melage/resource/eco_seg_old.png +0 -0
  88. melage/resource/export.png +0 -0
  89. melage/resource/hand-grab-icon-10.jpg +0 -0
  90. melage/resource/hand-grab-icon-25.jpg +0 -0
  91. melage/resource/info.png +0 -0
  92. melage/resource/line.png +0 -0
  93. melage/resource/linefaded.png +0 -0
  94. melage/resource/load.png +0 -0
  95. melage/resource/main.ico +0 -0
  96. melage/resource/manual_images/3D_rightc.png +0 -0
  97. melage/resource/manual_images/3D_rightc_goto.png +0 -0
  98. melage/resource/manual_images/3D_rightc_paint.png +0 -0
  99. melage/resource/manual_images/3D_rightc_paint_draw1.png +0 -0
  100. melage/resource/manual_images/3D_rightc_paint_draw2.png +0 -0
  101. melage/resource/manual_images/3D_rightc_paint_render.png +0 -0
  102. melage/resource/manual_images/3D_rightc_paint_render2.png +0 -0
  103. melage/resource/manual_images/3D_rightc_paint_render3.png +0 -0
  104. melage/resource/manual_images/3D_rightc_paint_render4.png +0 -0
  105. melage/resource/manual_images/3D_rightc_paint_render5.png +0 -0
  106. melage/resource/manual_images/3D_rightc_paint_render6.png +0 -0
  107. melage/resource/manual_images/3D_rightc_seg.png +0 -0
  108. melage/resource/manual_images/exit_toolbar.png +0 -0
  109. melage/resource/manual_images/load_image_file.png +0 -0
  110. melage/resource/manual_images/load_image_file_openp.png +0 -0
  111. melage/resource/manual_images/main_page.png +0 -0
  112. melage/resource/manual_images/menu_file.png +0 -0
  113. melage/resource/manual_images/menu_file_export.png +0 -0
  114. melage/resource/manual_images/menu_file_import.png +0 -0
  115. melage/resource/manual_images/menu_file_settings.png +0 -0
  116. melage/resource/manual_images/menu_file_ss.png +0 -0
  117. melage/resource/manual_images/open_save_load.png +0 -0
  118. melage/resource/manual_images/panning_toolbar.png +0 -0
  119. melage/resource/manual_images/segmentation_toolbar.png +0 -0
  120. melage/resource/manual_images/tab_mri.png +0 -0
  121. melage/resource/manual_images/tab_us.png +0 -0
  122. melage/resource/manual_images/tabs.png +0 -0
  123. melage/resource/manual_images/toolbar_tools.png +0 -0
  124. melage/resource/manual_images/tools_basic.png +0 -0
  125. melage/resource/manual_images/tools_bet.png +0 -0
  126. melage/resource/manual_images/tools_cs.png +0 -0
  127. melage/resource/manual_images/tools_deepbet.png +0 -0
  128. melage/resource/manual_images/tools_imageinfo.png +0 -0
  129. melage/resource/manual_images/tools_maskO.png +0 -0
  130. melage/resource/manual_images/tools_masking.png +0 -0
  131. melage/resource/manual_images/tools_n4b.png +0 -0
  132. melage/resource/manual_images/tools_resize.png +0 -0
  133. melage/resource/manual_images/tools_ruler.png +0 -0
  134. melage/resource/manual_images/tools_seg.png +0 -0
  135. melage/resource/manual_images/tools_threshold.png +0 -0
  136. melage/resource/manual_images/tools_tools.png +0 -0
  137. melage/resource/manual_images/widget_color.png +0 -0
  138. melage/resource/manual_images/widget_color_add.png +0 -0
  139. melage/resource/manual_images/widget_color_add2.png +0 -0
  140. melage/resource/manual_images/widget_color_additional.png +0 -0
  141. melage/resource/manual_images/widget_images.png +0 -0
  142. melage/resource/manual_images/widget_images2.png +0 -0
  143. melage/resource/manual_images/widget_images3.png +0 -0
  144. melage/resource/manual_images/widget_marker.png +0 -0
  145. melage/resource/manual_images/widget_mri.png +0 -0
  146. melage/resource/manual_images/widget_mri2.png +0 -0
  147. melage/resource/manual_images/widget_segintensity.png +0 -0
  148. melage/resource/manual_images/widget_tab_mutualview.png +0 -0
  149. melage/resource/manual_images/widget_tab_mutualview2.png +0 -0
  150. melage/resource/manual_images/widget_table.png +0 -0
  151. melage/resource/manual_images/widget_table2.png +0 -0
  152. melage/resource/manual_images/widget_us.png +0 -0
  153. melage/resource/melage_top.ico +0 -0
  154. melage/resource/melage_top.png +0 -0
  155. melage/resource/melage_top0.png +0 -0
  156. melage/resource/melage_top1.png +0 -0
  157. melage/resource/melage_top4.png +0 -0
  158. melage/resource/mri (copy).png +0 -0
  159. melage/resource/mri.png +0 -0
  160. melage/resource/mri0.png +0 -0
  161. melage/resource/mri000.png +0 -0
  162. melage/resource/mri22.png +0 -0
  163. melage/resource/mri_big.png +0 -0
  164. melage/resource/mri_old.png +0 -0
  165. melage/resource/mri_seg.png +0 -0
  166. melage/resource/mri_seg_old.png +0 -0
  167. melage/resource/new.png +0 -0
  168. melage/resource/open.png +0 -0
  169. melage/resource/open2.png +0 -0
  170. melage/resource/pan.png +0 -0
  171. melage/resource/pencil.png +0 -0
  172. melage/resource/pencilFaded.png +0 -0
  173. melage/resource/points.png +0 -0
  174. melage/resource/pointsFaded.png +0 -0
  175. melage/resource/rotate.png +0 -0
  176. melage/resource/ruler.png +0 -0
  177. melage/resource/rulerFaded.png +0 -0
  178. melage/resource/s.png +0 -0
  179. melage/resource/s.psd +0 -0
  180. melage/resource/save.png +0 -0
  181. melage/resource/saveas.png +0 -0
  182. melage/resource/seg_mri.png +0 -0
  183. melage/resource/seg_mri2.png +0 -0
  184. melage/resource/settings.png +0 -0
  185. melage/resource/synch.png +0 -0
  186. melage/resource/synchFaded.png +0 -0
  187. melage/resource/theme/rc/.keep +1 -0
  188. melage/resource/theme/rc/arrow_down.png +0 -0
  189. melage/resource/theme/rc/arrow_down@2x.png +0 -0
  190. melage/resource/theme/rc/arrow_down_disabled.png +0 -0
  191. melage/resource/theme/rc/arrow_down_disabled@2x.png +0 -0
  192. melage/resource/theme/rc/arrow_down_focus.png +0 -0
  193. melage/resource/theme/rc/arrow_down_focus@2x.png +0 -0
  194. melage/resource/theme/rc/arrow_down_pressed.png +0 -0
  195. melage/resource/theme/rc/arrow_down_pressed@2x.png +0 -0
  196. melage/resource/theme/rc/arrow_left.png +0 -0
  197. melage/resource/theme/rc/arrow_left@2x.png +0 -0
  198. melage/resource/theme/rc/arrow_left_disabled.png +0 -0
  199. melage/resource/theme/rc/arrow_left_disabled@2x.png +0 -0
  200. melage/resource/theme/rc/arrow_left_focus.png +0 -0
  201. melage/resource/theme/rc/arrow_left_focus@2x.png +0 -0
  202. melage/resource/theme/rc/arrow_left_pressed.png +0 -0
  203. melage/resource/theme/rc/arrow_left_pressed@2x.png +0 -0
  204. melage/resource/theme/rc/arrow_right.png +0 -0
  205. melage/resource/theme/rc/arrow_right@2x.png +0 -0
  206. melage/resource/theme/rc/arrow_right_disabled.png +0 -0
  207. melage/resource/theme/rc/arrow_right_disabled@2x.png +0 -0
  208. melage/resource/theme/rc/arrow_right_focus.png +0 -0
  209. melage/resource/theme/rc/arrow_right_focus@2x.png +0 -0
  210. melage/resource/theme/rc/arrow_right_pressed.png +0 -0
  211. melage/resource/theme/rc/arrow_right_pressed@2x.png +0 -0
  212. melage/resource/theme/rc/arrow_up.png +0 -0
  213. melage/resource/theme/rc/arrow_up@2x.png +0 -0
  214. melage/resource/theme/rc/arrow_up_disabled.png +0 -0
  215. melage/resource/theme/rc/arrow_up_disabled@2x.png +0 -0
  216. melage/resource/theme/rc/arrow_up_focus.png +0 -0
  217. melage/resource/theme/rc/arrow_up_focus@2x.png +0 -0
  218. melage/resource/theme/rc/arrow_up_pressed.png +0 -0
  219. melage/resource/theme/rc/arrow_up_pressed@2x.png +0 -0
  220. melage/resource/theme/rc/base_icon.png +0 -0
  221. melage/resource/theme/rc/base_icon@2x.png +0 -0
  222. melage/resource/theme/rc/base_icon_disabled.png +0 -0
  223. melage/resource/theme/rc/base_icon_disabled@2x.png +0 -0
  224. melage/resource/theme/rc/base_icon_focus.png +0 -0
  225. melage/resource/theme/rc/base_icon_focus@2x.png +0 -0
  226. melage/resource/theme/rc/base_icon_pressed.png +0 -0
  227. melage/resource/theme/rc/base_icon_pressed@2x.png +0 -0
  228. melage/resource/theme/rc/branch_closed.png +0 -0
  229. melage/resource/theme/rc/branch_closed@2x.png +0 -0
  230. melage/resource/theme/rc/branch_closed_disabled.png +0 -0
  231. melage/resource/theme/rc/branch_closed_disabled@2x.png +0 -0
  232. melage/resource/theme/rc/branch_closed_focus.png +0 -0
  233. melage/resource/theme/rc/branch_closed_focus@2x.png +0 -0
  234. melage/resource/theme/rc/branch_closed_pressed.png +0 -0
  235. melage/resource/theme/rc/branch_closed_pressed@2x.png +0 -0
  236. melage/resource/theme/rc/branch_end.png +0 -0
  237. melage/resource/theme/rc/branch_end@2x.png +0 -0
  238. melage/resource/theme/rc/branch_end_disabled.png +0 -0
  239. melage/resource/theme/rc/branch_end_disabled@2x.png +0 -0
  240. melage/resource/theme/rc/branch_end_focus.png +0 -0
  241. melage/resource/theme/rc/branch_end_focus@2x.png +0 -0
  242. melage/resource/theme/rc/branch_end_pressed.png +0 -0
  243. melage/resource/theme/rc/branch_end_pressed@2x.png +0 -0
  244. melage/resource/theme/rc/branch_line.png +0 -0
  245. melage/resource/theme/rc/branch_line@2x.png +0 -0
  246. melage/resource/theme/rc/branch_line_disabled.png +0 -0
  247. melage/resource/theme/rc/branch_line_disabled@2x.png +0 -0
  248. melage/resource/theme/rc/branch_line_focus.png +0 -0
  249. melage/resource/theme/rc/branch_line_focus@2x.png +0 -0
  250. melage/resource/theme/rc/branch_line_pressed.png +0 -0
  251. melage/resource/theme/rc/branch_line_pressed@2x.png +0 -0
  252. melage/resource/theme/rc/branch_more.png +0 -0
  253. melage/resource/theme/rc/branch_more@2x.png +0 -0
  254. melage/resource/theme/rc/branch_more_disabled.png +0 -0
  255. melage/resource/theme/rc/branch_more_disabled@2x.png +0 -0
  256. melage/resource/theme/rc/branch_more_focus.png +0 -0
  257. melage/resource/theme/rc/branch_more_focus@2x.png +0 -0
  258. melage/resource/theme/rc/branch_more_pressed.png +0 -0
  259. melage/resource/theme/rc/branch_more_pressed@2x.png +0 -0
  260. melage/resource/theme/rc/branch_open.png +0 -0
  261. melage/resource/theme/rc/branch_open@2x.png +0 -0
  262. melage/resource/theme/rc/branch_open_disabled.png +0 -0
  263. melage/resource/theme/rc/branch_open_disabled@2x.png +0 -0
  264. melage/resource/theme/rc/branch_open_focus.png +0 -0
  265. melage/resource/theme/rc/branch_open_focus@2x.png +0 -0
  266. melage/resource/theme/rc/branch_open_pressed.png +0 -0
  267. melage/resource/theme/rc/branch_open_pressed@2x.png +0 -0
  268. melage/resource/theme/rc/checkbox_checked.png +0 -0
  269. melage/resource/theme/rc/checkbox_checked0.png +0 -0
  270. melage/resource/theme/rc/checkbox_checked@2x.png +0 -0
  271. melage/resource/theme/rc/checkbox_checked@2x0.png +0 -0
  272. melage/resource/theme/rc/checkbox_checked@2x000.png.png +0 -0
  273. melage/resource/theme/rc/checkbox_checked_disabled.png +0 -0
  274. melage/resource/theme/rc/checkbox_checked_disabled0.png +0 -0
  275. melage/resource/theme/rc/checkbox_checked_disabled@2x.png +0 -0
  276. melage/resource/theme/rc/checkbox_checked_disabled@2x0.png +0 -0
  277. melage/resource/theme/rc/checkbox_checked_focus.png +0 -0
  278. melage/resource/theme/rc/checkbox_checked_focus0.png +0 -0
  279. melage/resource/theme/rc/checkbox_checked_focus@2x.png +0 -0
  280. melage/resource/theme/rc/checkbox_checked_focus@2x0.png +0 -0
  281. melage/resource/theme/rc/checkbox_checked_pressed.png +0 -0
  282. melage/resource/theme/rc/checkbox_checked_pressed0.png +0 -0
  283. melage/resource/theme/rc/checkbox_checked_pressed@2x.png +0 -0
  284. melage/resource/theme/rc/checkbox_checked_pressed@2x0.png +0 -0
  285. melage/resource/theme/rc/checkbox_indeterminate.png +0 -0
  286. melage/resource/theme/rc/checkbox_indeterminate@2x.png +0 -0
  287. melage/resource/theme/rc/checkbox_indeterminate_disabled.png +0 -0
  288. melage/resource/theme/rc/checkbox_indeterminate_disabled@2x.png +0 -0
  289. melage/resource/theme/rc/checkbox_indeterminate_focus.png +0 -0
  290. melage/resource/theme/rc/checkbox_indeterminate_focus@2x.png +0 -0
  291. melage/resource/theme/rc/checkbox_indeterminate_pressed.png +0 -0
  292. melage/resource/theme/rc/checkbox_indeterminate_pressed@2x.png +0 -0
  293. melage/resource/theme/rc/checkbox_unchecked.png +0 -0
  294. melage/resource/theme/rc/checkbox_unchecked0.png +0 -0
  295. melage/resource/theme/rc/checkbox_unchecked00.png +0 -0
  296. melage/resource/theme/rc/checkbox_unchecked@2x.png +0 -0
  297. melage/resource/theme/rc/checkbox_unchecked@2x0.png +0 -0
  298. melage/resource/theme/rc/checkbox_unchecked@2x00.png +0 -0
  299. melage/resource/theme/rc/checkbox_unchecked_disabled.png +0 -0
  300. melage/resource/theme/rc/checkbox_unchecked_disabled0.png +0 -0
  301. melage/resource/theme/rc/checkbox_unchecked_disabled00.png +0 -0
  302. melage/resource/theme/rc/checkbox_unchecked_disabled@2x.png +0 -0
  303. melage/resource/theme/rc/checkbox_unchecked_disabled@2x0.png +0 -0
  304. melage/resource/theme/rc/checkbox_unchecked_disabled@2x00.png +0 -0
  305. melage/resource/theme/rc/checkbox_unchecked_focus.png +0 -0
  306. melage/resource/theme/rc/checkbox_unchecked_focus0.png +0 -0
  307. melage/resource/theme/rc/checkbox_unchecked_focus00.png +0 -0
  308. melage/resource/theme/rc/checkbox_unchecked_focus@2x.png +0 -0
  309. melage/resource/theme/rc/checkbox_unchecked_focus@2x0.png +0 -0
  310. melage/resource/theme/rc/checkbox_unchecked_focus@2x00.png +0 -0
  311. melage/resource/theme/rc/checkbox_unchecked_pressed.png +0 -0
  312. melage/resource/theme/rc/checkbox_unchecked_pressed0.png +0 -0
  313. melage/resource/theme/rc/checkbox_unchecked_pressed00.png +0 -0
  314. melage/resource/theme/rc/checkbox_unchecked_pressed@2x.png +0 -0
  315. melage/resource/theme/rc/checkbox_unchecked_pressed@2x0.png +0 -0
  316. melage/resource/theme/rc/checkbox_unchecked_pressed@2x00.png +0 -0
  317. melage/resource/theme/rc/line_horizontal.png +0 -0
  318. melage/resource/theme/rc/line_horizontal@2x.png +0 -0
  319. melage/resource/theme/rc/line_horizontal_disabled.png +0 -0
  320. melage/resource/theme/rc/line_horizontal_disabled@2x.png +0 -0
  321. melage/resource/theme/rc/line_horizontal_focus.png +0 -0
  322. melage/resource/theme/rc/line_horizontal_focus@2x.png +0 -0
  323. melage/resource/theme/rc/line_horizontal_pressed.png +0 -0
  324. melage/resource/theme/rc/line_horizontal_pressed@2x.png +0 -0
  325. melage/resource/theme/rc/line_vertical.png +0 -0
  326. melage/resource/theme/rc/line_vertical@2x.png +0 -0
  327. melage/resource/theme/rc/line_vertical_disabled.png +0 -0
  328. melage/resource/theme/rc/line_vertical_disabled@2x.png +0 -0
  329. melage/resource/theme/rc/line_vertical_focus.png +0 -0
  330. melage/resource/theme/rc/line_vertical_focus@2x.png +0 -0
  331. melage/resource/theme/rc/line_vertical_pressed.png +0 -0
  332. melage/resource/theme/rc/line_vertical_pressed@2x.png +0 -0
  333. melage/resource/theme/rc/radio_checked.png +0 -0
  334. melage/resource/theme/rc/radio_checked@2x.png +0 -0
  335. melage/resource/theme/rc/radio_checked_disabled.png +0 -0
  336. melage/resource/theme/rc/radio_checked_disabled@2x.png +0 -0
  337. melage/resource/theme/rc/radio_checked_focus.png +0 -0
  338. melage/resource/theme/rc/radio_checked_focus@2x.png +0 -0
  339. melage/resource/theme/rc/radio_checked_pressed.png +0 -0
  340. melage/resource/theme/rc/radio_checked_pressed@2x.png +0 -0
  341. melage/resource/theme/rc/radio_unchecked.png +0 -0
  342. melage/resource/theme/rc/radio_unchecked@2x.png +0 -0
  343. melage/resource/theme/rc/radio_unchecked_disabled.png +0 -0
  344. melage/resource/theme/rc/radio_unchecked_disabled@2x.png +0 -0
  345. melage/resource/theme/rc/radio_unchecked_focus.png +0 -0
  346. melage/resource/theme/rc/radio_unchecked_focus@2x.png +0 -0
  347. melage/resource/theme/rc/radio_unchecked_pressed.png +0 -0
  348. melage/resource/theme/rc/radio_unchecked_pressed@2x.png +0 -0
  349. melage/resource/theme/rc/toolbar_move_horizontal.png +0 -0
  350. melage/resource/theme/rc/toolbar_move_horizontal@2x.png +0 -0
  351. melage/resource/theme/rc/toolbar_move_horizontal_disabled.png +0 -0
  352. melage/resource/theme/rc/toolbar_move_horizontal_disabled@2x.png +0 -0
  353. melage/resource/theme/rc/toolbar_move_horizontal_focus.png +0 -0
  354. melage/resource/theme/rc/toolbar_move_horizontal_focus@2x.png +0 -0
  355. melage/resource/theme/rc/toolbar_move_horizontal_pressed.png +0 -0
  356. melage/resource/theme/rc/toolbar_move_horizontal_pressed@2x.png +0 -0
  357. melage/resource/theme/rc/toolbar_move_vertical.png +0 -0
  358. melage/resource/theme/rc/toolbar_move_vertical@2x.png +0 -0
  359. melage/resource/theme/rc/toolbar_move_vertical_disabled.png +0 -0
  360. melage/resource/theme/rc/toolbar_move_vertical_disabled@2x.png +0 -0
  361. melage/resource/theme/rc/toolbar_move_vertical_focus.png +0 -0
  362. melage/resource/theme/rc/toolbar_move_vertical_focus@2x.png +0 -0
  363. melage/resource/theme/rc/toolbar_move_vertical_pressed.png +0 -0
  364. melage/resource/theme/rc/toolbar_move_vertical_pressed@2x.png +0 -0
  365. melage/resource/theme/rc/toolbar_separator_horizontal.png +0 -0
  366. melage/resource/theme/rc/toolbar_separator_horizontal@2x.png +0 -0
  367. melage/resource/theme/rc/toolbar_separator_horizontal_disabled.png +0 -0
  368. melage/resource/theme/rc/toolbar_separator_horizontal_disabled@2x.png +0 -0
  369. melage/resource/theme/rc/toolbar_separator_horizontal_focus.png +0 -0
  370. melage/resource/theme/rc/toolbar_separator_horizontal_focus@2x.png +0 -0
  371. melage/resource/theme/rc/toolbar_separator_horizontal_pressed.png +0 -0
  372. melage/resource/theme/rc/toolbar_separator_horizontal_pressed@2x.png +0 -0
  373. melage/resource/theme/rc/toolbar_separator_vertical.png +0 -0
  374. melage/resource/theme/rc/toolbar_separator_vertical@2x.png +0 -0
  375. melage/resource/theme/rc/toolbar_separator_vertical_disabled.png +0 -0
  376. melage/resource/theme/rc/toolbar_separator_vertical_disabled@2x.png +0 -0
  377. melage/resource/theme/rc/toolbar_separator_vertical_focus.png +0 -0
  378. melage/resource/theme/rc/toolbar_separator_vertical_focus@2x.png +0 -0
  379. melage/resource/theme/rc/toolbar_separator_vertical_pressed.png +0 -0
  380. melage/resource/theme/rc/toolbar_separator_vertical_pressed@2x.png +0 -0
  381. melage/resource/theme/rc/transparent.png +0 -0
  382. melage/resource/theme/rc/transparent@2x.png +0 -0
  383. melage/resource/theme/rc/transparent_disabled.png +0 -0
  384. melage/resource/theme/rc/transparent_disabled@2x.png +0 -0
  385. melage/resource/theme/rc/transparent_focus.png +0 -0
  386. melage/resource/theme/rc/transparent_focus@2x.png +0 -0
  387. melage/resource/theme/rc/transparent_pressed.png +0 -0
  388. melage/resource/theme/rc/transparent_pressed@2x.png +0 -0
  389. melage/resource/theme/rc/window_close.png +0 -0
  390. melage/resource/theme/rc/window_close@2x.png +0 -0
  391. melage/resource/theme/rc/window_close_disabled.png +0 -0
  392. melage/resource/theme/rc/window_close_disabled@2x.png +0 -0
  393. melage/resource/theme/rc/window_close_focus.png +0 -0
  394. melage/resource/theme/rc/window_close_focus@2x.png +0 -0
  395. melage/resource/theme/rc/window_close_pressed.png +0 -0
  396. melage/resource/theme/rc/window_close_pressed@2x.png +0 -0
  397. melage/resource/theme/rc/window_grip.png +0 -0
  398. melage/resource/theme/rc/window_grip@2x.png +0 -0
  399. melage/resource/theme/rc/window_grip_disabled.png +0 -0
  400. melage/resource/theme/rc/window_grip_disabled@2x.png +0 -0
  401. melage/resource/theme/rc/window_grip_focus.png +0 -0
  402. melage/resource/theme/rc/window_grip_focus@2x.png +0 -0
  403. melage/resource/theme/rc/window_grip_pressed.png +0 -0
  404. melage/resource/theme/rc/window_grip_pressed@2x.png +0 -0
  405. melage/resource/theme/rc/window_minimize.png +0 -0
  406. melage/resource/theme/rc/window_minimize@2x.png +0 -0
  407. melage/resource/theme/rc/window_minimize_disabled.png +0 -0
  408. melage/resource/theme/rc/window_minimize_disabled@2x.png +0 -0
  409. melage/resource/theme/rc/window_minimize_focus.png +0 -0
  410. melage/resource/theme/rc/window_minimize_focus@2x.png +0 -0
  411. melage/resource/theme/rc/window_minimize_pressed.png +0 -0
  412. melage/resource/theme/rc/window_minimize_pressed@2x.png +0 -0
  413. melage/resource/theme/rc/window_undock.png +0 -0
  414. melage/resource/theme/rc/window_undock@2x.png +0 -0
  415. melage/resource/theme/rc/window_undock_disabled.png +0 -0
  416. melage/resource/theme/rc/window_undock_disabled@2x.png +0 -0
  417. melage/resource/theme/rc/window_undock_focus.png +0 -0
  418. melage/resource/theme/rc/window_undock_focus@2x.png +0 -0
  419. melage/resource/theme/rc/window_undock_pressed.png +0 -0
  420. melage/resource/theme/rc/window_undock_pressed@2x.png +0 -0
  421. melage/resource/theme/style.qss +2223 -0
  422. melage/resource/tract.png +0 -0
  423. melage/resource/view1.png +0 -0
  424. melage/resource/view1_eco.png +0 -0
  425. melage/resource/view1_mri.png +0 -0
  426. melage/resource/view1_seg.png +0 -0
  427. melage/resource/view2.png +0 -0
  428. melage/resource/view2_seg.png +0 -0
  429. melage/resource/w.png +0 -0
  430. melage/resource/zoom_in.png +0 -0
  431. melage/resource/zoom_inFaded.png +0 -0
  432. melage/resource/zoom_out.png +0 -0
  433. melage/resource/zoom_outFaded.png +0 -0
  434. melage/some_notes.txt +3 -0
  435. melage/utils/DispalyIm.py +2788 -0
  436. melage/utils/GMM.py +720 -0
  437. melage/utils/Shaders_120.py +257 -0
  438. melage/utils/Shaders_330.py +314 -0
  439. melage/utils/Shaders_bu.py +314 -0
  440. melage/utils/__init__0.py +7 -0
  441. melage/utils/brain_extraction_helper.py +234 -0
  442. melage/utils/custom_QScrollBar.py +61 -0
  443. melage/utils/glScientific.py +1554 -0
  444. melage/utils/glScientific_bc.py +1585 -0
  445. melage/utils/readData.py +1061 -0
  446. melage/utils/registration.py +512 -0
  447. melage/utils/source_folder.py +18 -0
  448. melage/utils/utils.py +3808 -0
  449. melage/version.txt +1 -0
  450. melage/widgets/ApplyMask.py +212 -0
  451. melage/widgets/ChangeSystem.py +152 -0
  452. melage/widgets/DeepLModels/InfantSegment/Unet.py +464 -0
  453. melage/widgets/DeepLModels/NPP/dataset/mri_dataset_affine.py +149 -0
  454. melage/widgets/DeepLModels/NPP/models/checkpoints/npp_v1.pth.py +0 -0
  455. melage/widgets/DeepLModels/NPP/models/losses.py +146 -0
  456. melage/widgets/DeepLModels/NPP/models/model.py +272 -0
  457. melage/widgets/DeepLModels/NPP/models/utils.py +303 -0
  458. melage/widgets/DeepLModels/NPP/npp.py +116 -0
  459. melage/widgets/DeepLModels/NPP/requirements.txt +8 -0
  460. melage/widgets/DeepLModels/NPP/train/train.py +116 -0
  461. melage/widgets/DeepLModels/Unet3DAtt.py +657 -0
  462. melage/widgets/DeepLModels/Unet3D_basic.py +648 -0
  463. melage/widgets/DeepLModels/new_unet.py +652 -0
  464. melage/widgets/DeepLModels/new_unet_old.py +639 -0
  465. melage/widgets/DeepLModels/new_unet_old2.py +658 -0
  466. melage/widgets/HistImage.py +153 -0
  467. melage/widgets/ImageThresholding.py +222 -0
  468. melage/widgets/MaskOperations.py +147 -0
  469. melage/widgets/N4Dialog.py +241 -0
  470. melage/widgets/Segmentation/FCM.py +1553 -0
  471. melage/widgets/Segmentation/__init__.py +588 -0
  472. melage/widgets/Segmentation/utils.py +417 -0
  473. melage/widgets/SemiAutoSeg.py +666 -0
  474. melage/widgets/Synthstrip.py +141 -0
  475. melage/widgets/__init__0.py +5 -0
  476. melage/widgets/about.py +246 -0
  477. melage/widgets/activation.py +437 -0
  478. melage/widgets/activator.py +147 -0
  479. melage/widgets/be_dl.py +409 -0
  480. melage/widgets/be_dl_unet3d.py +441 -0
  481. melage/widgets/brain_extraction.py +855 -0
  482. melage/widgets/brain_extraction_dl.py +887 -0
  483. melage/widgets/brain_extraction_dl_bu.py +869 -0
  484. melage/widgets/colorwidget.py +100 -0
  485. melage/widgets/dockWidgets.py +2005 -0
  486. melage/widgets/enhanceImWidget.py +109 -0
  487. melage/widgets/fileDialog_widget.py +275 -0
  488. melage/widgets/iminfo.py +346 -0
  489. melage/widgets/mainwindow_widget.py +6775 -0
  490. melage/widgets/melageAbout.py +123 -0
  491. melage/widgets/openglWidgets.py +556 -0
  492. melage/widgets/registrationWidget.py +342 -0
  493. melage/widgets/repeat_widget.py +74 -0
  494. melage/widgets/screenshot_widget.py +138 -0
  495. melage/widgets/settings_widget.py +77 -0
  496. melage/widgets/tranformationWidget.py +275 -0
  497. melage-0.0.65.dist-info/METADATA +742 -0
  498. melage-0.0.65.dist-info/RECORD +501 -0
  499. melage-0.0.65.dist-info/WHEEL +5 -0
  500. melage-0.0.65.dist-info/entry_points.txt +2 -0
  501. melage-0.0.65.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1553 @@
1
+ import numpy as np
2
+
3
+ from melage.widgets.Segmentation.utils import BiasCorrection
4
+ from melage.widgets.Segmentation.utils import create_window_3D, ssim3D
5
+ from melage.widgets.Segmentation.utils import LargestCC, \
6
+ update_according_to_neighbours_conv, neighborhood_conv, axis_based_convolution, adjust_common_structures, \
7
+ compute_sdf, rescale_between_a_b
8
+ from sklearn.preprocessing import PolynomialFeatures
9
+ from scipy.ndimage import binary_fill_holes, binary_dilation
10
+ from scipy.special import softmax
11
+ from scipy.ndimage import gaussian_filter
12
+ from skimage.metrics import structural_similarity as ssim
13
+ from scipy.ndimage import sobel
14
+ import abc
15
+
16
+
17
+
18
+
19
+ class FCM(object):
20
+
21
+ def __init__(self, parent=None):
22
+ self.parent = parent
23
+
24
+
25
+ @abc.abstractmethod
26
+ def Update_memership(self):
27
+ raise NotImplementedError("Subclass should implement this.")
28
+
29
+ @abc.abstractmethod
30
+ def Update_centers(self):
31
+ raise NotImplementedError("Subclass should implement this.")
32
+
33
+ def predict(self, use_softmax=False):
34
+ raise NotImplementedError("Subclass should implement this.")
35
+
36
+
37
+ @abc.abstractmethod
38
+ def fit(self):
39
+ raise NotImplementedError("Subclass should implement this.")
40
+
41
+ def _normalizeAtlasCreateMask(self):
42
+ raise NotImplementedError("Subclass should implement this.")
43
+
44
+ def initialize_fcm(self, initialization_method='otsu'):
45
+
46
+ if initialization_method=='random':
47
+ self.rng = np.random.default_rng(0)
48
+ m, n, o = self.image.shape
49
+ self.Membership = self.rng.uniform(size=(m, n, o, self.num_tissues))
50
+ self.Membership = self.Membership / np.tile(self.Membership.sum(axis=-1)[...,np.newaxis], self.num_tissues)
51
+
52
+ self.Membership[~self.mask, :] = 0
53
+ mask = self.mask.copy()
54
+
55
+ numerator = np.einsum('il->l',
56
+ np.expand_dims(self.image, -1)[mask, :] * pow(self.Membership[mask, :],
57
+ self.fuzziness))
58
+
59
+ denominator = np.einsum('il->l', pow(self.Membership[mask], self.fuzziness))
60
+ ind_non_denom = denominator != 0
61
+ numerator[ind_non_denom] = numerator[ind_non_denom] / denominator[ind_non_denom]
62
+ numerator[numerator == 0] = 0.00001
63
+ self.Centers = numerator
64
+ elif initialization_method=='otsu':
65
+ from skimage.filters import threshold_multiotsu, threshold_otsu
66
+ self.Centers = list(threshold_multiotsu(self.image[self.mask], classes=self.num_tissues+1))
67
+ el = -2. / (self.fuzziness - 1)
68
+
69
+ numerator = np.zeros((*self.image.shape, self.num_tissues))
70
+
71
+ for i in range(self.num_tissues):
72
+ numerator[self.mask, i] = np.power(abs(self.image[self.mask] - self.Centers[i])+1e-7, el)
73
+ #numerator[self.mask, i] = np.power(abs(self.image[self.mask] - self.Centers[i])+1e-7, el)
74
+
75
+ sumn = numerator.sum(-1)
76
+ ind_non_zero = sumn != 0
77
+ sumn = np.expand_dims(sumn, -1)
78
+ numerator[ind_non_zero, :] /= sumn[ind_non_zero, :]
79
+ self.Membership = numerator
80
+ self.Membership_freeB = numerator.copy()
81
+
82
+ elif initialization_method == 'kmeans':
83
+ from sklearn.cluster import KMeans
84
+ km = KMeans(self.num_tissues, random_state=0).fit(self.image[self.image > 0].reshape(-1, 1))
85
+ self.Centers = km.cluster_centers_.squeeze()
86
+ #idx = np.arange(self.num_gray)
87
+ #c_mesh, idx_mesh = np.meshgrid(self.Centers, idx)
88
+ el = -2. / (self.fuzziness - 1)
89
+
90
+ numerator = np.zeros((*self.image.shape, self.num_tissues))
91
+
92
+
93
+ for i in range(self.num_tissues):
94
+ numerator[self.mask>0, i] = np.power(abs(self.image[self.mask>0] - self.Centers[i]),el)
95
+
96
+ sumn = numerator.sum(-1)
97
+ ind_non_zero = sumn != 0
98
+ sumn = np.expand_dims(sumn, -1)
99
+ numerator[ind_non_zero, :] /= sumn[ind_non_zero, :]
100
+ self.Membership = numerator
101
+
102
+
103
+
104
+
105
+
106
+ class esFCM(FCM):
107
+
108
+ def __init__(self, image, affine,
109
+ image_range, num_tissues, fuzziness,
110
+ epsilon, max_iter,
111
+ padding=0,
112
+ tissuelabels=None, correct_bias=True,
113
+ mask=None, max_fail=4, use_ssim=True):
114
+ super(esFCM, self).__init__()
115
+ self.biascorrection = BiasCorrection()
116
+ self.use_ssim = use_ssim
117
+ self.mask = mask
118
+ self.image = image
119
+ self._imdim = [sh == 1 for sh in self.image.shape]
120
+ self._is2D = sum([sh == 1 for sh in self.image.shape])>0
121
+ self.max_fail = max_fail
122
+ self.window = create_window_3D(11, 1)
123
+
124
+ self.estimate = image.copy() # wstep
125
+ self.weight = image.copy() # wstep
126
+ self.type_im = 'T1'
127
+ self.image_range = image_range
128
+ self.num_tissues = num_tissues
129
+ self.fuzziness = fuzziness
130
+ self.padding = padding
131
+ self.epsilon = epsilon
132
+ self.max_iter = max_iter
133
+ self.correct_bias = correct_bias
134
+
135
+ self.shape = image.shape # image shape
136
+ # flatted image shape: (number of pixels,1)
137
+
138
+ self.affine = affine
139
+ self.biasfield = 1
140
+
141
+ if tissuelabels is not None:
142
+ self.tissuelabels = tissuelabels.astype('int')
143
+ else:
144
+ #
145
+ if self.num_tissues == 3:
146
+ self.tissuelabels = np.array([2, 3, 4])
147
+ else:
148
+ self.tissuelabels = np.zeros(self.num_tissues)
149
+
150
+ def SetBiasField(self, biasfield):
151
+ self.biasfield = biasfield
152
+
153
+ def Update_membership(self, constraint=True):
154
+ """
155
+ Updating FCM membership function
156
+ @param final:
157
+ @param membership_p:
158
+ @return:
159
+ """
160
+
161
+ el = -2. / (self.fuzziness - 1)
162
+
163
+ numerator = np.zeros_like(self.Membership)
164
+
165
+ for i in range(self.num_tissues):
166
+ weight = 1
167
+ numerator[self.mask, i] = weight * np.power(abs(self.filtered_image[self.mask] - self.Centers[i]) + 1e-7,
168
+ el)
169
+
170
+ sumn = numerator.sum(-1)
171
+ numerator[sumn != 0] = (numerator[sumn != 0]) / ((sumn[sumn != 0])[..., np.newaxis])
172
+
173
+ ind_non_zero_maks = self.mask == 1
174
+
175
+ mrf_energy = self._proximity_measure(ind_non_zero_maks, self.Membership)
176
+
177
+ numerator *= mrf_energy
178
+
179
+
180
+
181
+
182
+ return numerator
183
+
184
+
185
+ def Update_centers(self):
186
+ """
187
+ Update center of the clusters
188
+ @return:
189
+ """
190
+ mask = self.mask.copy()
191
+
192
+ numerator = np.einsum('il->l',
193
+ np.expand_dims(self.filtered_image, -1)[mask, :] * pow(self.Membership[mask, :],
194
+ self.fuzziness))
195
+ denominator = np.einsum('il->l', pow(self.Membership[mask], self.fuzziness))
196
+ ind_non_denom = denominator != 0
197
+ numerator[ind_non_denom] = numerator[ind_non_denom] / denominator[ind_non_denom]
198
+
199
+ numerator[numerator == 0] = 0.00001 # for numerical stability
200
+ return numerator
201
+
202
+ def WStep(self):
203
+ """
204
+ WStep
205
+ @return:
206
+ """
207
+
208
+ input_inp = self.image
209
+
210
+ a = self.predict()
211
+ uq = np.unique(a)
212
+ uq = [u for u in uq if u != 0]
213
+ pred = np.zeros((*a.shape, self.num_tissues))
214
+ for i, u in enumerate(uq):
215
+ ind = a == u
216
+ pred[ind, i] = 1
217
+
218
+ numstd = np.einsum('ijkl,ijkl->ijk', self.Membership, (input_inp[..., None] - self.Centers) ** 2)
219
+ denominator = np.sqrt(numstd)
220
+
221
+ numerator = np.einsum('ijkl,l', self.Membership, self.Centers) # +self.Membership*self.Centers
222
+
223
+ ind_non_zero = denominator != 0
224
+
225
+ self.weight[ind_non_zero] = denominator[ind_non_zero]
226
+ self.estimate[ind_non_zero] = numerator[ind_non_zero] # / denominator[ind_non_zero]
227
+
228
+ self.weight[(~ind_non_zero)] = self.padding
229
+ self.estimate[(~ind_non_zero)] = self.padding
230
+
231
+ def BStep(self, mask=None):
232
+ # bias correction step
233
+
234
+ if mask is None:
235
+ mask = self.mask
236
+
237
+ mask[~self.mask] = 0
238
+ self.biascorrection.set_info(target=self.image, reference=self.estimate,
239
+ weight=self.weight, biasfield=self.biasfield, padding=self.padding,
240
+ mask=mask, affine=self.affine, cov_pq=None, use_original=False)
241
+
242
+ self.filtered_image = self.image.copy()
243
+ if mask.sum() > 100:
244
+ self.biascorrection.Run()
245
+ self.biascorrection.Apply(self.filtered_image)
246
+ self.filtered_image[~self.mask] = 0
247
+ return
248
+
249
+
250
+ def _proximity_measure(self, index_, Membership=None, sqr2dist=False):
251
+ # Fuzzy c-means clustering with spatial information for image segmentation
252
+
253
+ if Membership is None:
254
+ Membership = self.Membership
255
+
256
+ in_out = np.zeros_like(Membership)
257
+ for i in range(self.num_tissues):
258
+ in_out[index_, i] = \
259
+ neighborhood_conv(Membership[..., i][..., None], kerenel_size=3, direction='xyz', sqr2dist=False)[
260
+ index_, 0]
261
+
262
+ in_out /= in_out.max()
263
+ return in_out
264
+
265
+
266
+ def softmax(self, x):
267
+ return np.exp(x) / np.sum(np.exp(x), -1)[..., None]
268
+
269
+
270
+
271
+ def fit(self, progressBar):
272
+
273
+ if not hasattr(self, 'Membership'):
274
+ self.Membership = self.atlas_ims.copy()
275
+
276
+ degree = 2
277
+
278
+ biasf = PolynomialFeatures(degree) # SplineTransformer(n_knots=2, degree=degree)#
279
+ best_cost = -np.inf
280
+ self.SetBiasField(biasf)
281
+ num_fails = 0
282
+ self.filtered_image = self.image.copy()
283
+ old_cost = np.inf
284
+
285
+ i = 0
286
+
287
+
288
+
289
+ while True:
290
+ # if i == 0:
291
+ self.Centers = self.Update_centers()
292
+
293
+ old_u = np.copy(self.Membership)
294
+ self.Membership = self.Update_membership()
295
+
296
+
297
+
298
+ cost = np.sum(abs(self.Membership - old_u) > 0.1) / np.prod(self.image[self.mask].shape)
299
+
300
+ progressBar.setValue(int(i / (self.max_iter + 1) * 100))
301
+ if self.use_ssim and cost < self.epsilon and self.correct_bias or abs(old_cost - cost) < 1e-6:
302
+ if not self.use_ssim:
303
+ break
304
+ self.WStep()
305
+
306
+ # Apply mapping
307
+
308
+ s1 = sobel(self.image)
309
+ s2 = sobel(self.predict())
310
+ fast_method = True
311
+ if fast_method:
312
+ if self._is2D:
313
+ cost_ssim, ssim_map = ssim(s1.squeeze() / s1.max(), s2.squeeze() / s2.max(), full=True,
314
+ win_size=11)
315
+ ssim_map = np.expand_dims(ssim_map, np.where(self._imdim)[0][0])
316
+ else:
317
+ cost_ssim, ssim_map = ssim(s1 / s1.max(), s2 / s2.max(), full=True,
318
+ win_size=11)
319
+ else: # faster
320
+ ssim_map = ssim3D(s1 / s1.max(), s2 / s2.max(), self.window,
321
+ self.window.shape[-1], 1, contrast=False)
322
+ cost_ssim = ssim_map[self.mask].mean()
323
+
324
+
325
+ ssim_map = rescale_between_a_b(-ssim_map, -1000, 1000)
326
+ ssim_map[~self.mask] = 0
327
+
328
+ if (cost_ssim - best_cost) > 1e-4:
329
+ print("best SSIM value {}".format(cost_ssim))
330
+
331
+ self.BestCenters = self.Centers.copy()
332
+ self.BestFilter = self.filtered_image.copy()
333
+ self.BestMS = self.Membership.copy()
334
+
335
+
336
+ best_cost = cost_ssim
337
+ num_fails = 0
338
+ else:
339
+ num_fails += 1
340
+
341
+ if num_fails > self.max_fail: # abs(old_cost_ssim - cost_ssim) < 1e-4
342
+ break
343
+ if num_fails == 0:
344
+
345
+ self.weight = ssim_map # rescale_between_a_b(sobel(self.image),-1,1) #ssim_map
346
+ self.BStep(mask=None)
347
+ else:
348
+ self.filtered_image = self.BestFilter.copy()
349
+
350
+
351
+ print("Iteration %d : cost = %f" % (i, cost))
352
+ old_cost = cost
353
+ if i > self.max_iter - 1:
354
+ break
355
+
356
+ # break
357
+ i += 1
358
+
359
+ ### Update with the best parameters
360
+ if self.use_ssim:
361
+ self.Centers = self.BestCenters
362
+ self.filtered_image = self.BestFilter
363
+
364
+ self.Membership = self.BestMS
365
+
366
+
367
+ sortedC = self.Centers.argsort()
368
+ sorted_el = [sortedC[i] for i in range(self.num_tissues)]
369
+ self.Membership = self.Membership[..., sorted_el]
370
+ self.Centers = self.Centers[sorted_el]
371
+ if self.num_tissues == 3:
372
+
373
+ if self.type_im=='T1': # T1
374
+ self.wmlabel = [sortedC[2].item()]
375
+ self.gmlabel = [sortedC[1].item()]
376
+ self.csflabel = [sortedC[0].item()]
377
+
378
+ elif self.num_tissues == 2:
379
+ self.wmlabel = [sortedC[1]]
380
+ self.gmlabel = [sortedC[0]]
381
+
382
+
383
+
384
+
385
+
386
+ def predict(self, use_softmax=False, Membership=None):
387
+ """
388
+ Segment image
389
+ @return:
390
+ """
391
+ if Membership is None:
392
+ Membership = self.Membership
393
+ if use_softmax:
394
+ MM = softmax(Membership, -1)
395
+ else:
396
+ MM = Membership
397
+
398
+ sumu = Membership.sum(-1)
399
+ ind_zero = sumu == 0
400
+ maxs = MM.argmax(-1) # defuzzify
401
+ self.output = maxs + 1
402
+ self.output[ind_zero] = 0
403
+ return self.output
404
+
405
+
406
+
407
+
408
+ class FCM_pure(FCM):
409
+ """
410
+ Fuzzy c-means clustering with spatial information for image segmentation: 2006
411
+ """
412
+ def __init__(self, image, affine, atlas,
413
+ image_range, num_tissues, fuzziness,
414
+ epsilon, max_iter,
415
+ padding=0, constraint=False, post_correction=True,mask =None):
416
+ super(FCM_pure).__init__()
417
+ self.biascorrection = BiasCorrection()
418
+
419
+ self.mask = mask
420
+
421
+ self.estimate = image.copy() # wstep
422
+ self.weight = image.copy() # wstep
423
+
424
+ self.image = rescale_between_a_b(image, 0, 1000)
425
+
426
+ self.image_range = image_range
427
+ self.num_tissues = num_tissues
428
+ self.fuzziness = fuzziness
429
+ self.padding = padding
430
+ self.post_correction = post_correction
431
+
432
+ self.epsilon = epsilon
433
+ self.constraint = constraint
434
+ self.max_iter = max_iter
435
+
436
+ self.atlas_ims = atlas
437
+ self.shape = image.shape # image shape
438
+ self.numPixels = image.size
439
+ self.affine = affine
440
+
441
+
442
+
443
+
444
+
445
+
446
+
447
+
448
+
449
+ def Update_memership(self):
450
+ '''Compute weights'''
451
+ # idx = np.arange(self.num_gray)
452
+ # c_mesh, idx_mesh = np.meshgrid(self.Centers, idx)
453
+ el = -2. / (self.fuzziness - 1)
454
+
455
+ numerator = np.zeros_like(self.Membership)
456
+
457
+ for i in range(self.num_tissues):
458
+ numerator[self.mask, i] = np.power(abs(self.image[self.mask] - self.Centers[i]) + 1e-7,
459
+ el)
460
+
461
+
462
+ sumn = numerator.sum(-1)
463
+ numerator[sumn != 0] = (numerator[sumn != 0]) / ((sumn[sumn != 0])[..., np.newaxis])
464
+
465
+ return numerator
466
+
467
+
468
+ def Update_centers(self):
469
+ """
470
+ Update center of the clusters
471
+ @return:
472
+ """
473
+ mask = self.mask.copy()
474
+
475
+ numerator = np.einsum('il->l', np.expand_dims(self.image, -1)[mask, :] * pow(self.Membership[mask, :],
476
+ self.fuzziness))
477
+
478
+ denominator = np.einsum('il->l', pow(self.Membership[mask,:], self.fuzziness))
479
+ ind_non_denom = denominator != 0
480
+ numerator[ind_non_denom] = numerator[ind_non_denom] / denominator[ind_non_denom]
481
+ numerator[numerator == 0] = 0.00001
482
+ return numerator
483
+
484
+
485
+
486
+
487
+ def fit(self, progressBar):
488
+ #if not hasattr(self, 'Membership'):
489
+ # self.Membership = self.atlas_ims.copy()
490
+
491
+ #self.last_seg = self.predict()
492
+
493
+
494
+ oldd = np.inf
495
+ i = 0
496
+ while True:
497
+
498
+ self.Centers = self.Update_centers()
499
+
500
+ old_u = np.copy(self.Membership)
501
+
502
+ self.Membership = self.Update_memership()
503
+
504
+ d = np.sum(abs(self.Membership - old_u) > 0.1) / np.prod(self.image[self.mask].shape)
505
+
506
+ print("Iteration %d : cost = %f" % (i, d))
507
+ progressBar.setValue(int(i/(self.max_iter+1)*100))
508
+ if d < self.epsilon or abs(oldd - d) < 1e-2:
509
+ break
510
+
511
+ oldd = d
512
+
513
+ i += 1
514
+
515
+
516
+ self.predict()
517
+
518
+ def predict(self, use_softmax=False):
519
+ """
520
+ Segment image
521
+ @return:
522
+ """
523
+ Membership = self.Membership
524
+ if use_softmax:
525
+ MM = softmax(Membership, -1)
526
+ else:
527
+ MM = Membership
528
+
529
+ sumu = Membership.sum(-1)
530
+ ind_zero = sumu == 0
531
+ maxs = MM.argmax(-1) # defuzzify
532
+ self.output = maxs + 1
533
+ self.output[ind_zero] = 0
534
+ return self.output
535
+
536
+
537
+
538
+
539
+ class Constrained_esFCM(FCM):
540
+
541
+ def __init__(self, image, affine, atlas,
542
+ image_range, num_tissues, fuzziness,
543
+ epsilon, max_iter,
544
+ padding=0, constraint=False,
545
+ tissuelabels=None, correct_bias=True, post_correction=True,
546
+ mask=None, max_fail=4, use_ssim=True, equalize=False):
547
+ super(Constrained_esFCM, self).__init__()
548
+ self.biascorrection = BiasCorrection()
549
+ self.use_ssim = use_ssim
550
+ self.mask = mask
551
+ self.max_fail = max_fail
552
+ self.window = create_window_3D(11, 1)
553
+
554
+ self.estimate = image.copy() # wstep
555
+ self.weight = image.copy() # wstep
556
+
557
+ if equalize:
558
+ from skimage import exposure
559
+ from melage.utils.utils import histogram_equalization
560
+ self.image = histogram_equalization(image)
561
+ else:
562
+ self.image = image
563
+
564
+ self.image_range = image_range
565
+ self.num_tissues = num_tissues
566
+ self.fuzziness = fuzziness
567
+ self.padding = padding
568
+ self.post_correction = post_correction
569
+ self.epsilon = epsilon
570
+ self.constraint = constraint
571
+ self.max_iter = max_iter
572
+ if self.constraint:
573
+ print('Neontal platform is activated')
574
+ else:
575
+ print('Neontal platform is deactivated')
576
+ self.correct_bias = correct_bias
577
+
578
+ self.atlas_ims = atlas # in case atlas image is provided
579
+ self.shape = image.shape # image shape
580
+ # flatted image shape: (number of pixels,1)
581
+
582
+ self.affine = affine
583
+ self.OriginalImage = image
584
+ if self.atlas_ims is not None:
585
+ self._normalizeAtlasCreateMask()
586
+ if self.constraint:
587
+ self.mask_sdf = compute_sdf(mask, bounded=False)
588
+ self.biasfield = 1
589
+
590
+ if tissuelabels is not None:
591
+ self.tissuelabels = tissuelabels.astype('int')
592
+ else:
593
+ #
594
+ if self.num_tissues == 3:
595
+ self.tissuelabels = np.array([2, 3, 4])
596
+ else:
597
+ self.tissuelabels = np.zeros(self.num_tissues)
598
+ old = True
599
+ if old:
600
+ self.outlabel = [l[0] for l in np.argwhere(self.tissuelabels == 1)]
601
+ self.csflabel = [l[0] for l in np.argwhere(self.tissuelabels == 2)]
602
+ self.gmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 3)]
603
+ self.wmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 4)]
604
+ self.dgmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 5)] # non cortical graymatter
605
+ self.venlabel = [l[0] for l in np.argwhere(self.tissuelabels == 6)]
606
+
607
+ self.cereblabel = []
608
+ self.bslabel = [] # brain stem
609
+ self.amyglabel = []
610
+
611
+ else:
612
+
613
+ self.csflabel = [l[0] for l in np.argwhere(self.tissuelabels == 1)]
614
+ self.gmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 2)]
615
+ self.wmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 3)]
616
+ self.outlabel = [l[0] for l in np.argwhere(self.tissuelabels == 4)]
617
+ self.venlabel = [l[0] for l in np.argwhere(self.tissuelabels == 5)]
618
+ self.cereblabel = [l[0] for l in np.argwhere(self.tissuelabels == 6)]
619
+ self.dgmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 7)] # non cortical graymatter
620
+ self.bslabel = [l[0] for l in np.argwhere(self.tissuelabels == 8)] # brain stem
621
+ self.amyglabel = [l[0] for l in np.argwhere(self.tissuelabels == 9)]
622
+
623
+ def SetBiasField(self, biasfield):
624
+ self.biasfield = biasfield
625
+
626
+ def Update_membership(self, constraint=True):
627
+ """
628
+ Updating FCM membership function
629
+ @param final:
630
+ @param membership_p:
631
+ @return:
632
+ """
633
+
634
+ el = -2. / (self.fuzziness - 1)
635
+
636
+ numerator = np.zeros_like(self.Membership)
637
+
638
+ ###########Compute weight ##########
639
+ a = self.predict()
640
+ uq = np.unique(a)
641
+ uq = [u for u in uq if u != 0]
642
+ pred = np.zeros((*a.shape, self.num_tissues))
643
+ for i, u in enumerate(uq):
644
+ ind = a == u
645
+ pred[ind, i] = 1
646
+
647
+ # numstd = np.einsum('ijkl,ijkl->ijk', pred, (self.image[..., None] - self.Centers) ** 2)
648
+ # weight = np.sqrt(numstd)
649
+
650
+ if self.atlas_ims is not None:
651
+ weight = self.atlas_ims
652
+ # weight = np.zeros_like(self.atlas_ims)
653
+ # weight = (fuzzy_weights+self.epsilon) / (fuzzy_weights.sum(-1) + self.epsilon)[..., np.newaxis]
654
+ # weight =np.exp(-(self.predict(Membership=self.atlas_ims)[...,np.newaxis] - np.arange(self.num_tissues))**2)
655
+ # weight = (fuzzy_weights + self.epsilon) / (fuzzy_weights.sum(-1) + self.epsilon)[..., np.newaxis]
656
+ # weight=1
657
+ else:
658
+ weight = 1
659
+ for i in range(self.num_tissues):
660
+ if constraint and self.atlas_ims is not None:
661
+ if i == 20 and self.num_tissues == 3:
662
+ weight = 1
663
+ else:
664
+ weight = self.atlas_ims[..., i]
665
+ weight = weight[self.mask]
666
+ else:
667
+ weight = 1
668
+ numerator[self.mask, i] = weight * np.power(abs(self.filtered_image[self.mask] - self.Centers[i]) + 1e-7,
669
+ el)
670
+ # numerator =(((self.filtered_image[..., np.newaxis] - self.Centers)+self.epsilon))**el
671
+ sumn = numerator.sum(-1)
672
+ numerator[sumn != 0] = (numerator[sumn != 0]) / ((sumn[sumn != 0])[..., np.newaxis])
673
+ # numerator[~self.mask, :] = 0
674
+ ind_non_zero_maks = self.mask == 1
675
+ # numerator*=rescale_between_a_b(self.weight[..., np.newaxis],0,1)
676
+ # if membership_p is None:
677
+ membership_p = numerator
678
+ if self.atlas_ims is not None:
679
+ mrf_energy = self._proximity_measure(ind_non_zero_maks, self.Membership)
680
+ # mrf_energy*=self.atlas_ims
681
+ # mrf_energy[...,[0,3,4,5]]*=self.atlas_ims[...,[0,3,4,5]]
682
+ # mrf_energy = np.ones_like(numerator)
683
+ # mrf_energy
684
+ # mrf_energy[..., [1, 2]] *= self.atlas_ims[..., [1, 2]]
685
+ # mrf_energy *= self._proximity_measure(ind_non_zero_maks, membership_p)
686
+ else:
687
+ mrf_energy = self._proximity_measure(ind_non_zero_maks, self.Membership)
688
+
689
+ numerator *= mrf_energy
690
+ if constraint:
691
+ # sumn = numerator.sum(-1)
692
+ # ind_non_zero = sumn != 0
693
+ # sumn = np.expand_dims(sumn, -1)
694
+ # numerator[ind_non_zero, :] /= sumn[ind_non_zero, :]
695
+ # pass
696
+ sumn = numerator.sum(-1)
697
+ numerator[sumn != 0] = (numerator[sumn != 0]) / ((sumn[sumn != 0])[..., np.newaxis])
698
+ # numerator*=self.atlas_ims
699
+ # numerator = 0.5*(numerator + self.atlas_ims)
700
+ # pass
701
+ # sumn = numerator.sum(-1)
702
+ # ind_non_zero = sumn != 0
703
+ # sumn = np.expand_dims(sumn, -1)
704
+ # numerator[ind_non_zero, :] /= sumn[ind_non_zero, :]
705
+ # if self.amyglabel is not None:
706
+ # numerator[...,self.amyglabel[0]] = self.atlas_ims[...,self.amyglabel[0]]
707
+
708
+ # numerator[..., [3, 5]] *= self.atlas_ims[..., [3, 5]]
709
+ # numerator *= self.atlas_ims
710
+ # numerator[..., [1, 2]] *= self.atlas_ims[..., [1, 2]]
711
+ # mrf_energy[..., [0, 2]] *= self.atlas_ims[..., [0, 2]]
712
+ # numerator[..., [self.csflabel[0]]] = self.atlas_ims[..., [self.csflabel[0]]]
713
+ # self.Membership = np.maximum.reduce([numerator, self.atlas_ims])
714
+ """
715
+ sumn = numerator.sum(-1)
716
+ ind_non_zero = sumn != 0
717
+ sumn = np.expand_dims(sumn, -1)
718
+ numerator[ind_non_zero, :] /= sumn[ind_non_zero, :]
719
+ """
720
+ return numerator
721
+
722
+ def Update_membership_old(self):
723
+ '''Compute weights'''
724
+ # idx = np.arange(self.num_gray)
725
+ # c_mesh, idx_mesh = np.meshgrid(self.Centers, idx)
726
+ el = -2. / (self.fuzziness - 1)
727
+
728
+ numerator = np.zeros_like(self.Membership)
729
+
730
+ for i in range(self.num_tissues):
731
+ numerator[self.mask, i] = np.power(abs(self.filtered_image[self.mask] - self.Centers[i]) + 1e-7, el)
732
+ # for j in range(self.num_tissues):
733
+ # numerator[self.mask,i]+=np.power(numi/abs(self.filtered_image[self.mask] - self.Centers[j]), power)
734
+ # denominator[i] = np.sum(abs(self.filtered_image[self.mask] - self.Centers[i]) ** power)
735
+ # if denominator[i]!=0:
736
+ # numerator[...,i]/= denominator[i]
737
+
738
+ # sumn = mrf_energy.sum(-1)
739
+ ##ind_non_zero = sumn != 0
740
+ # sumn = np.expand_dims(sumn, -1)
741
+ # mrf_energy[ind_non_zero, :] /= sumn[ind_non_zero, :]
742
+ ind_non_zero_maks = self.mask == 1
743
+
744
+ mrf_energy = self._proximity_measure(ind_non_zero_maks, self.Membership)
745
+
746
+ if self.constraint:
747
+ print(self.wmlabel, self.gmlabel)
748
+ if not self.constraint:
749
+ mrf_energy[..., [2]] *= self.atlas_ims[..., [2]] # just wm
750
+ # mrf_energy[...,[0,2]] *= self.atlas_ims[...,[0,2]]
751
+ numerator *= mrf_energy
752
+ if self.constraint:
753
+ numerator *= self.atlas_ims
754
+ # numerator[..., [0, 1,2,5]] *= self.atlas_ims[..., [0, 1,2,5]]
755
+ else:
756
+ numerator *= mrf_energy
757
+ sumn = numerator.sum(-1)
758
+ ind_non_zero = sumn != 0
759
+ sumn = np.expand_dims(sumn, -1)
760
+
761
+ numerator[ind_non_zero, :] /= sumn[ind_non_zero, :]
762
+ numerator *= self.atlas_ims
763
+
764
+ return numerator
765
+
766
+ def Update_centers(self):
767
+ """
768
+ Update center of the clusters
769
+ @return:
770
+ """
771
+ mask = self.mask.copy()
772
+
773
+ numerator = np.einsum('il->l',
774
+ np.expand_dims(self.filtered_image, -1)[mask, :] * pow(self.Membership[mask, :],
775
+ self.fuzziness))
776
+ denominator = np.einsum('il->l', pow(self.Membership[mask], self.fuzziness))
777
+ ind_non_denom = denominator != 0
778
+ numerator[ind_non_denom] = numerator[ind_non_denom] / denominator[ind_non_denom]
779
+
780
+ numerator[numerator == 0] = 0.00001 # for numerical stability
781
+ return numerator
782
+
783
+ def WStep(self):
784
+ """
785
+ WStep
786
+ @return:
787
+ """
788
+
789
+ input_inp = self.image
790
+
791
+ a = self.predict()
792
+ uq = np.unique(a)
793
+ uq = [u for u in uq if u != 0]
794
+ pred = np.zeros((*a.shape, self.num_tissues))
795
+ for i, u in enumerate(uq):
796
+ ind = a == u
797
+ pred[ind, i] = 1
798
+
799
+ numstd = np.einsum('ijkl,ijkl->ijk', self.Membership, (input_inp[..., None] - self.Centers) ** 2)
800
+ denominator = np.sqrt(numstd)
801
+ # self.Membership = (self.Membership) / ((self.Membership.sum(-1))[..., np.newaxis])
802
+ # self.Membership[~self.mask, :] = 0
803
+ numerator = np.einsum('ijkl,l', self.Membership, self.Centers) # +self.Membership*self.Centers
804
+
805
+ ind_non_zero = denominator != 0
806
+
807
+ self.weight[ind_non_zero] = denominator[ind_non_zero]
808
+ self.estimate[ind_non_zero] = numerator[ind_non_zero] # / denominator[ind_non_zero]
809
+
810
+ self.weight[(~ind_non_zero)] = self.padding
811
+ self.estimate[(~ind_non_zero)] = self.padding
812
+
813
+ def BStep(self, mask=None):
814
+ # bias correction step
815
+
816
+ if mask is None:
817
+ mask = self.mask
818
+
819
+ mask[~self.mask] = 0
820
+ self.biascorrection.set_info(target=self.image, reference=self.estimate,
821
+ weight=self.weight, biasfield=self.biasfield, padding=self.padding,
822
+ mask=mask, affine=self.affine, cov_pq=None, use_original=False)
823
+
824
+ self.filtered_image = self.OriginalImage.copy()
825
+ if mask.sum() > 100:
826
+ self.biascorrection.Run()
827
+ self.biascorrection.Apply(self.filtered_image)
828
+ self.filtered_image[~self.mask] = 0
829
+
830
+ return
831
+
832
+ def _normalizeAtlasCreateMask(self):
833
+ """
834
+ Normalizing atlas creation
835
+ @return:
836
+ """
837
+ self.atlas_ims[self.atlas_ims < 0] = 0
838
+ mask = self.atlas_ims.sum(-1)
839
+ mask_rep = np.repeat(np.expand_dims(mask, -1), (self.atlas_ims.shape[-1]), -1)
840
+ ind_positive = mask_rep > 0
841
+ self.atlas_ims[ind_positive] /= mask_rep[ind_positive] # mutual normalize between 0 and 1
842
+ self.atlas_ims[~ind_positive] = 0
843
+
844
+ def _csf_gm_bg_correction(self):
845
+ """
846
+ Correction for CSF, Gray Matter and Background
847
+ @return:
848
+ """
849
+ print('Correction for CSF BG GM using nearest neighbour method ...')
850
+ output_image = self.predict()
851
+
852
+ gm = output_image.copy()
853
+ label_gm = self.gmlabel[0] + 1
854
+ label_csf = self.csflabel[0] + 1
855
+ ind_csf = gm == label_csf
856
+ ind_gm = gm == label_gm
857
+
858
+ gmneighbourscsf = update_according_to_neighbours_conv(output_image, ind_gm, [self.csflabel[0] + 1], sign='+',
859
+ connectivity=6, kernel_size=3)
860
+
861
+ gmneighboursOut = update_according_to_neighbours_conv(output_image, ind_gm, [0], sign='+',
862
+ connectivity=6, kernel_size=3)
863
+
864
+ gmn = gmneighbourscsf + gmneighboursOut
865
+ ind = (gmneighbourscsf > 0) * (gmneighboursOut > 0)
866
+ self.Membership[(gmn >= 4), label_gm - 1] = 0
867
+ self.Membership[(gmn >= 4), label_csf - 1] = 1
868
+ self.Membership[ind, :] = 0
869
+ self.Membership[ind, label_csf - 1] = 1
870
+
871
+ def _proximity_measure(self, index_, Membership=None, sqr2dist=False):
872
+ # Fuzzy c-means clustering with spatial information for image segmentation
873
+ # sFCM
874
+ # invSpacing = 1. / self.spacing
875
+ in_out = np.ones_like(self.Membership)
876
+ if Membership is None:
877
+ Membership = self.Membership
878
+
879
+ in_out = np.zeros_like(Membership)
880
+ for i in range(self.num_tissues):
881
+ in_out[index_, i] = \
882
+ neighborhood_conv(Membership[..., i][..., None], kerenel_size=3, direction='xyz', sqr2dist=False)[
883
+ index_, 0]
884
+ # in_out /= 6
885
+
886
+ in_out /= in_out.max()
887
+ return in_out
888
+
889
+ def _reverse_prob(self, index, label1, label2):
890
+ """
891
+ Reversing the probability
892
+ @param index:
893
+ @param label1:
894
+ @param label2:
895
+ @return:
896
+ """
897
+ tmp1 = self.Membership[index, label1].copy()
898
+ tmp2 = self.Membership[index, label2].copy()
899
+ ind_max = tmp1 > tmp2
900
+ mins_vals = tmp1[~ind_max].copy()
901
+ tmp1[~ind_max] = tmp2[~ind_max]
902
+ tmp2[~ind_max] = mins_vals
903
+ self.Membership[index, label1] = tmp1 # max
904
+ self.Membership[index, label2] = tmp2
905
+
906
+ def _connection_between_bg_wm(self):
907
+ seg = self.predict()
908
+ if len(self.outlabel) <= 0:
909
+ return
910
+ index_bg_used = (seg == 0) + (seg == (self.outlabel[0] + 1))
911
+ index_bg_used = index_bg_used > 0
912
+ ind_wm = 0
913
+ for el in self.wmlabel:
914
+ ind_wm += seg == (el + 1)
915
+ ind_wm = ind_wm > 0
916
+
917
+ # index of all neighbours plus the center
918
+ ind_wm_neighbours = neighborhood_conv(ind_wm[..., None], kerenel_size=3,
919
+ direction='xyz', sqr2dist=False)[..., 0]
920
+
921
+ ind_bg_neighbours = \
922
+ neighborhood_conv(index_bg_used[..., None], kerenel_size=3,
923
+ direction='xyz', sqr2dist=False)[..., 0]
924
+ if len(self.venlabel) > 0:
925
+ ind_non_ventric = seg != (self.venlabel[0] + 1)
926
+ # neigbhour hould less than two should be something else
927
+ ind_common_bg_wm = (ind_wm_neighbours > 0) * (ind_bg_neighbours > 0) * (ind_wm) * (ind_non_ventric)
928
+ else:
929
+ ind_common_bg_wm = (ind_wm_neighbours > 0) * (ind_bg_neighbours > 0) * (ind_wm)
930
+ self.Membership[ind_common_bg_wm, :] = 0
931
+ self.Membership[ind_common_bg_wm, self.gmlabel[0]] = 1
932
+
933
+ def _connection_between_csf_wm(self, closing=True):
934
+ """
935
+ Correct the border between CSF and white matter
936
+ @param closing:
937
+ @return:
938
+ """
939
+ seg = self.predict()
940
+ if len(self.outlabel) > 0:
941
+ index_csf_used = (seg == (self.csflabel[0] + 1)).astype('int') + (seg == (self.outlabel[0] + 1)).astype(
942
+ 'int')
943
+ else:
944
+ index_csf_used = (seg == (self.csflabel[0] + 1)).astype('int') + (seg == 0).astype('int')
945
+ index_csf_used = index_csf_used > 0
946
+ ind_wm = 0
947
+ for el in self.wmlabel:
948
+ ind_wm += seg == (el + 1)
949
+ ind_wm = ind_wm > 0
950
+
951
+ # ind_gm = seg == (self.gmlabel[0] + 1)
952
+ # index_gm_used = ind_gm
953
+ # gms= compute_sdf(ind_gm, bounded=False)
954
+
955
+ """
956
+
957
+ wms= compute_sdf(ind_wm, bounded=False)
958
+ csfs = compute_sdf(index_csf_used, bounded=False)
959
+ ind_comon_wm_csf =(wms<=2)*(csfs<=0)*(csfs>=-4)*(wms>=0) * (self.mask_sdf > -4)
960
+ self._reverse_probs_new(ind_comon_wm_csf*ind_wm, self.wmlabel[0], self.gmlabel[0])
961
+ self._reverse_probs_new(ind_comon_wm_csf*index_csf_used, self.csflabel[0], self.gmlabel[0])
962
+ return
963
+ """
964
+ # (gms>=0)*(gms<=1)
965
+ # index of all neighbours plus the center
966
+ ind_wm_neighbours = neighborhood_conv(ind_wm[..., None], kerenel_size=3,
967
+ direction='xyz', sqr2dist=False)[..., 0]
968
+
969
+ ind_csf_neighbours = \
970
+ neighborhood_conv(index_csf_used[..., None], kerenel_size=3,
971
+ direction='xyz', sqr2dist=False)[..., 0]
972
+ if len(self.venlabel) > 0:
973
+ ind_non_ventric = seg != (self.venlabel[0] + 1)
974
+ # neigbhour hould less than two should be something else
975
+ ind_common_csf_wm = (ind_wm_neighbours > 0) * (ind_csf_neighbours > 0) * (ind_wm) * (
976
+ ind_non_ventric) # * (self.mask_sdf > -2)
977
+ else:
978
+ ind_common_csf_wm = (ind_wm_neighbours > 0) * (ind_csf_neighbours > 0) * (ind_wm) # * (self.mask_sdf > -2)
979
+ # ind_common_csf_wm = (ind_wm_neighbours > 0) * (ind_csf_neighbours > 0) * (ind_wm) * (self.mask_sdf > -2)
980
+ ind_common_csf_wm = binary_dilation(ind_common_csf_wm)
981
+ if closing:
982
+ self._reverse_prob(ind_common_csf_wm, self.gmlabel[0], self.wmlabel[0])
983
+ else:
984
+ self._reverse_prob(ind_common_csf_wm, self.csflabel[0], self.wmlabel[0])
985
+
986
+ def _remove_extra_wm(self, Membership=None, soft=False):
987
+ """
988
+ Remove extra white matter ...
989
+ @param total:
990
+ @param soft:
991
+ @return:
992
+ """
993
+ if Membership is None:
994
+ Membership = self.Membership
995
+
996
+ try:
997
+ seg = self.predict(Membership=Membership)
998
+ index_0 = seg == (self.csflabel[0] + 1)
999
+ if len(self.outlabel) > 0:
1000
+ index_0 += seg == (self.outlabel[0] + 1)
1001
+ index_0 += seg == 0
1002
+ csf_out_zero = 300
1003
+ seg[index_0 > 0] = csf_out_zero
1004
+ index_csf_out_bg = index_0 > 0
1005
+ ind_wm = 0
1006
+ for el in self.wmlabel:
1007
+ ind_wm += seg == (el + 1)
1008
+ ind_wm = ind_wm > 0
1009
+ cc, cc_f = LargestCC(ind_wm, 1)
1010
+ ind_wm_lcc = 0
1011
+ ind_low_wm = np.argwhere(cc_f <= cc_f[cc_f.argsort()[-2]] * 0.05)
1012
+ ind_high_wm = np.argwhere(cc_f > cc_f[cc_f.argsort()[-2]] * 0.05)
1013
+ if len(ind_high_wm) < len(ind_low_wm):
1014
+ ind_non_wm = 0
1015
+ for i in ind_high_wm:
1016
+ ind_non_wm += cc == i
1017
+ ind_wm_lcc = (~(ind_non_wm > 0))
1018
+ else:
1019
+ for i in ind_low_wm:
1020
+ ind_wm += cc == i
1021
+ ind_wm_lcc = ind_wm > 0
1022
+ # ind_wm = seg == (self.wmlabel[0] + 1)
1023
+ ind_wm_neighbours = \
1024
+ neighborhood_conv(ind_wm_lcc[..., None], kerenel_size=3,
1025
+ direction='xyz', sqr2dist=False)[..., 0]
1026
+
1027
+ index_csf_new = (ind_wm_neighbours > 1) * (~index_csf_out_bg)
1028
+
1029
+ a1 = axis_based_convolution(ind_wm.astype('int'), kernel_size=3)
1030
+ gmlbl = self.gmlabel[0] + 1
1031
+ # csflbl = self.csflabel[0] + 1
1032
+ csfs_new = np.zeros_like(seg)
1033
+ try:
1034
+ indx_l = a1[..., 0] > 0
1035
+ indx_r = a1[..., 1] > 0
1036
+ csfs_new[ind_wm] += ((seg[indx_l] == gmlbl) * (seg[indx_r] == csf_out_zero)) + (
1037
+ (seg[indx_l] == csf_out_zero) * (seg[indx_r] == gmlbl)) + (
1038
+ (seg[indx_l] == csf_out_zero) * (seg[indx_r] == csf_out_zero))
1039
+ except:
1040
+ pass
1041
+ try:
1042
+ indy_l = a1[..., 2] > 0
1043
+ indy_r = a1[..., 3] > 0
1044
+ csfs_new[ind_wm] += ((seg[indy_l] == gmlbl) * (seg[indy_r] == csf_out_zero)) + (
1045
+ (seg[indy_l] == csf_out_zero) * (seg[indy_r] == gmlbl)) + (
1046
+ (seg[indy_l] == csf_out_zero) * (seg[indy_r] == csf_out_zero))
1047
+ except:
1048
+ pass
1049
+ try:
1050
+ indz_l = a1[..., 4] > 0
1051
+ indz_r = a1[..., 5] > 0
1052
+ csfs_new[ind_wm] += ((seg[indz_l] == gmlbl) * (seg[indz_r] == csf_out_zero)) + (
1053
+ (seg[indz_l] == csf_out_zero) * (seg[indz_r] == gmlbl)) + (
1054
+ (seg[indz_l] == csf_out_zero) * (seg[indz_r] == csf_out_zero))
1055
+ except:
1056
+ pass
1057
+ index_csf_new = (csfs_new.astype('int') + index_csf_new.astype('int')) > 0
1058
+ for el2 in self.wmlabel:
1059
+ Membership[index_csf_new, el2] *= 0.1
1060
+
1061
+ Membership[index_csf_new] = (
1062
+ neighborhood_conv(Membership, kerenel_size=3, direction='xyz', sqr2dist=False)[
1063
+ index_csf_new] / 6)
1064
+
1065
+ return index_csf_new
1066
+ except:
1067
+ return None
1068
+
1069
+ def _get_index_label(self, seg, label):
1070
+ ind_lbl = 0
1071
+ for el in label:
1072
+ ind_lbl += seg == (el + 1)
1073
+ ind_lbl = ind_lbl > 0
1074
+ return ind_lbl
1075
+
1076
+ def _binary_fill_holes_lcc(self, index, threshold=3):
1077
+ segl, segl_f = LargestCC(index)
1078
+ if len(segl_f) > 2:
1079
+ argmax_gmf = np.argsort(segl_f)[-2]
1080
+ else:
1081
+ argmax_gmf = 1
1082
+ index_used = (segl != 0) * (segl != argmax_gmf)
1083
+ index_used_filled = binary_fill_holes(index_used) > 0
1084
+ index_remain = (index_used_filled.astype('int') - index_used.astype('int')) > 0
1085
+ segl_f_remove = np.argwhere(segl_f <= threshold)
1086
+ segl_f_keep = np.argwhere(segl_f > threshold)
1087
+
1088
+ if len(segl_f_keep) < len(segl_f_remove):
1089
+ shouldbe_kept = 0
1090
+ for el in segl_f_keep:
1091
+ shouldbe_kept += (segl == el).astype('int')
1092
+ shouldbe_removed = ~(shouldbe_kept > 0)
1093
+ else:
1094
+ shouldbe_removed = 0
1095
+ for el in segl_f_remove:
1096
+ if el == 0:
1097
+ continue
1098
+ shouldbe_removed += (segl == el).astype('int')
1099
+ if type(shouldbe_removed) == int:
1100
+ shouldbe_removed = np.zeros_like(index_used) > 0
1101
+ else:
1102
+ shouldbe_removed = shouldbe_removed > 0
1103
+ return index_remain, shouldbe_removed
1104
+
1105
+ def _neighbours(self, index):
1106
+ ind_neighbours = \
1107
+ neighborhood_conv(index[..., None], kerenel_size=3,
1108
+ direction='xyz', sqr2dist=False)[..., 0]
1109
+ return ind_neighbours
1110
+
1111
+ def softmax(self, x):
1112
+ return np.exp(x) / np.sum(np.exp(x), -1)[..., None]
1113
+
1114
+ def _remove_common_structures(self, threshold=5):
1115
+ seg = self.predict()
1116
+ concat1 = []
1117
+ concat2 = []
1118
+ neigbs = np.zeros((*self.image.shape, self.Membership.shape[-1]))
1119
+ if len(self.wmlabel) > 0:
1120
+ ind_wm = self._get_index_label(seg, self.wmlabel)
1121
+ ind_wm_cc, ind_wm_extra = self._binary_fill_holes_lcc(ind_wm, threshold=threshold)
1122
+ neigbs[..., self.wmlabel[0]] = self._neighbours(ind_wm)
1123
+ concat1.append(ind_wm_extra)
1124
+ concat2.append(ind_wm_cc)
1125
+ if len(self.gmlabel) > 0:
1126
+ ind_gm = self._get_index_label(seg, self.gmlabel)
1127
+ ind_gm_cc, ind_gm_extra = self._binary_fill_holes_lcc(ind_gm, threshold=threshold)
1128
+ neigbs[..., self.gmlabel[0]] = self._neighbours(ind_gm)
1129
+ concat1.append(ind_gm_extra)
1130
+ concat2.append(ind_gm_cc)
1131
+ if len(self.csflabel) > 0:
1132
+ if len(self.outlabel) > 0:
1133
+ ind_csf = self._get_index_label(seg, self.csflabel + self.outlabel)
1134
+ else:
1135
+ ind_csf = self._get_index_label(seg, self.csflabel)
1136
+ ind_csf_cc, ind_csf_extra = self._binary_fill_holes_lcc(ind_csf, threshold=threshold)
1137
+ neigbs[..., self.csflabel[0]] = self._neighbours(ind_csf)
1138
+ concat1.append(ind_csf_extra)
1139
+ concat2.append(ind_csf_cc)
1140
+ if len(self.dgmlabel) > 0:
1141
+ ind_dgm = self._get_index_label(seg, self.dgmlabel)
1142
+ ind_dgm_cc, ind_dgm_extra = self._binary_fill_holes_lcc(ind_dgm, threshold=threshold)
1143
+ neigbs[..., self.gmlabel[0]] = self._neighbours(ind_dgm)
1144
+ concat1.append(ind_dgm_extra)
1145
+ concat2.append(ind_dgm_cc)
1146
+ if len(self.venlabel) > 0:
1147
+ ind_ven = self._get_index_label(seg, self.venlabel)
1148
+ ind_ven_cc, ind_ven_extra = self._binary_fill_holes_lcc(ind_ven, threshold=20)
1149
+ neigbs[..., self.venlabel[0]] = self._neighbours(ind_ven)
1150
+ concat1.append(ind_ven_extra)
1151
+ concat2.append(ind_ven_cc)
1152
+
1153
+ neigbssf = self.softmax(neigbs)
1154
+ for indice in concat1:
1155
+ self.Membership[indice, :] = neigbssf[indice, :]
1156
+ for indice in concat2:
1157
+ self.Membership[indice, :] = neigbssf[indice, :]
1158
+
1159
+ def _remove_small_structures(self, label, threshold_percent=0.5, Membership=None):
1160
+ if Membership is None:
1161
+ Membership = self.Membership
1162
+ ### REMOVE SMALL STRUCTURES
1163
+ seg = self.predict()
1164
+ if len(label) == 0:
1165
+ return
1166
+ ind_lbl = 0
1167
+ for el in label:
1168
+ ind_lbl += seg == (el + 1)
1169
+ ind_lbl = ind_lbl > 0
1170
+
1171
+ segl, segl_f = LargestCC(ind_lbl, 1)
1172
+ if len(segl_f) > 2:
1173
+ segl, segl_f = LargestCC(ind_lbl, 1)
1174
+ if len(segl_f) > 2:
1175
+ argmax_gmf = np.argsort(segl_f)[-2]
1176
+ else:
1177
+ argmax_gmf = 1
1178
+ """
1179
+
1180
+ index_total = 0
1181
+ max_v = ind_lbl.sum()/ind_lbl.shape[0]
1182
+ ind_remove = np.zeros_like(ind_lbl)
1183
+ for sh in range(ind_lbl.shape[0]):
1184
+ if ind_lbl[sh,...].sum()<0.05*max_v:
1185
+ continue
1186
+ segl, segl_f = LargestCC(ind_lbl[sh,...],1)
1187
+ if len(segl_f) > 2:
1188
+ argmax_gmf = np.argsort(segl_f)[-2]
1189
+ else:
1190
+ argmax_gmf = 1
1191
+ segl_f_remove = np.argwhere(segl_f != segl_f[argmax_gmf])
1192
+ shouldbe_removed = 0
1193
+ for el in segl_f_remove:
1194
+ if el.all() == 0:
1195
+ continue
1196
+ shouldbe_removed += (segl == el).astype('int')
1197
+ ind_remove[sh,...] = shouldbe_removed
1198
+ """
1199
+ ind_remove = (segl != argmax_gmf) * (segl != 0)
1200
+ # segl_f_remove = np.argwhere(ind_remove)
1201
+ index_use = ind_remove > 0
1202
+ Membership[index_use, label[0]] = 0
1203
+
1204
+ Membership[index_use] = (
1205
+ neighborhood_conv(Membership, kerenel_size=3, direction='xyz', sqr2dist=False)[
1206
+ index_use] / 6)
1207
+ return index_use
1208
+ else:
1209
+ return (ind_lbl * 0) > 0
1210
+
1211
+ def set_tissue_labels(self):
1212
+ self.tissuelabels = np.zeros(self.num_tissues)
1213
+
1214
+ def _wm_touch_csf_out(self, outval, csfval, gmval, wmval, ind_wm_gm_csfout, lambda_val):
1215
+ # if is a wm voxel that touches (outlier or csf) and gm -> csf, gm
1216
+
1217
+ sum_gm_csf = csfval + gmval
1218
+ ind_wm_gm_csfout_no_zero = (sum_gm_csf != 0) * ind_wm_gm_csfout
1219
+ # for non zero pixels
1220
+ gmval[ind_wm_gm_csfout_no_zero] += (1 - lambda_val) * wmval[ind_wm_gm_csfout_no_zero] * (
1221
+ gmval[ind_wm_gm_csfout_no_zero] / sum_gm_csf[ind_wm_gm_csfout_no_zero])
1222
+
1223
+ csfval[ind_wm_gm_csfout_no_zero] += (1 - lambda_val) * wmval[ind_wm_gm_csfout_no_zero] * (
1224
+ csfval[ind_wm_gm_csfout_no_zero] / sum_gm_csf[ind_wm_gm_csfout_no_zero])
1225
+
1226
+ # for zero pixels
1227
+ ind_wm_gm_csfout_zero = (sum_gm_csf == 0) * (ind_wm_gm_csfout)
1228
+ gmval[ind_wm_gm_csfout_zero] += (1 - lambda_val) * wmval[ind_wm_gm_csfout_zero] * 0.5
1229
+ csfval[ind_wm_gm_csfout_zero] += (1 - lambda_val) * wmval[ind_wm_gm_csfout_zero] * 0.5
1230
+
1231
+ # after that
1232
+ wmval[ind_wm_gm_csfout] *= lambda_val
1233
+ return [outval, csfval, gmval, wmval]
1234
+
1235
+
1236
+
1237
+ def adjust_membership(self, Membership, threshold=None):
1238
+ # self.cereblabel = [l[0] for l in np.argwhere(self.tissuelabels == 6)]
1239
+ # self.dgmlabel = [l[0] for l in np.argwhere(self.tissuelabels == 7)] # non cortical graymatter
1240
+ # self.bslabel = [l[0] for l in np.argwhere(self.tissuelabels == 8)] # brain stem
1241
+ # self.amyglabel = [l[0] for l in np.argwhere(self.tissuelabels == 9)]
1242
+ # self.venlabel = [l[0] for l in np.argwhere(self.tissuelabels == 5)]
1243
+ seg = self.predict()
1244
+ remain_index = 0
1245
+ index_used_filleds = []
1246
+ for el in self.dgmlabel + self.amyglabel + self.bslabel + self.venlabel + self.cereblabel:
1247
+ index = seg == el + 1
1248
+ # index_used_filled = binary_dilation(index)
1249
+
1250
+ segl, segl_f = LargestCC(index, 1)
1251
+ if len(segl_f) > 2:
1252
+ argmax_gmf = [np.argsort(segl_f)[-2]]
1253
+ else:
1254
+ argmax_gmf = [1]
1255
+ if el == 9: # Amygdala
1256
+ argmax_gmf = [np.argsort(segl_f)[-2], np.argsort(segl_f)[-3]]
1257
+
1258
+ indx = 0
1259
+ for maxf in argmax_gmf:
1260
+ indx += (segl == maxf)
1261
+ index_used = (segl != 0) * indx > 0
1262
+
1263
+ index_used_filled = binary_fill_holes(index_used) > 0
1264
+ m = Membership[..., el]
1265
+ m[index_used_filled] = np.clip(Membership[index_used_filled, :].max(-1) + 0.1, 0, 1)
1266
+ Membership[..., el] = m
1267
+ # Membership[index_used_filled, el] = np.clip(Membership[index_used_filled,:].max(-1)+0.1,0,1)
1268
+
1269
+ index_used_filleds.append([index_used_filled, el])
1270
+
1271
+ remain_ind = (index.astype('int') - index_used_filled.astype('int')) > 0
1272
+ Membership[remain_ind, el] = 0
1273
+ remain_index += remain_ind
1274
+ Membership[remain_index > 0] = (
1275
+ neighborhood_conv(Membership, kerenel_size=3, direction='xyz', sqr2dist=False)[
1276
+ remain_index > 0] / 6)
1277
+
1278
+ return remain_index > 0, index_used_filleds
1279
+
1280
+ def _reverse_probs_new(self, ind_revise, label1, label2, exclude_largest=False):
1281
+ if exclude_largest:
1282
+ segl, segl_f = LargestCC(ind_revise, 1)
1283
+ if len(segl_f) > 2:
1284
+ argmax_gmf = [np.argsort(segl_f)[-2]]
1285
+ else:
1286
+ argmax_gmf = [1]
1287
+ indx = 0
1288
+ for maxf in argmax_gmf:
1289
+ indx += (segl == maxf)
1290
+ index_used = (segl != 0) * indx > 0
1291
+ remain_ind = (ind_revise.astype('int') - index_used.astype('int')) > 0
1292
+ else:
1293
+ remain_ind = ind_revise
1294
+ indices = np.where(remain_ind > 0)
1295
+
1296
+ m = self.Membership[indices[0], indices[1], indices[2], label1].copy()
1297
+ m2 = self.Membership[indices[0], indices[1], indices[2], label2]
1298
+
1299
+ self.Membership[indices[0], indices[1], indices[2], label2] = m
1300
+ self.Membership[indices[0], indices[1], indices[2], label1] = m2
1301
+
1302
+ def correct_wm_csf_gm(self):
1303
+ summation = 0
1304
+ seg = self.predict()
1305
+ ind_wm = seg == self.wmlabel[0] + 1
1306
+ # ind_csf = seg == self.csflabel[0] + 1
1307
+ ind_gm = seg == self.gmlabel[0] + 1
1308
+ gms = compute_sdf(ind_gm, bounded=False)
1309
+ spacing = 0.5 # self.header['pixdim'][1]
1310
+ segl, segl_f = LargestCC(ind_wm, 1)
1311
+ if len(segl_f) > 2:
1312
+ argmax_gmf = [np.argsort(segl_f)[-2], np.argsort(segl_f)[-3]]
1313
+ else:
1314
+ argmax_gmf = 1
1315
+ ind_wm2 = (segl != argmax_gmf[0]) * (segl > 0) * (segl != argmax_gmf[1])
1316
+ wm2 = compute_sdf(ind_wm2, bounded=False)
1317
+ # contamination of white matter in gray matter
1318
+ ind_revise_wm_gm = (((gms >= 0) * (gms <= 1) * (wm2 <= 1) * ind_wm))
1319
+ summation += ind_revise_wm_gm.sum()
1320
+ if summation != 0:
1321
+ self._reverse_probs_new(ind_revise_wm_gm, self.wmlabel[0], self.csflabel[0])
1322
+ seg = self.predict()
1323
+ ind_wm = seg == self.wmlabel[0] + 1
1324
+
1325
+ cc, cc_f = LargestCC(ind_wm, 1)
1326
+ if len(cc_f) > 2:
1327
+ sorted_f = np.argsort(cc_f)
1328
+ argmax_g = [sorted_f[-2], sorted_f[-3]]
1329
+ else:
1330
+ argmax_g = [0, 0]
1331
+ # ind_wm_larg = ((cc==argmax_g[0]).astype('int')+(cc==argmax_g[1]).astype('int'))>0
1332
+ # remain_wm = (ind_wm.astype('int')-ind_wm_larg.astype('int'))>0
1333
+ if len(self.csflabel) > 0 and 1 > 2:
1334
+ ind_ = (seg == self.csflabel[0] + 1).astype('int')
1335
+ if len(self.outlabel) > 0:
1336
+ ind_ += (seg == self.outlabel[0] + 1).astype('int')
1337
+ ind_csf = (ind_) > 0
1338
+ # ind_gm = seg == self.gmlabel[0] + 1
1339
+
1340
+ ind_rest = (seg != 0).astype('int') - (ind_csf.astype('int') + ind_gm.astype('int') + ind_wm.astype('int'))
1341
+ # gms = compute_sdf(ind_gm, bounded=False)
1342
+ wms = compute_sdf(ind_wm, bounded=False)
1343
+ csfs = compute_sdf(ind_csf, bounded=False)
1344
+ rest = compute_sdf(ind_rest, bounded=False)
1345
+ ind_revise_wm_csf = ((csfs <= 0) * (
1346
+ (csfs >= -3) * (wms >= 0) *
1347
+ (wms <= 2) * (self.mask_sdf > -10) * (self.mask_sdf <= -3) * (rest > 5) * ind_csf))
1348
+ ind_revise_wm_csf = (ind_revise_wm_csf.astype('int') - ind_revise_wm_gm.astype('int')) > 0
1349
+ ind_revise_wm_csf *= (seg == self.csflabel[0] + 1)
1350
+ self._reverse_probs_new(ind_revise_wm_csf * ind_wm, self.wmlabel[0], self.csflabel[0])
1351
+ self._reverse_probs_new(ind_revise_wm_csf * ind_csf, self.csflabel[0], self.gmlabel[0])
1352
+ summation += ind_revise_wm_csf.sum()
1353
+ # self._reverse_probs_new(ind_revise_wm_csf, self.wmlabel[0], self.csflabel[0])
1354
+ return summation
1355
+
1356
+ def _correction_wm(self):
1357
+ cc, cc_f = LargestCC(self.predict() == self.wmlabel[0] + 1, 1)
1358
+ if len(cc_f) > 2:
1359
+ argm = cc_f.argsort()[-2]
1360
+ argms = np.argwhere(cc_f > 0.05 * cc_f[argm]).squeeze()
1361
+ for a in argms:
1362
+ cc[cc == a] = 0
1363
+ A = self.Membership[..., self.wmlabel]
1364
+ A[cc > 0] = 0
1365
+ self.Membership[..., self.wmlabel] = A
1366
+
1367
+ def fit(self, progressBar):
1368
+
1369
+ # ind_common_csf_dgm = ((self.atlas_ims[..., 3] > 0.1) * (self.atlas_ims[..., 0] > 0.1))
1370
+ # self.atlas_ims[ind_common_csf_dgm, self.csflabel[0]] *= 0.1
1371
+ if not hasattr(self, 'Membership') or self.constraint:
1372
+ self.Membership = self.atlas_ims.copy()
1373
+
1374
+ degree = 2
1375
+ max_degree = 2
1376
+ biasf = PolynomialFeatures(degree) # SplineTransformer(n_knots=2, degree=degree)#
1377
+ best_cost = -np.inf
1378
+ self.SetBiasField(biasf)
1379
+ num_fails = 0
1380
+ self.filtered_image = self.image.copy()
1381
+ old_cost = np.inf
1382
+ old_cost_ssim = np.inf
1383
+ i = 0
1384
+ # self.Centers = self.Update_centers()
1385
+
1386
+ # self.Membership = self.Update_membership(constraint=False)
1387
+ # self.WStep()
1388
+ # self.filtered_image = rescale_between_a_b(self.weight, 0, 1000).copy()
1389
+ # self.filtered_image = rescale_between_a_b(self.filtered_image+gaussian_filter(self.filtered_image,2),0,1000)
1390
+ # self.filtered_image[~self.mask]=0
1391
+ # a = neighborhood_conv(self.filtered_image[..., np.newaxis]).squeeze()
1392
+ ssim_map = None
1393
+ # alphas = np.linspace(0.3,1,self.max_iter)
1394
+ while True:
1395
+ # if i == 0:
1396
+ self.Centers = self.Update_centers()
1397
+
1398
+ old_u = np.copy(self.Membership)
1399
+ self.Membership = self.Update_membership()
1400
+
1401
+ if self.constraint:
1402
+ self.adjust_membership(self.Membership)
1403
+
1404
+ cost = np.sum(abs(self.Membership - old_u) > 0.1) / np.prod(self.image[self.mask].shape)
1405
+
1406
+ progressBar.setValue(int(i / (self.max_iter + 1) * 100))
1407
+ if self.use_ssim and cost < self.epsilon and self.correct_bias or abs(old_cost - cost) < 1e-6:
1408
+ if not self.use_ssim:
1409
+ break
1410
+ self.WStep()
1411
+
1412
+ # Apply mapping
1413
+
1414
+ s1 = sobel(self.image)
1415
+ s2 = sobel(self.predict())
1416
+ #ssim_map = ssim3D(s1 / s1.max(), s2 / s2.max(), self.window,
1417
+ # self.window.shape[-1], 1, contrast=True)
1418
+ #cost_ssim = ssim_map[self.mask].mean()
1419
+ from skimage.metrics import structural_similarity as ssim
1420
+ cost_ssim, ssim_map = ssim(s1 / s1.max(), s2 / s2.max(), full=True,
1421
+ win_size=11)
1422
+
1423
+ ssim_map = rescale_between_a_b(-ssim_map, -1000, 1000)
1424
+ ssim_map[~self.mask] = 0
1425
+
1426
+ if (cost_ssim - best_cost) > 1e-4:
1427
+ print("best SSIM value {}".format(cost_ssim))
1428
+ summation_new = np.inf
1429
+
1430
+ if self.constraint:
1431
+ summation_new = self.correct_wm_csf_gm()
1432
+ # changed_index = self._remove_extra_wm(Membership=self.Membership)
1433
+ # if changed_index is not None:
1434
+ # self.atlas_ims[changed_index, :] = self.Membership[changed_index, :]
1435
+ changed_index, index_changed_el = self.adjust_membership(self.Membership, threshold=None)
1436
+ for [indx, el] in index_changed_el:
1437
+ self.atlas_ims[indx, el] = self.Membership[indx, el]
1438
+ self.atlas_ims[changed_index, :] = self.Membership[changed_index, :]
1439
+ # changed_index = self._remove_small_structures(self.gmlabel, Membership=self.Membership)
1440
+ # self.atlas_ims[changed_index, :] = self.Membership[changed_index, :]
1441
+ # self.atlas_ims[...,0] = self.Membership[...,0].copy()
1442
+ self.BestCenters = self.Centers.copy()
1443
+ self.BestFilter = self.filtered_image.copy()
1444
+ self.BestMS = self.Membership.copy()
1445
+ if self.atlas_ims is not None:
1446
+ self.Membership = self.atlas_ims.copy()
1447
+
1448
+ best_cost = cost_ssim
1449
+ num_fails = 0
1450
+ else:
1451
+ num_fails += 1
1452
+
1453
+ if num_fails > self.max_fail: # abs(old_cost_ssim - cost_ssim) < 1e-4
1454
+ break
1455
+ if num_fails == 0:
1456
+
1457
+ self.weight = ssim_map # rescale_between_a_b(sobel(self.image),-1,1) #ssim_map
1458
+ self.BStep(mask=None)
1459
+ else:
1460
+ self.filtered_image = self.BestFilter.copy()
1461
+ # self.Membership = self.BestMS.copy()
1462
+
1463
+ old_cost_ssim = cost_ssim
1464
+
1465
+ # self.huiPVCorrection()
1466
+ # self._remove_common_structures(threshold=3)
1467
+
1468
+ print("Iteration %d : cost = %f" % (i, cost))
1469
+ old_cost = cost
1470
+ if i > self.max_iter - 1:
1471
+ break
1472
+
1473
+ # break
1474
+ i += 1
1475
+
1476
+ ### Update with the best parameters
1477
+ if self.use_ssim:
1478
+ self.Centers = self.BestCenters
1479
+ self.filtered_image = self.BestFilter
1480
+
1481
+ self.Membership = self.BestMS
1482
+
1483
+ # if degree==max_degree and not self.constraint:
1484
+ if not self.constraint:
1485
+ sortedC = self.Centers.argsort()
1486
+ sorted_el = [sortedC[i] for i in range(self.num_tissues)]
1487
+ self.Membership = self.Membership[..., sorted_el]
1488
+ self.Centers = self.Centers[sorted_el]
1489
+ if self.num_tissues == 3:
1490
+
1491
+ if len(self.csflabel) > 0: # T1
1492
+ self.wmlabel = [sortedC[2].item()]
1493
+ self.gmlabel = [sortedC[1].item()]
1494
+ self.csflabel = [sortedC[0].item()]
1495
+
1496
+ elif self.num_tissues == 2:
1497
+ self.wmlabel = [sortedC[1]]
1498
+ self.gmlabel = [sortedC[0]]
1499
+ else:
1500
+ pass
1501
+ # if self.num_tissues==3:
1502
+ # sortedC = self.Centers.argsort()
1503
+ # self.Membership = self.Membership[..., [sortedC[0], sortedC[2], sortedC[1]]]
1504
+ # self.Centers = self.Centers[[sortedC[0], sortedC[2], sortedC[1]]]
1505
+ # if len(self.csflabel) > 0: # T1
1506
+ # self.wmlabel = [sortedC[2].item()]
1507
+ # self.gmlabel = [sortedC[1].item()]
1508
+ # self.csflabel = [sortedC[0].item()]
1509
+
1510
+ #self.post_correction = True
1511
+ print('post correction is {}'.format(self.post_correction))
1512
+ if self.post_correction:
1513
+
1514
+
1515
+
1516
+
1517
+ ### REMOVE SMALL STRUCTURES FROM WM
1518
+ self.adjust_membership(self.Membership)
1519
+
1520
+ self._remove_small_structures(self.dgmlabel)
1521
+
1522
+ self.Membership = adjust_common_structures(self.Membership, threshold=None)
1523
+ summation_old = 0
1524
+ summation_new = np.inf
1525
+
1526
+ if self.constraint and self.num_tissues > 4:
1527
+ self._correction_wm()
1528
+ self._connection_between_csf_wm(closing=True)
1529
+ else:
1530
+ self._correction_wm()
1531
+ # self._connection_between_bg_wm()
1532
+
1533
+ self.predict()
1534
+
1535
+ def predict(self, use_softmax=False, Membership=None):
1536
+ """
1537
+ Segment image
1538
+ @return:
1539
+ """
1540
+ if Membership is None:
1541
+ Membership = self.Membership
1542
+ if use_softmax:
1543
+ MM = softmax(Membership, -1)
1544
+ else:
1545
+ MM = Membership
1546
+
1547
+ sumu = Membership.sum(-1)
1548
+ ind_zero = sumu == 0
1549
+ maxs = MM.argmax(-1) # defuzzify
1550
+ self.output = maxs + 1
1551
+ self.output[ind_zero] = 0
1552
+ return self.output
1553
+