11"""Example script to perform landmark localization on LAX images using fine-tuned checkpoint."""
22
3+ import io
34from pathlib import Path
45
56import imageio
89import SimpleITK as sitk # noqa: N813
910import torch
1011from monai .transforms import ScaleIntensityd
12+ from PIL import Image
1113from tqdm import tqdm
1214
1315from cinema import ConvUNetR , heatmap_soft_argmax
@@ -22,11 +24,11 @@ def plot_heatmaps(images: np.ndarray, probs: np.ndarray, filepath: Path) -> None
2224 filepath: path to save the GIF file.
2325 """
2426 n_frames = probs .shape [- 1 ]
25- temp_frame_paths = []
27+ frames = []
2628
2729 for t in tqdm (range (n_frames ), desc = "Creating heatmap GIF frames" ):
2830 # Create individual frame
29- fig , ax = plt .subplots (figsize = (5 , 5 ), dpi = 300 )
31+ fig , ax = plt .subplots (figsize = (5 , 5 ), dpi = 150 )
3032
3133 # Plot image
3234 ax .imshow (images [..., 0 , t ], cmap = "gray" )
@@ -40,19 +42,20 @@ def plot_heatmaps(images: np.ndarray, probs: np.ndarray, filepath: Path) -> None
4042 ax .set_xticks ([])
4143 ax .set_yticks ([])
4244
43- # Save frame
44- frame_path = f"_tmp_heatmap_frame_{ t :03d} .png"
45- plt .savefig (frame_path , bbox_inches = "tight" , pad_inches = 0 , dpi = 300 )
45+ # Render figure to numpy array using BytesIO (universal across backends)
46+ buf = io .BytesIO ()
47+ plt .savefig (buf , format = "png" , bbox_inches = "tight" , pad_inches = 0 , dpi = 150 )
48+ buf .seek (0 )
49+ img = Image .open (buf )
50+ frame = np .array (img .convert ("RGB" ))
51+ frames .append (frame )
52+ buf .close ()
4653 plt .close (fig )
47- temp_frame_paths .append (frame_path )
4854
49- # Create GIF
55+ # Create GIF directly from memory arrays
5056 with imageio .get_writer (filepath , mode = "I" , duration = 100 , loop = 0 ) as writer :
51- for frame_path in tqdm (temp_frame_paths , desc = "Creating heatmap GIF" ):
52- image = imageio .v2 .imread (frame_path )
53- writer .append_data (image )
54- # Clean up temporary file
55- Path (frame_path ).unlink ()
57+ for frame in tqdm (frames , desc = "Creating heatmap GIF" ):
58+ writer .append_data (frame )
5659
5760
5861def plot_landmarks (images : np .ndarray , coords : np .ndarray , filepath : Path ) -> None :
@@ -64,11 +67,11 @@ def plot_landmarks(images: np.ndarray, coords: np.ndarray, filepath: Path) -> No
6467 filepath: path to save the GIF file.
6568 """
6669 n_frames = images .shape [- 1 ]
67- temp_frame_paths = []
70+ frames = []
6871
6972 for t in tqdm (range (n_frames ), desc = "Creating landmark GIF frames" ):
7073 # Create individual frame
71- fig , ax = plt .subplots (figsize = (5 , 5 ), dpi = 300 )
74+ fig , ax = plt .subplots (figsize = (5 , 5 ), dpi = 150 )
7275
7376 # draw predictions with cross
7477 preds = images [..., t ] * np .array ([1 , 1 , 1 ])[None , None , :]
@@ -84,19 +87,20 @@ def plot_landmarks(images: np.ndarray, coords: np.ndarray, filepath: Path) -> No
8487 ax .set_xticks ([])
8588 ax .set_yticks ([])
8689
87- # Save frame
88- frame_path = f"_tmp_landmark_frame_{ t :03d} .png"
89- plt .savefig (frame_path , bbox_inches = "tight" , pad_inches = 0 , dpi = 300 )
90+ # Render figure to numpy array using BytesIO (universal across backends)
91+ buf = io .BytesIO ()
92+ plt .savefig (buf , format = "png" , bbox_inches = "tight" , pad_inches = 0 , dpi = 150 )
93+ buf .seek (0 )
94+ img = Image .open (buf )
95+ frame = np .array (img .convert ("RGB" ))
96+ frames .append (frame )
97+ buf .close ()
9098 plt .close (fig )
91- temp_frame_paths .append (frame_path )
9299
93- # Create GIF
100+ # Create GIF directly from memory arrays
94101 with imageio .get_writer (filepath , mode = "I" , duration = 100 , loop = 0 ) as writer :
95- for frame_path in tqdm (temp_frame_paths , desc = "Creating landmark GIF" ):
96- image = imageio .v2 .imread (frame_path )
97- writer .append_data (image )
98- # Clean up temporary file
99- Path (frame_path ).unlink ()
102+ for frame in tqdm (frames , desc = "Creating landmark GIF" ):
103+ writer .append_data (frame )
100104
101105
102106def plot_lv (coords : np .ndarray , filepath : Path ) -> None :
0 commit comments