""" Test ScolioVis API with Spinal-AI2024 subset5 images """ import sys import json from pathlib import Path sys.path.insert(0, str(Path(__file__).parent)) import cv2 import numpy as np from PIL import Image import matplotlib matplotlib.use('Agg') import matplotlib.pyplot as plt def load_model(): print("Loading Keypoint R-CNN model...") from scoliovis.get_model import get_kprcnn_model model = get_kprcnn_model() model.eval() print("Model loaded!") return model def predict_single(model, image_path): import torch from torchvision.transforms import functional as F from scoliovis.kprcnn import _filter_output, kprcnn_to_scoliovis_api_format image = Image.open(image_path).convert('RGB') image_cv = cv2.cvtColor(np.array(image), cv2.COLOR_RGB2BGR) device = torch.device('cpu') model.to(device) image_tensor = F.to_tensor(image_cv) images_input = [image_tensor.to(device)] with torch.no_grad(): outputs = model(images_input) bboxes, keypoints, scores = _filter_output(outputs[0]) result = kprcnn_to_scoliovis_api_format(bboxes, keypoints, scores, image_cv.shape) return result, image_cv, keypoints def visualize_result(image_cv, keypoints, result, output_path): img_rgb = cv2.cvtColor(image_cv, cv2.COLOR_BGR2RGB) fig, ax = plt.subplots(1, 1, figsize=(8, 12)) ax.imshow(img_rgb) colors = plt.cm.rainbow(np.linspace(0, 1, len(keypoints))) for idx, (kps, color) in enumerate(zip(keypoints, colors)): xs = [p[0] for p in kps] ys = [p[1] for p in kps] order = [0, 1, 3, 2, 0] for i in range(4): ax.plot([xs[order[i]], xs[order[i+1]]], [ys[order[i]], ys[order[i+1]]], color=color, linewidth=2) cx, cy = np.mean(xs), np.mean(ys) ax.plot(cx, cy, 'o', color=color, markersize=4) if result.get('angles'): angles = result['angles'] title = f"Type: {result.get('curve_type', 'N/A')}\n" title += f"PT: {angles['pt']['angle']:.1f}° MT: {angles['mt']['angle']:.1f}° TL: {angles['tl']['angle']:.1f}°" ax.set_title(title, fontsize=10) else: ax.set_title("Could not calculate angles", fontsize=10) ax.axis('off') plt.tight_layout() plt.savefig(output_path, dpi=150, bbox_inches='tight') plt.close() def main(): test_images = [ "../data/Spinal-AI2024/Spinal-AI2024-subset5/016001.jpg", "../data/Spinal-AI2024/Spinal-AI2024-subset5/016002.jpg", "../data/Spinal-AI2024/Spinal-AI2024-subset5/016003.jpg", "../data/Spinal-AI2024/Spinal-AI2024-subset5/016004.jpg", "../data/Spinal-AI2024/Spinal-AI2024-subset5/016005.jpg", ] output_dir = Path("OUTPUT_TEST_1") output_dir.mkdir(exist_ok=True) model = load_model() results = [] for img_path in test_images: img_name = Path(img_path).stem print(f"\nProcessing {img_name}...") result, image_cv, keypoints = predict_single(model, img_path) # Save visualization output_path = output_dir / f"{img_name}_result.png" visualize_result(image_cv, keypoints, result, output_path) print(f" Saved: {output_path}") # Collect results if result.get('angles'): angles = result['angles'] results.append({ "image": img_name + ".jpg", "vertebrae_detected": len(keypoints), "curve_type": result.get('curve_type'), "pt": round(angles['pt']['angle'], 2), "mt": round(angles['mt']['angle'], 2), "tl": round(angles['tl']['angle'], 2) }) print(f" Vertebrae: {len(keypoints)}, PT: {angles['pt']['angle']:.1f}°, MT: {angles['mt']['angle']:.1f}°, TL: {angles['tl']['angle']:.1f}°") else: results.append({ "image": img_name + ".jpg", "vertebrae_detected": len(keypoints), "error": "Could not calculate angles" }) print(f" Vertebrae: {len(keypoints)}, Could not calculate angles") # Save JSON results with open(output_dir / "results.json", 'w') as f: json.dump(results, f, indent=2) print(f"\nResults saved to {output_dir}/results.json") if __name__ == "__main__": main()