| import os
|
| import argparse
|
| import torch
|
| import numpy as np
|
| from PIL import Image
|
| import torchvision.transforms as transforms
|
| from TrainModel import SimpleAE
|
|
|
| def load_checkpoint(path, device='cpu'):
|
| """
|
| Load autoencoder model and threshold from checkpoint file.
|
| """
|
|
|
| checkpoint = torch.load(path, map_location=device, weights_only=False)
|
| model = SimpleAE().to(device)
|
| model.load_state_dict(checkpoint['model_state'])
|
| threshold = checkpoint['threshold']
|
| model.eval()
|
| return model, threshold
|
|
|
|
|
| def preprocess_image(image_path, img_size):
|
| """
|
| Load and preprocess image: resize, grayscale, to tensor.
|
| """
|
| img = Image.open(image_path).convert('L')
|
| transform = transforms.Compose([
|
| transforms.Resize((img_size, img_size)),
|
| transforms.ToTensor()
|
| ])
|
| tensor = transform(img).unsqueeze(0)
|
| return tensor
|
|
|
|
|
| def compute_reconstruction_error(model, x_tensor, device='cpu'):
|
| """
|
| Compute mean squared reconstruction error for input tensor.
|
| """
|
| x = x_tensor.to(device)
|
| with torch.no_grad():
|
| recon = model(x)
|
| mse = torch.mean((recon - x) ** 2).item()
|
| return mse
|
|
|
|
|
| def map_error_to_quality(mse, threshold):
|
| """
|
| Convert reconstruction error to a quality percentage in [0,100].
|
| - If mse <= threshold: quality = 100 * (1 - mse/threshold)
|
| - Else: quality = 0
|
| Confidence equals quality.
|
| """
|
| if mse <= threshold:
|
| quality = (1 - mse / threshold) * 100
|
| else:
|
| quality = 0.0
|
|
|
| quality = max(0.0, min(100.0, quality))
|
| confidence = quality
|
| return round(quality, 2), round(confidence, 2)
|
|
|
|
|
| def main(args):
|
|
|
| if not os.path.isfile(args.model_path):
|
| raise FileNotFoundError(f"Model checkpoint not found: {args.model_path}")
|
| if not os.path.isfile(args.image_path):
|
| raise FileNotFoundError(f"Image file not found: {args.image_path}")
|
|
|
|
|
| model, threshold = load_checkpoint(args.model_path, device='cpu')
|
|
|
|
|
| x = preprocess_image(args.image_path, args.img_size)
|
|
|
|
|
| mse_error = compute_reconstruction_error(model, x, device='cpu')
|
|
|
|
|
| quality_pct, confidence_pct = map_error_to_quality(mse_error, threshold)
|
|
|
|
|
| print(f"Image: {os.path.basename(args.image_path)}")
|
| print(f"Reconstruction MSE Error: {mse_error:.6f}")
|
| print(f"Threshold (95th percentile): {threshold:.6f}")
|
| print(f"Quality Score: {quality_pct:.2f}%")
|
| print(f"Confidence: {confidence_pct:.2f}%")
|
|
|
| if __name__ == '__main__':
|
| parser = argparse.ArgumentParser(description='Assess quality of a radiology image using trained QA model')
|
| parser.add_argument('--model_path', type=str, default='./models/autoencoder_qc.pth', help='Path to QA model checkpoint')
|
| parser.add_argument('--image_path', type=str, required=True, help='Path to radiology image (PNG/JPG)')
|
| parser.add_argument('--img_size', type=int, default=128, help='Image resize dimension (square)')
|
| args = parser.parse_args()
|
| main(args)
|
|
|