Spaces:
Sleeping
Sleeping
AutoDeploy
Fix: Python 3.8 compatibility (use Tuple from typing) + Gradio 4.48.1 security update
8f59aab
| """ | |
| Simple test script - Test model on sample images without masks | |
| Phiên bản đơn giản - test mô hình trên ảnh mẫu mà không cần mask | |
| """ | |
| import os | |
| import argparse | |
| from pathlib import Path | |
| import numpy as np | |
| from PIL import Image | |
| import json | |
| from tqdm import tqdm | |
| import torch | |
| import torch.nn.functional as F | |
| from transformers import SegformerForSemanticSegmentation, SegformerImageProcessor | |
| class SimpleSegmentationTester: | |
| def __init__(self, model_path, device="auto"): | |
| self.device = torch.device("cuda" if device == "auto" and torch.cuda.is_available() else "cpu") | |
| print(f"🖥️ Device: {self.device}") | |
| print(f"📁 Loading model from: {model_path}") | |
| try: | |
| # Load model | |
| self.model = SegformerForSemanticSegmentation.from_pretrained(model_path) | |
| self.model.to(self.device) | |
| self.model.eval() | |
| # Create default processor (from nvidia/segformer-b0-finetuned-cityscapes-1024-1024) | |
| self.processor = SegformerImageProcessor( | |
| do_resize=True, | |
| size={"height": 512, "width": 512}, | |
| do_normalize=True, | |
| image_mean=[0.485, 0.456, 0.406], | |
| image_std=[0.229, 0.224, 0.225], | |
| do_reduce_labels=False | |
| ) | |
| print("✓ Model loaded successfully") | |
| except Exception as e: | |
| print(f"✗ Error loading model: {e}") | |
| raise | |
| def predict_single(self, image_path, return_probs=False): | |
| """Dự đoán trên một ảnh""" | |
| try: | |
| # Load image | |
| image = Image.open(image_path).convert("RGB") | |
| original_size = image.size[::-1] # (H, W) | |
| # Process image | |
| inputs = self.processor(images=image, return_tensors="pt") | |
| # Inference | |
| with torch.no_grad(): | |
| outputs = self.model(pixel_values=inputs["pixel_values"].to(self.device)) | |
| logits = outputs.logits | |
| # Interpolate to original size | |
| upsampled_logits = F.interpolate( | |
| logits, | |
| size=original_size, | |
| mode="bilinear", | |
| align_corners=False | |
| ) | |
| pred_mask = upsampled_logits.argmax(dim=1)[0].cpu().numpy() | |
| if return_probs: | |
| probs = torch.softmax(upsampled_logits, dim=1)[0].cpu().numpy() | |
| return pred_mask, probs | |
| return pred_mask | |
| except Exception as e: | |
| print(f"✗ Error predicting on {image_path}: {e}") | |
| return None | |
| def process_images(self, image_dir, output_dir=None): | |
| """Xử lý tất cả ảnh trong thư mục""" | |
| image_dir = Path(image_dir) | |
| if not image_dir.exists(): | |
| print(f"✗ Directory not found: {image_dir}") | |
| return False | |
| image_paths = sorted(list(image_dir.glob("*.png"))) + sorted(list(image_dir.glob("*.jpg"))) | |
| if not image_paths: | |
| print(f"✗ No images found in {image_dir}") | |
| return False | |
| print(f"\n📊 Processing {len(image_paths)} images...") | |
| if output_dir: | |
| output_dir = Path(output_dir) | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| results = [] | |
| for img_path in tqdm(image_paths): | |
| img_id = img_path.stem | |
| # Predict | |
| pred_mask = self.predict_single(img_path) | |
| if pred_mask is None: | |
| continue | |
| # Count detected organs | |
| total_pixels = pred_mask.size | |
| detected_organs = { | |
| 'large_bowel': int((pred_mask == 1).sum()), | |
| 'small_bowel': int((pred_mask == 2).sum()), | |
| 'stomach': int((pred_mask == 3).sum()), | |
| 'background': int((pred_mask == 0).sum()), | |
| 'total_pixels': total_pixels | |
| } | |
| result = { | |
| 'image_id': img_id, | |
| 'detected_organs': detected_organs, | |
| 'total_pixels': total_pixels | |
| } | |
| results.append(result) | |
| # Save prediction mask if output_dir provided | |
| if output_dir: | |
| # Colorize prediction | |
| pred_colored = np.zeros((*pred_mask.shape, 3), dtype=np.uint8) | |
| # Colors: 1=red, 2=green, 3=blue, 0=black | |
| pred_colored[pred_mask == 1] = [255, 0, 0] # Large bowel - Red | |
| pred_colored[pred_mask == 2] = [0, 154, 23] # Small bowel - Green | |
| pred_colored[pred_mask == 3] = [0, 127, 255] # Stomach - Blue | |
| pred_img = Image.fromarray(pred_colored) | |
| pred_img.save(output_dir / f"{img_id}_pred.png") | |
| # Print summary | |
| print("\n" + "="*60) | |
| print("📈 Prediction Summary") | |
| print("="*60) | |
| if results: | |
| print(f"\nProcessed {len(results)} images successfully\n") | |
| # Statistics | |
| for idx, result in enumerate(results, 1): | |
| print(f"{idx}. {result['image_id']}") | |
| organs = result['detected_organs'] | |
| total = organs['large_bowel'] + organs['small_bowel'] + organs['stomach'] | |
| if total > 0: | |
| print(f" - Large bowel: {organs['large_bowel']:,} pixels") | |
| print(f" - Small bowel: {organs['small_bowel']:,} pixels") | |
| print(f" - Stomach: {organs['stomach']:,} pixels") | |
| print(f" - Total organs: {total:,} pixels ({100*total/organs['total_pixels']:.1f}%)") | |
| else: | |
| print(f" - No organs detected") | |
| # Save results | |
| if output_dir: | |
| with open(output_dir / "predictions.json", 'w') as f: | |
| json.dump(results, f, indent=2) | |
| print(f"\n✓ Predictions saved to {output_dir}") | |
| print(f" - Colored masks: {output_dir}/*_pred.png") | |
| print(f" - Results JSON: {output_dir}/predictions.json") | |
| return True | |
| def main(): | |
| parser = argparse.ArgumentParser(description="Simple test on sample images") | |
| parser.add_argument("--model", type=str, required=True, | |
| help="Path to trained model") | |
| parser.add_argument("--images", type=str, required=True, | |
| help="Path to images directory") | |
| parser.add_argument("--output-dir", type=str, default=None, | |
| help="Output directory for results") | |
| args = parser.parse_args() | |
| # Initialize tester | |
| tester = SimpleSegmentationTester(args.model) | |
| # Process images | |
| success = tester.process_images(args.images, args.output_dir) | |
| return success | |
| if __name__ == "__main__": | |
| success = main() | |
| exit(0 if success else 1) | |