Vbai-TS-2.4
1
4 languages
license:cc-by-nc-sa-4.0
by
Neurazum
Image Model
OTHER
New
0 downloads
Early-stage
Edge AI:
Mobile
Laptop
Server
Unknown
Mobile
Laptop
Server
Quick Summary
AI model with specialized capabilities.
Code Examples
Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Kullanım / Usagepythonpytorch
import torch
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms
from PIL import Image
import matplotlib.pyplot as plt
import numpy as np
import cv2
import os
import argparse
from pathlib import Path
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix, average_precision_score
from sklearn.preprocessing import label_binarize
transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
edge_transform = transforms.Compose([
transforms.Resize((224, 224)),
transforms.Grayscale(num_output_channels=1),
transforms.ToTensor()
])
class BrainStructureAnalyzer:
@staticmethod
def detect_tumor_edges(image_tensor):
try:
if len(image_tensor.shape) == 4:
image = image_tensor[0].squeeze().cpu().numpy()
else:
image = image_tensor.squeeze().cpu().numpy()
image = ((image - image.min()) / (image.max() - image.min()) * 255).astype(np.uint8)
blurred = cv2.GaussianBlur(image, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
kernel = np.ones((3, 3), np.uint8)
edges = cv2.morphologyEx(edges, cv2.MORPH_CLOSE, kernel)
return edges
except Exception as e:
print(f"Edge detection hatası: {e}")
return np.zeros((224, 224), dtype=np.uint8)
@staticmethod
def analyze_tumor_structure(image_tensor):
edges = BrainStructureAnalyzer.detect_tumor_edges(image_tensor)
try:
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
if contours:
contours = sorted(contours, key=cv2.contourArea, reverse=True)[:3]
else:
contours = []
except Exception as e:
print(f"Kontur analizi hatası: {e}")
contours = []
return edges, contours
class AttentionModule(nn.Module):
def __init__(self, in_channels):
super(AttentionModule, self).__init__()
self.conv1 = nn.Conv2d(in_channels, max(1, in_channels // 8), 1)
self.conv2 = nn.Conv2d(max(1, in_channels // 8), 1, 1)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
attention = self.conv1(x)
attention = F.relu(attention)
attention = self.conv2(attention)
attention = self.sigmoid(attention)
return x * attention, attention
class EnhancedCNN(nn.Module):
def __init__(self, num_classes=4):
super(EnhancedCNN, self).__init__()
self.num_classes = num_classes
self.model_type = 'c'
self.conv1 = nn.Conv2d(3, 32, kernel_size=3, stride=1, padding=1)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, stride=1, padding=1)
self.conv3 = nn.Conv2d(64, 128, kernel_size=3, stride=1, padding=1)
self.attention1 = AttentionModule(64)
self.attention2 = AttentionModule(128)
self.fc1 = nn.Linear(128 * 28 * 28, 512)
self.dropout = nn.Dropout(0.5)
self.relu = nn.ReLU()
self.pool = nn.MaxPool2d(kernel_size=2, stride=2, padding=0)
self.edge_conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
self.edge_conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
self.edge_pool = nn.AdaptiveAvgPool2d(56)
self.edge_fc = nn.Linear(64 * 56 * 56, 128)
self.fc2 = nn.Linear(512, num_classes)
self.combined_fc = nn.Linear(512 + 128, num_classes)
def forward(self, x, edge_x=None):
x = self.pool(self.relu(self.conv1(x)))
x = self.relu(self.conv2(x))
x, attention_map1 = self.attention1(x)
x = self.pool(x)
x = self.relu(self.conv3(x))
x, attention_map2 = self.attention2(x)
x = self.pool(x)
x_flat = x.view(x.size(0), -1)
x_flat = self.relu(self.fc1(x_flat))
x_flat = self.dropout(x_flat)
if edge_x is not None:
try:
edge_x = self.pool(self.relu(self.edge_conv1(edge_x)))
edge_x = self.pool(self.relu(self.edge_conv2(edge_x)))
edge_x = self.edge_pool(edge_x)
edge_features = edge_x.view(edge_x.size(0), -1)
edge_features = self.relu(self.edge_fc(edge_features))
x_flat = torch.cat([x_flat, edge_features], dim=1)
output = self.combined_fc(x_flat)
except Exception as e:
print(f"Edge branch hatası: {e}")
output = self.fc2(x_flat)
else:
output = self.fc2(x_flat)
return output, attention_map2
class VisualizationManager:
@staticmethod
def denormalize_image(image_tensor):
mean = torch.tensor([0.485, 0.456, 0.406]).view(3, 1, 1)
std = torch.tensor([0.229, 0.224, 0.225]).view(3, 1, 1)
if image_tensor.device.type == 'cuda':
mean = mean.cuda()
std = std.cuda()
image = image_tensor * std + mean
image = torch.clamp(image, 0, 1)
return image
@staticmethod
def create_tumor_visualization(image, attention_map, prediction, class_names, edges=None,
save_path=None, confidence=None, show_plot=False):
try:
fig, axes = plt.subplots(2, 2, figsize=(15, 12))
if isinstance(image, torch.Tensor):
image = VisualizationManager.denormalize_image(image)
image = image.permute(1, 2, 0).cpu().numpy()
axes[0, 0].imshow(image)
axes[0, 0].set_title('Orijinal MRI Görüntüsü', fontsize=12, fontweight='bold')
axes[0, 0].axis('off')
if attention_map is not None:
attention = attention_map.squeeze().cpu().numpy()
if attention.ndim > 2:
attention = np.mean(attention, axis=0)
attention = cv2.resize(attention, (224, 224))
im = axes[0, 1].imshow(attention, cmap='jet', alpha=0.8)
axes[0, 1].set_title('Dikkat Haritası (Tümör Bölgeleri)', fontsize=12, fontweight='bold')
axes[0, 1].axis('off')
plt.colorbar(im, ax=axes[0, 1], fraction=0.046)
else:
axes[0, 1].text(0.5, 0.5, 'Dikkat Haritası\nMevcut Değil',
ha='center', va='center', transform=axes[0, 1].transAxes)
axes[0, 1].axis('off')
if edges is not None:
axes[1, 0].imshow(edges, cmap='gray')
axes[1, 0].set_title('Tümör Yapısı Çizgileri', fontsize=12, fontweight='bold')
axes[1, 0].axis('off')
else:
axes[1, 0].text(0.5, 0.5, 'Tümör Yapısı\nAnalizi Mevcut Değil',
ha='center', va='center', transform=axes[1, 0].transAxes)
axes[1, 0].axis('off')
axes[1, 1].imshow(image)
if attention_map is not None:
attention_overlay = cv2.resize(attention, (224, 224))
axes[1, 1].imshow(attention_overlay, cmap='jet', alpha=0.4)
predicted_class = class_names[prediction] if prediction < len(class_names) else "Bilinmeyen"
title_text = f'Teşhis: {predicted_class}'
if confidence is not None:
title_text += f'\nGüven: {confidence:.2f}%'
axes[1, 1].set_title(title_text, fontsize=12, fontweight='bold', color='red')
axes[1, 1].axis('off')
plt.tight_layout()
if save_path:
try:
plt.savefig(save_path, dpi=300, bbox_inches='tight')
print(f"✅ Görselleştirme kaydedildi: {save_path}")
except Exception as e:
print(f"⚠️ Görselleştirme kaydetme hatası: {e}")
if show_plot:
plt.show()
else:
plt.close(fig)
return fig
except Exception as e:
print(f"❌ Görselleştirme oluşturma hatası: {e}")
return None
def count_parameters(model):
total_params = sum(p.numel() for p in model.parameters())
trainable_params = sum(p.numel() for p in model.parameters() if p.requires_grad)
return total_params, trainable_params
def load_model(model_path, device):
print(f"📦 Model yükleniyor: {model_path}")
if not os.path.exists(model_path):
raise FileNotFoundError(f"Model dosyası bulunamadı: {model_path}")
checkpoint = torch.load(model_path, map_location=device)
model_config = checkpoint.get('model_config', {'num_classes': 4, 'model_type': 'c'})
class_names = checkpoint.get('class_names', ['glioma_tumor', 'meningioma_tumor', 'no_tumor', 'pituitary_tumor'])
model = EnhancedCNN(num_classes=model_config['num_classes']).to(device)
model.load_state_dict(checkpoint['model_state_dict'])
model.eval()
total_params, trainable_params = count_parameters(model)
print(f"✅ Model başarıyla yüklendi!")
print(f" Sınıflar: {class_names}")
print(f" Model tipi: {model_config['model_type']}")
print(f" Toplam parametre sayısı: {total_params:,}")
print(f" Eğitilebilir parametre sayısı: {trainable_params:,}")
return model, class_names
def test_single_image(model, image_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n🔍 Görüntü analiz ediliyor: {image_path}")
try:
image = Image.open(image_path).convert('RGB')
image_tensor = transform(image).unsqueeze(0).to(device)
edge_tensor = edge_transform(image).unsqueeze(0).to(device)
with torch.no_grad():
outputs, attention_maps = model(image_tensor, edge_tensor)
probabilities = F.softmax(outputs, dim=1)
confidence, predicted = torch.max(probabilities, 1)
confidence_value = confidence[0].item() * 100
predicted_class = predicted[0].item()
edges, contours = BrainStructureAnalyzer.analyze_tumor_structure(edge_tensor)
print(f"\n{'='*60}")
print(f"📊 SONUÇLAR")
print(f"{'='*60}")
print(f"🎯 Teşhis: {class_names[predicted_class]}")
print(f"📈 Güven Skoru: {confidence_value:.2f}%")
print(f"\n📉 Tüm Sınıf Olasılıkları:")
for i, class_name in enumerate(class_names):
prob = probabilities[0][i].item() * 100
bar = '█' * int(prob / 2)
print(f" {class_name:25s}: {prob:6.2f}% {bar}")
print(f"{'='*60}\n")
os.makedirs(output_dir, exist_ok=True)
image_name = Path(image_path).stem
save_path = os.path.join(output_dir, f'{image_name}_analysis.png')
VisualizationManager.create_tumor_visualization(
image_tensor[0],
attention_maps[0] if attention_maps is not None else None,
predicted_class,
class_names,
edges,
save_path,
confidence_value,
show_plot
)
return {
'image_path': image_path,
'prediction': class_names[predicted_class],
'confidence': confidence_value,
'probabilities': {class_names[i]: probabilities[0][i].item() * 100 for i in range(len(class_names))}
}
except Exception as e:
print(f"❌ Görüntü analizi hatası: {e}")
import traceback
traceback.print_exc()
return None
def calculate_metrics(y_true, y_pred, y_probs, class_names):
accuracy = np.mean(np.array(y_true) == np.array(y_pred))
precision = precision_score(y_true, y_pred, average='macro', zero_division=0)
recall = recall_score(y_true, y_pred, average='macro', zero_division=0)
f1 = f1_score(y_true, y_pred, average='macro', zero_division=0)
precision_per_class = precision_score(y_true, y_pred, average=None, zero_division=0)
recall_per_class = recall_score(y_true, y_pred, average=None, zero_division=0)
f1_per_class = f1_score(y_true, y_pred, average=None, zero_division=0)
n_classes = len(class_names)
y_true_bin = label_binarize(y_true, classes=list(range(n_classes)))
ap_scores = []
for i in range(n_classes):
try:
ap = average_precision_score(y_true_bin[:, i], np.array(y_probs)[:, i])
ap_scores.append(ap)
except:
ap_scores.append(0.0)
mAP = np.mean(ap_scores)
cm = confusion_matrix(y_true, y_pred)
return {
'accuracy': accuracy,
'precision': precision,
'recall': recall,
'f1_score': f1,
'precision_per_class': precision_per_class,
'recall_per_class': recall_per_class,
'f1_per_class': f1_per_class,
'ap_scores': ap_scores,
'mAP': mAP,
'confusion_matrix': cm
}
def test_directory(model, directory_path, class_names, device, output_dir='test_results', show_plot=False):
print(f"\n📁 Klasör test ediliyor: {directory_path}")
image_extensions = ['.png', '.jpg', '.jpeg', '.bmp', '.tiff']
image_files = []
ground_truths = []
max_images_per_class = 10
for class_idx, class_name in enumerate(class_names):
class_dir = Path(directory_path) / class_name
if class_dir.exists():
class_files = []
for ext in image_extensions:
files = list(class_dir.glob(f'*{ext}'))
files.extend(list(class_dir.glob(f'*{ext.upper()}')))
class_files.extend(files)
class_files = class_files[:max_images_per_class]
image_files.extend(class_files)
ground_truths.extend([class_idx] * len(class_files))
print(f" {class_name}: {len(class_files)} görüntü")
if not image_files:
print(f"⚠️ Klasörde görüntü bulunamadı: {directory_path}")
return []
print(f"✅ Toplam {len(image_files)} görüntü bulundu\n")
results = []
predictions = []
probabilities_list = []
for i, (image_file, true_label) in enumerate(zip(image_files, ground_truths), 1):
print(f"\n{'='*70}")
print(f"Görüntü {i}/{len(image_files)}")
print(f"{'='*70}")
result = test_single_image(model, str(image_file), class_names, device, output_dir, show_plot)
if result:
results.append(result)
pred_class = class_names.index(result['prediction'])
predictions.append(pred_class)
probs = [result['probabilities'][cn] / 100.0 for cn in class_names]
probabilities_list.append(probs)
if results and len(predictions) == len(ground_truths):
metrics = calculate_metrics(ground_truths, predictions, probabilities_list, class_names)
print(f"\n\n{'='*70}")
print(f"📊 DETAYLI TEST SONUÇLARI")
print(f"{'='*70}")
print(f"Toplam Test Edilen Görüntü: {len(results)}")
print(f"\n📈 GENEL METRİKLER:")
print(f" Accuracy (Doğruluk): {metrics['accuracy']*100:.2f}%")
print(f" Precision (Kesinlik): {metrics['precision']*100:.2f}%")
print(f" Recall (Duyarlılık): {metrics['recall']*100:.2f}%")
print(f" F1 Score: {metrics['f1_score']*100:.2f}%")
print(f" mAP (mean AP): {metrics['mAP']*100:.2f}%")
print(f"\n📊 SINIF BAZINDA METRİKLER:")
print(f"{'Sınıf':<25} {'Precision':<12} {'Recall':<12} {'F1 Score':<12} {'AP Score':<12}")
print(f"{'-'*73}")
for i, class_name in enumerate(class_names):
print(f"{class_name:<25} {metrics['precision_per_class'][i]*100:>10.2f}% "
f"{metrics['recall_per_class'][i]*100:>10.2f}% "
f"{metrics['f1_per_class'][i]*100:>10.2f}% "
f"{metrics['ap_scores'][i]*100:>10.2f}%")
print(f"\n📋 CONFUSION MATRIX:")
print(f"{'':>25}", end='')
for cn in class_names:
print(f"{cn[:10]:>12}", end='')
print()
for i, class_name in enumerate(class_names):
print(f"{class_name:<25}", end='')
for j in range(len(class_names)):
print(f"{metrics['confusion_matrix'][i][j]:>12}", end='')
print()
class_counts = {}
for result in results:
pred = result['prediction']
class_counts[pred] = class_counts.get(pred, 0) + 1
print(f"\n🎯 TAHMİN DAĞILIMI:")
for class_name, count in class_counts.items():
percentage = (count / len(results)) * 100
print(f" {class_name:25s}: {count:3d} ({percentage:.1f}%)")
avg_confidence = sum(r['confidence'] for r in results) / len(results)
print(f"\n📈 Ortalama Güven Skoru: {avg_confidence:.2f}%")
print(f"{'='*70}\n")
return results, metrics
else:
print(f"\n⚠️ Metrik hesaplaması için yeterli veri yok")
return results, None
def main():
parser = argparse.ArgumentParser(description='MRI Tümör Tespiti Test Script')
parser.add_argument('--model', type=str, required=True, help='Eğitilmiş model dosyasının yolu (.pt)')
parser.add_argument('--image', type=str, help='Test edilecek tek görüntü yolu')
parser.add_argument('--directory', type=str, help='Test edilecek klasör yolu')
parser.add_argument('--output', type=str, default='test_results', help='Sonuçların kaydedileceği klasör')
parser.add_argument('--show', action='store_true', help='Sonuçları ekranda göster')
parser.add_argument('--device', type=str, default='cuda' if torch.cuda.is_available() else 'cpu',
help='Kullanılacak cihaz (cuda/cpu)')
args = parser.parse_args()
print("🧠 MRI Tümör Tespiti Test Sistemi")
print("=" * 70)
device = torch.device(args.device)
print(f"🖥️ Kullanılan cihaz: {device}")
if device.type == 'cuda':
print(f" GPU: {torch.cuda.get_device_name(0)}")
print()
try:
model, class_names = load_model(args.model, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
return
if args.image:
test_single_image(model, args.image, class_names, device, args.output, args.show)
elif args.directory:
# Klasör testi
results, metrics = test_directory(model, args.directory, class_names, device, args.output, args.show)
else:
print("⚠️ Lütfen --image veya --directory parametresi belirtin")
parser.print_help()
if __name__ == '__main__':
import sys
if len(sys.argv) == 1:
print("🧠 MRI Tümör Tespiti Test Sistemi - İnteraktif Mod")
print("=" * 70)
model_path = input("Model dosyası yolu (.pt): ").strip()
test_type = input("Test tipi (1: Tek görüntü, 2: Klasör): ").strip()
if not os.path.exists(model_path):
print(f"❌ Model dosyası bulunamadı: {model_path}")
sys.exit(1)
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
print(f"\n🖥️ Kullanılan cihaz: {device}\n")
try:
model, class_names = load_model(model_path, device)
except Exception as e:
print(f"❌ Model yükleme hatası: {e}")
sys.exit(1)
if test_type == '1':
image_path = input("Görüntü dosyası yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
test_single_image(model, image_path, class_names, device, 'test_results', show)
elif test_type == '2':
dir_path = input("Klasör yolu: ").strip()
show = input("Sonuçları göster? (e/h): ").strip().lower() == 'e'
results, metrics = test_directory(model, dir_path, class_names, device, 'test_results', show)
else:
print("❌ Geçersiz seçim")
else:
main()Deploy This Model
Production-ready deployment in minutes
Together.ai
Instant API access to this model
Production-ready inference API. Start free, scale to millions.
Try Free APIReplicate
One-click model deployment
Run models in the cloud with simple API. No DevOps required.
Deploy NowDisclosure: We may earn a commission from these partners. This helps keep LLMYourWay free.