mosta02 commited on
Commit
cc7fa4d
·
verified ·
1 Parent(s): 90891b2

Upload centerline_extraction.py

Browse files
Files changed (1) hide show
  1. centerline_extraction.py +23 -11
centerline_extraction.py CHANGED
@@ -142,7 +142,7 @@ def compute_centerlines_network(
142
  # Extract main aorta→iliacs centerline via Voronoi method
143
  try:
144
  print("Extracting main centerline...")
145
- centerline_polydata = extract_centerline_from_surface(surface_polydata_ras, aorta_iliac_endpoints_ras, curve_sampling_distance, smooth_iterations=0)
146
  print(f"Main centerline: {centerline_polydata.GetNumberOfCells()} cells, {centerline_polydata.GetNumberOfPoints()} points")
147
  except Exception as e:
148
  print(f"Main centerline extraction failed: {type(e).__name__}: {e}")
@@ -157,7 +157,7 @@ def compute_centerlines_network(
157
  except Exception as e:
158
  print(f"Branch extraction failed: {type(e).__name__}: {e}")
159
 
160
- # Merge main + branch centerlines, and finally smooth all the centerlines
161
  if branch_centerlines:
162
  try:
163
  merged = merge_main_and_branch_centerlines(centerline_polydata, branch_centerlines)
@@ -726,7 +726,7 @@ def smooth_centerline_polydata(centerline_polydata, iterations, relaxation_facto
726
  # Process all branches, generating their centerlines, computing their new bifurcation points on actual voronoi centerline (not skeleton)
727
  def process_all_branches(branch_information, main_centerline_polydata, surface_polydata, curve_sampling_distance):
728
  if not branch_information:
729
- return []
730
 
731
  # Convert branch info from LPS to RAS
732
  branch_info_ras = []
@@ -768,7 +768,8 @@ def extract_branch_centerline(branch_info, main_centerline_polydata, surface_pol
768
 
769
  # Extract the branch centerline
770
  try:
771
- branch_centerline = extract_centerline_from_surface(clipped_surface, branch_endpoints, curve_sampling_distance, smooth_iterations=0)
 
772
  return branch_centerline, contact_point
773
  except Exception as e:
774
  print(f"\nWarning: branch centerline extraction failed: {e}")
@@ -812,11 +813,25 @@ def clip_surface_around_points(surface_polydata, point1, point2, radius_multipli
812
  cleaner.Update()
813
  return cleaner.GetOutput()
814
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
815
  # Merge the main aorta→iliacs centerline with all branch centerlines into one polydata.
816
  def merge_main_and_branch_centerlines(main_centerline_polydata, branch_centerlines):
817
  if not branch_centerlines:
818
- # Still smooth the main-only result
819
- return smooth_centerline_polydata(main_centerline_polydata, iterations=20, relaxation_factor=0.1)
820
 
821
  append_filter = vtk.vtkAppendPolyData()
822
  append_filter.AddInputData(main_centerline_polydata)
@@ -828,14 +843,11 @@ def merge_main_and_branch_centerlines(main_centerline_polydata, branch_centerlin
828
  cleaner = vtk.vtkCleanPolyData()
829
  cleaner.SetInputData(append_filter.GetOutput())
830
  cleaner.SetToleranceIsAbsolute(True)
831
- cleaner.SetAbsoluteTolerance(0.5) # 0.5mm tolerance to merge junction points from separately-extracted branch centerlines
832
  cleaner.Update()
833
 
834
- # Smooth ONCE on the fully-connected network — endpoints and junction nodes are fixed by BoundarySmoothingOff
835
  merged = cleaner.GetOutput()
836
- smoothed = smooth_centerline_polydata(merged, iterations=20, relaxation_factor=0.1)
837
- print(f"Merged+smoothed: {smoothed.GetNumberOfCells()} cells, {smoothed.GetNumberOfPoints()} points")
838
- return smoothed
839
 
840
  # Main Pipeline for extracting centerline data, labeling bifurcations and arteries, computing ostium and reference point positions
841
  def extract_centerline_data(centerlines, branch_junctions=None):
 
142
  # Extract main aorta→iliacs centerline via Voronoi method
143
  try:
144
  print("Extracting main centerline...")
145
+ centerline_polydata = extract_centerline_from_surface(surface_polydata_ras, aorta_iliac_endpoints_ras, curve_sampling_distance, smooth_iterations=20)
146
  print(f"Main centerline: {centerline_polydata.GetNumberOfCells()} cells, {centerline_polydata.GetNumberOfPoints()} points")
147
  except Exception as e:
148
  print(f"Main centerline extraction failed: {type(e).__name__}: {e}")
 
157
  except Exception as e:
158
  print(f"Branch extraction failed: {type(e).__name__}: {e}")
159
 
160
+ # Merge main + branch centerlines
161
  if branch_centerlines:
162
  try:
163
  merged = merge_main_and_branch_centerlines(centerline_polydata, branch_centerlines)
 
726
  # Process all branches, generating their centerlines, computing their new bifurcation points on actual voronoi centerline (not skeleton)
727
  def process_all_branches(branch_information, main_centerline_polydata, surface_polydata, curve_sampling_distance):
728
  if not branch_information:
729
+ return [], []
730
 
731
  # Convert branch info from LPS to RAS
732
  branch_info_ras = []
 
768
 
769
  # Extract the branch centerline
770
  try:
771
+ branch_centerline = extract_centerline_from_surface(clipped_surface, branch_endpoints, curve_sampling_distance, smooth_iterations=10)
772
+ branch_centerline = snap_branch_to_contact(branch_centerline, contact_point)
773
  return branch_centerline, contact_point
774
  except Exception as e:
775
  print(f"\nWarning: branch centerline extraction failed: {e}")
 
813
  cleaner.Update()
814
  return cleaner.GetOutput()
815
 
816
+ # Forces the branch centerline endpoint nearest to contact_point to land at EXACTLY that coordinate, guaranteeing vtkCleanPolyData can merge it with the main centerline
817
+ def snap_branch_to_contact(branch_cl, contact_point):
818
+ pts = branch_cl.GetPoints()
819
+ n = pts.GetNumberOfPoints()
820
+ if n < 2:
821
+ return branch_cl
822
+ p_first = pts.GetPoint(0)
823
+ p_last = pts.GetPoint(n - 1)
824
+ d_first = vtk.vtkMath.Distance2BetweenPoints(p_first, contact_point)
825
+ d_last = vtk.vtkMath.Distance2BetweenPoints(p_last, contact_point)
826
+ snap_id = 0 if d_first < d_last else n - 1
827
+ pts.SetPoint(snap_id, contact_point[0], contact_point[1], contact_point[2])
828
+ pts.Modified()
829
+ return branch_cl
830
+
831
  # Merge the main aorta→iliacs centerline with all branch centerlines into one polydata.
832
  def merge_main_and_branch_centerlines(main_centerline_polydata, branch_centerlines):
833
  if not branch_centerlines:
834
+ return main_centerline_polydata
 
835
 
836
  append_filter = vtk.vtkAppendPolyData()
837
  append_filter.AddInputData(main_centerline_polydata)
 
843
  cleaner = vtk.vtkCleanPolyData()
844
  cleaner.SetInputData(append_filter.GetOutput())
845
  cleaner.SetToleranceIsAbsolute(True)
846
+ cleaner.SetAbsoluteTolerance(0.1) # 0.1mm tolerance to merge junction points from separately-extracted branch centerlines
847
  cleaner.Update()
848
 
 
849
  merged = cleaner.GetOutput()
850
+ return merged
 
 
851
 
852
  # Main Pipeline for extracting centerline data, labeling bifurcations and arteries, computing ostium and reference point positions
853
  def extract_centerline_data(centerlines, branch_junctions=None):