diff --git a/.gitignore b/.gitignore index 21d0b898f..a38501f98 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ .venv/ +CIFAKE/ +CIEDGE/ diff --git a/eval_model_ciedge.py b/eval_model_ciedge.py new file mode 100644 index 000000000..25db04427 --- /dev/null +++ b/eval_model_ciedge.py @@ -0,0 +1,121 @@ +import os +import torch +import torchvision +import torchvision.transforms as transforms +from torch.utils.data import DataLoader +from torchvision import datasets, models +import torch.nn as nn +import torch.optim as optim +from tqdm import tqdm # https://tqdm.github.io/ + +# https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +# ======= Settings ======= +CIEDGE_DIR = "./CIEDGE" +CIFAKE_DIR = "./CIFAKE" +BATCH_SIZE = 16 +NUM_CLASSES = 2 +DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +# ======= Transforms ======= +transform = transforms.Compose([ + transforms.Resize((224, 224)), # Ensure fixed input size + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], # ImageNet mean + [0.229, 0.224, 0.225]) # ImageNet std +]) + +cifake_dataset = datasets.ImageFolder(os.path.join(CIFAKE_DIR, "test"), transform=transform) +ciedge_dataset = datasets.ImageFolder(os.path.join(CIEDGE_DIR, "test"), transform=transform) +cifake_loader = DataLoader(cifake_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=True) +ciedge_loader = DataLoader(ciedge_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=True) + +# ======= Load Model ======= +cifake_model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1) +ciedge_model = models.resnet18(weights=models.ResNet18_Weights.IMAGENET1K_V1) + +cifake_model.fc = nn.Linear(cifake_model.fc.in_features, NUM_CLASSES) +ciedge_model.fc = nn.Linear(ciedge_model.fc.in_features, NUM_CLASSES) + +ciedge_state = torch.load("resnet18_ciedge.pth", map_location=torch.device('cpu')) +cifake_state = torch.load("resnet18_cifake.pth", map_location=torch.device('cpu')) + +cifake_model.load_state_dict(cifake_state) +ciedge_model.load_state_dict(ciedge_state) + + +cifake_model = cifake_model.to(DEVICE) +ciedge_model = ciedge_model.to(DEVICE) + + + +cifake_model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in cifake_loader: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = cifake_model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + if total > 400: + print(f"CIFAKE model evaluating CIFAKE data: {100 * correct / total:.2f}%") + break + + + +cifake_model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in ciedge_loader: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = cifake_model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + if total > 400: + print(f"CIFAKE model evaluating CIEDGE data: {100 * correct / total:.2f}%") + break + + + +ciedge_model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in cifake_loader: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = ciedge_model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + if total > 400: + print(f"CIEDGE model evaluating CIFAKE data: {100 * correct / total:.2f}%") + break + + + +ciedge_model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in ciedge_loader: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = ciedge_model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + if total > 400: + print(f"CIEDGE model evaluating CIEDGE data: {100 * correct / total:.2f}%") + break + + + + + + + + + diff --git a/eval_model_cifake.py b/eval_model_cifake.py new file mode 100644 index 000000000..5ef0e8629 --- /dev/null +++ b/eval_model_cifake.py @@ -0,0 +1,57 @@ +import os +import torch +import torchvision +import torchvision.transforms as transforms +from torch.utils.data import DataLoader +from torchvision import datasets, models +import torch.nn as nn +import torch.optim as optim +from tqdm import tqdm # https://tqdm.github.io/ + +# https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +# ======= Settings ======= +DATA_DIR = "./CIFAKE" +BATCH_SIZE = 16 +NUM_CLASSES = 2 +NUM_EPOCHS = 10 +LEARNING_RATE = 1e-4 +DEVICE = "cpu" + +# ======= Transforms ======= +transform = transforms.Compose([ + transforms.Resize((224, 224)), # Ensure fixed input size + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], # ImageNet mean + [0.229, 0.224, 0.225]) # ImageNet std +]) + +# ======= Load Data ======= +test_dataset = datasets.ImageFolder(os.path.join(DATA_DIR, "test"), transform=transform) +test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=True) + +# ======= Load Model ======= +model = models.resnet18(pretrained=True) +model.fc = nn.Linear(model.fc.in_features, NUM_CLASSES) +state = torch.load("resnet18_cifake.pth", map_location=torch.device('cpu')) +model.load_state_dict(state) +model = model.to(DEVICE) + + +# ======= Evaluation ======= +model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in tqdm(test_loader): + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + #print(f"total={total}, correct={correct}") + if total >= 400: + break + +print(f"Test Accuracy: {100 * correct / total:.2f}%") + diff --git a/genpath.awk b/genpath.awk new file mode 100644 index 000000000..32abe00dc --- /dev/null +++ b/genpath.awk @@ -0,0 +1 @@ +{a = $0; sub("CIFAKE", "CIEDGE", a); beton = "python main.py \'"$0"\' \'"a"\' &"; system(beton)} diff --git a/main.py b/main.py new file mode 100644 index 000000000..724d57a0f --- /dev/null +++ b/main.py @@ -0,0 +1,45 @@ +import sys +import cv2 +from pathlib import Path + +def laplace_edge_detection(image_path, output_path): + """ + Opens an image, applies Laplace filtering for edge detection, + and saves the resulting grayscale image. + + Args: + image_path (str): Path to the input image file. + output_path (str): Path to save the processed image. + """ + + try: + # Open the image in grayscale mode + img = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE) + + if img is None: + print(f"Error: Could not open or read image at {image_path}") + return + + # Apply Laplace filter for edge detection + laplace_kernel = np.array([[0, 1, 0], + [1, -4, 1], + [0, 1, 0]]) # Standard Laplace kernel + laplace_filtered = cv2.filter2D(img, -1, laplace_kernel) + + # Convert to uint8 (grayscale 8-bit) and clip values to the valid range [0, 255] + laplace_filtered = np.uint8(laplace_filtered) # Important for saving correctly + + # Save the resulting image + cv2.imwrite(output_path, laplace_filtered) + + print(f"Laplace edge detection complete. Image saved to {output_path}") + + except Exception as e: + print(f"An error occurred: {e}") + + +if __name__ == "__main__": + import numpy as np # Import here, only if needed for the main execution + input_path = sys.argv[1] + output_path = sys.argv[2] + laplace_edge_detection(input_path, output_path) diff --git a/resnet18_ciedge.pth b/resnet18_ciedge.pth new file mode 100644 index 000000000..3400d22b6 Binary files /dev/null and b/resnet18_ciedge.pth differ diff --git a/resnet18_cifake.pth b/resnet18_cifake.pth new file mode 100644 index 000000000..48a6398b9 Binary files /dev/null and b/resnet18_cifake.pth differ diff --git a/train_model_ciedge.py b/train_model_ciedge.py new file mode 100644 index 000000000..21b744a00 --- /dev/null +++ b/train_model_ciedge.py @@ -0,0 +1,85 @@ +import os +import torch +import torchvision +import torchvision.transforms as transforms +from torch.utils.data import DataLoader +from torchvision import datasets, models +import torch.nn as nn +import torch.optim as optim +from tqdm import tqdm # https://tqdm.github.io/ + +# https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +# ======= Settings ======= +DATA_DIR = "./CIEDGE" +BATCH_SIZE = 16 +NUM_CLASSES = 2 +NUM_EPOCHS = 10 +LEARNING_RATE = 1e-4 +DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +# ======= Transforms ======= +transform = transforms.Compose([ + transforms.Resize((224, 224)), # Ensure fixed input size + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], # ImageNet mean + [0.229, 0.224, 0.225]) # ImageNet std +]) + +# ======= Load Data ======= +train_dataset = datasets.ImageFolder(os.path.join(DATA_DIR, "train"), transform=transform) +test_dataset = datasets.ImageFolder(os.path.join(DATA_DIR, "test"), transform=transform) + +train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=True) +test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False, num_workers=2, pin_memory=True) + +# ======= Load Model ======= +model = models.resnet18(pretrained=True) +model.fc = nn.Linear(model.fc.in_features, NUM_CLASSES) +model = model.to(DEVICE) + +# ======= Loss and Optimizer ======= +criterion = nn.CrossEntropyLoss() +optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE) + +# ======= Training Loop ======= +for epoch in range(NUM_EPOCHS): + model.train() + running_loss = 0.0 + correct, total = 0, 0 + + loop = tqdm(train_loader, desc=f"Epoch {epoch+1}/{NUM_EPOCHS}") + for inputs, labels in loop: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() # Ensure tensor layout for MIOpen + + optimizer.zero_grad() + outputs = model(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + running_loss += loss.item() + _, predicted = torch.max(outputs, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + + loop.set_postfix(loss=loss.item(), acc=100. * correct / total) + +# ======= Evaluation ======= +model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in test_loader: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + +print(f"Test Accuracy: {100 * correct / total:.2f}%") + +# ======= Save Model ======= +torch.save(model.state_dict(), "resnet18_ciedge.pth") +# diff --git a/train_model_cifake.py b/train_model_cifake.py new file mode 100644 index 000000000..c3aab1f4b --- /dev/null +++ b/train_model_cifake.py @@ -0,0 +1,85 @@ +import os +import torch +import torchvision +import torchvision.transforms as transforms +from torch.utils.data import DataLoader +from torchvision import datasets, models +import torch.nn as nn +import torch.optim as optim +from tqdm import tqdm # https://tqdm.github.io/ + +# https://pytorch.org/tutorials/beginner/basics/quickstart_tutorial.html + +# ======= Settings ======= +DATA_DIR = "./CIFAKE" +BATCH_SIZE = 16 +NUM_CLASSES = 2 +NUM_EPOCHS = 10 +LEARNING_RATE = 1e-4 +DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu") + +# ======= Transforms ======= +transform = transforms.Compose([ + transforms.Resize((224, 224)), # Ensure fixed input size + transforms.ToTensor(), + transforms.Normalize([0.485, 0.456, 0.406], # ImageNet mean + [0.229, 0.224, 0.225]) # ImageNet std +]) + +# ======= Load Data ======= +train_dataset = datasets.ImageFolder(os.path.join(DATA_DIR, "train"), transform=transform) +test_dataset = datasets.ImageFolder(os.path.join(DATA_DIR, "test"), transform=transform) + +train_loader = DataLoader(train_dataset, batch_size=BATCH_SIZE, shuffle=True, num_workers=2, pin_memory=True) +test_loader = DataLoader(test_dataset, batch_size=BATCH_SIZE, shuffle=False, num_workers=2, pin_memory=True) + +# ======= Load Model ======= +model = models.resnet18(pretrained=True) +model.fc = nn.Linear(model.fc.in_features, NUM_CLASSES) +model = model.to(DEVICE) + +# ======= Loss and Optimizer ======= +criterion = nn.CrossEntropyLoss() +optimizer = optim.Adam(model.parameters(), lr=LEARNING_RATE) + +# ======= Training Loop ======= +for epoch in range(NUM_EPOCHS): + model.train() + running_loss = 0.0 + correct, total = 0, 0 + + loop = tqdm(train_loader, desc=f"Epoch {epoch+1}/{NUM_EPOCHS}") + for inputs, labels in loop: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() # Ensure tensor layout for MIOpen + + optimizer.zero_grad() + outputs = model(inputs) + loss = criterion(outputs, labels) + loss.backward() + optimizer.step() + + running_loss += loss.item() + _, predicted = torch.max(outputs, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + + loop.set_postfix(loss=loss.item(), acc=100. * correct / total) + +# ======= Evaluation ======= +model.eval() +correct, total = 0, 0 +with torch.no_grad(): + for inputs, labels in test_loader: + inputs, labels = inputs.to(DEVICE), labels.to(DEVICE) + inputs = inputs.contiguous() + outputs = model(inputs) + _, predicted = torch.max(outputs.data, 1) + total += labels.size(0) + correct += (predicted == labels).sum().item() + +print(f"Test Accuracy: {100 * correct / total:.2f}%") + +# ======= Save Model ======= +torch.save(model.state_dict(), "resnet18_cifake.pth") +#