draw deformation cutoff line in previews
This commit is contained in:
@@ -119,6 +119,28 @@ def crop_head_neck(image):
|
||||
return image.crop((left, top, right, bottom))
|
||||
|
||||
|
||||
def cutoff_center_z(coordinates_cutoff):
|
||||
return float(np.mean([point[0] for point in coordinates_cutoff]))
|
||||
|
||||
|
||||
def draw_cutoff_line(panel, image_depth, coordinates_cutoff=DEFAULT_COORDINATES_CUTOFF):
|
||||
panel = panel.copy()
|
||||
crop_height = int(image_depth * 0.72)
|
||||
if crop_height <= 0:
|
||||
return panel
|
||||
|
||||
line_y = int(round((image_depth - 1 - cutoff_center_z(coordinates_cutoff)) * panel.height / crop_height))
|
||||
if line_y < 0 or line_y >= panel.height:
|
||||
return panel
|
||||
|
||||
draw = ImageDraw.Draw(panel)
|
||||
shadow = (0, 0, 0)
|
||||
line_color = (255, 215, 60)
|
||||
draw.line((0, line_y, panel.width, line_y), fill=shadow, width=6)
|
||||
draw.line((0, line_y, panel.width, line_y), fill=line_color, width=3)
|
||||
return panel
|
||||
|
||||
|
||||
def fit_image(image, width, height):
|
||||
scale = min(width / image.width, height / image.height)
|
||||
resized = image.resize(
|
||||
@@ -333,12 +355,18 @@ def run_deformation(input_dir, output_dir, angle_degrees, transition_width, prog
|
||||
output_paths["legacy_soft"] = legacy_soft_dir
|
||||
|
||||
progress("正在生成四状态过程对比图...")
|
||||
preview_paths = make_four_state_preview(state_images, Path(output_dir), angle_degrees)
|
||||
preview_paths = make_four_state_preview(
|
||||
state_images,
|
||||
Path(output_dir),
|
||||
angle_degrees,
|
||||
vol_info.coordinates_cutoff,
|
||||
)
|
||||
make_output_preview_from_images(
|
||||
state_images["original"],
|
||||
state_images["soft_transition"],
|
||||
Path(output_dir),
|
||||
angle_degrees,
|
||||
vol_info.coordinates_cutoff,
|
||||
)
|
||||
return output_paths, preview_paths
|
||||
|
||||
@@ -375,14 +403,17 @@ def make_output_preview(original_dir, deformed_dicom_dir, output_dir, angle_degr
|
||||
return preview_path
|
||||
|
||||
|
||||
def sitk_sagittal_panel(image):
|
||||
def sitk_sagittal_panel(image, coordinates_cutoff=None):
|
||||
volume = sitk.GetArrayFromImage(image)[::-1]
|
||||
return crop_head_neck(sagittal_mip(volume))
|
||||
panel = crop_head_neck(sagittal_mip(volume))
|
||||
if coordinates_cutoff is not None:
|
||||
panel = draw_cutoff_line(panel, volume.shape[0], coordinates_cutoff)
|
||||
return panel
|
||||
|
||||
|
||||
def make_output_preview_from_images(original_image, deformed_image, output_dir, angle_degrees):
|
||||
before = sitk_sagittal_panel(original_image)
|
||||
after = sitk_sagittal_panel(deformed_image)
|
||||
def make_output_preview_from_images(original_image, deformed_image, output_dir, angle_degrees, coordinates_cutoff=None):
|
||||
before = sitk_sagittal_panel(original_image, coordinates_cutoff)
|
||||
after = sitk_sagittal_panel(deformed_image, coordinates_cutoff)
|
||||
|
||||
slide = Image.new("RGB", (2560, 1440), (0, 0, 0))
|
||||
draw = ImageDraw.Draw(slide)
|
||||
@@ -408,14 +439,14 @@ def make_output_preview_from_images(original_image, deformed_image, output_dir,
|
||||
return preview_path
|
||||
|
||||
|
||||
def make_four_state_preview(state_images, output_dir, angle_degrees):
|
||||
def make_four_state_preview(state_images, output_dir, angle_degrees, coordinates_cutoff=None):
|
||||
output_dir = Path(output_dir)
|
||||
screenshot_dir = output_dir / "process_screenshots"
|
||||
reset_folder(screenshot_dir)
|
||||
|
||||
panels = []
|
||||
for state_key, label, _ in STATE_LABELS:
|
||||
panel = sitk_sagittal_panel(state_images[state_key])
|
||||
panel = sitk_sagittal_panel(state_images[state_key], coordinates_cutoff)
|
||||
panel_path = screenshot_dir / f"{state_key}.png"
|
||||
panel.save(panel_path, quality=95)
|
||||
panels.append((label, panel))
|
||||
@@ -573,6 +604,7 @@ class HeadExtensionApp:
|
||||
self.status.set("正在读取 DICOM 生成预览...")
|
||||
self.cached_volume = load_dicom_volume(self.input_dir.get())
|
||||
before = crop_head_neck(sagittal_mip(self.cached_volume))
|
||||
before = draw_cutoff_line(before, self.cached_volume.shape[0])
|
||||
after = preview_deform_2d(before, float(self.angle.get()))
|
||||
|
||||
canvas = Image.new("RGB", (1120, 610), (0, 0, 0))
|
||||
|
||||
@@ -25,6 +25,7 @@ from head_extension_app import (
|
||||
APP_DIR,
|
||||
crop_head_neck,
|
||||
ct_window,
|
||||
draw_cutoff_line,
|
||||
fit_image,
|
||||
load_dicom_volume,
|
||||
preview_deform_2d,
|
||||
@@ -549,6 +550,7 @@ def start_job(kind, worker, owner=None, params=None, remember_user_task=True):
|
||||
def make_preview(input_dir, angle_degrees):
|
||||
volume = load_dicom_volume(input_dir)
|
||||
before = crop_head_neck(sagittal_mip(volume))
|
||||
before = draw_cutoff_line(before, volume.shape[0])
|
||||
after = preview_deform_2d(before, float(angle_degrees))
|
||||
|
||||
canvas = BytesIO()
|
||||
|
||||
Reference in New Issue
Block a user