Skip to content

Commit

Permalink
big revive + partially translated paper
Browse files Browse the repository at this point in the history
  • Loading branch information
Rexicon226 committed Mar 22, 2024
1 parent 2814136 commit 8cf3b81
Show file tree
Hide file tree
Showing 28 changed files with 411 additions and 170 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*iso filter=lfs diff=lfs merge=lfs -text
*pth filter=lfs diff=lfs merge=lfs -text
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
__pycache__/
.ruff_cache/

Paper/*.aux
Paper/*.log
Paper/*.bbl
Paper/*.blg
Paper/*.pdf

q.log
1 change: 1 addition & 0 deletions .python-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3.11
15 changes: 2 additions & 13 deletions CombinedMapGenerator/generator.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
"""Generator used to make map pairs"""
import random
import numpy as np
import matplotlib.pyplot as plt
from Terrain.map import Map
import asyncio
class Generator():

class Generator:
def __init__(self, width, height, octaves=1):
self.width = width
self.height = height
self.octaves = octaves

def generate_solveable_pair(self ):
"""Generates a map pair that is solveable"""
real = Map.solveable_map(self.width, self.height, self.octaves)
predicted = real + Map.built(self.width, self.height, self.octaves)


58 changes: 35 additions & 23 deletions CompositeEnvironment.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@

from Terrain import generator
import matplotlib.pyplot as plt
from ML.dnoise import EncoderDecoder as ed
from DNoise.dnoise import EncoderDecoder as ed
import torch
from torch import nn

Image = np.ndarray


class MAELoss(nn.Module):
def __init__(self):
Expand All @@ -22,20 +24,26 @@ def forward(self, y_pred, y_true):


class Environment:
def __init__(self, image, noisy, radius, center=None):
def __init__(
self, image: Image, noisy: Image, radius: int, center: None | tuple
) -> None:
self.image = image.copy()
self.radius = radius
self.noisy_image = noisy.copy()
self.center = center

def generate(self):
masked = get_visible_image(self.image, self.radius, self.noisy_image, self.center)
def generate(self) -> Image:
masked = get_visible_image(
self.image, self.radius, self.noisy_image, self.center
)
return masked


def create_circular_mask(h, w, radius, center=None):
def create_circular_mask(
h: int, w: int, radius: int, center: None | tuple = None
) -> np.ndarray:
if center is None: # use the middle of the image
center = (int(w / 2), int(h / 2))
center = (w / 2, h / 2)

y, x = np.ogrid[:h, :w]
dist_from_center = np.sqrt((x - center[0]) ** 2 + (y - center[1]) ** 2)
Expand All @@ -44,7 +52,9 @@ def create_circular_mask(h, w, radius, center=None):
return mask


def get_visible_image(image, radius, noisy, center):
def get_visible_image(
image: Image, radius: int, noisy: Image, center: None | tuple
) -> Image:
# Find the size of the image
image = np.abs(image)

Expand All @@ -64,12 +74,10 @@ def get_visible_image(image, radius, noisy, center):


class Visualizer:

def __init__(self, model_path, original):

self.model_path = model_path
self.original = original.copy()
self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
self.device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

def dNoiseVis(self, inputpic):
print("Loaded Model")
Expand All @@ -94,17 +102,22 @@ def dNoiseVis(self, inputpic):
de_noised_image = de_noised_image.cpu().numpy()
print("Processed Image")
fig, ax = plt.subplots(2, 2)
ax[0][0].imshow(de_noised_image, cmap='plasma_r')
ax[0][0].set_title('De-Noised Image')
ax[0][1].imshow(inputpic, cmap='plasma_r')
ax[0][1].set_title('Input')
ax[1][0].imshow(self.original, cmap='plasma_r')
ax[1][0].set_title('Clean Image')
ax[0][0].imshow(de_noised_image, cmap="plasma_r")
ax[0][0].set_title("De-Noised Image")
ax[0][1].imshow(inputpic, cmap="plasma_r")
ax[0][1].set_title("Noisy Image")
ax[1][0].imshow(self.original, cmap="plasma_r")
ax[1][0].set_title("Ground Image")
ax[1][1].hist(de_noised_image, bins=25)
ax[1][1].set_title('De-Noised Image Histogram')

fig.suptitle("Image Size: 256 x 256\nNoise Level: {}%\nAccuracy: {:.2f}%".format(noise_level, loss),
fontsize=16, y=0.9)
ax[1][1].set_title("De-Noised Image Histogram")

fig.suptitle(
"Image Size: 256 x 256\nNoise Level: {}%\nAccuracy: {:.2f}%".format(
noise_level, loss
),
fontsize=16,
y=0.9,
)
plt.show()

def dNoise(self, image):
Expand Down Expand Up @@ -141,16 +154,15 @@ def thresholdDNoise(input, x):
seed = random.randint(1, 100000000000)
x = random.randint(50, 200)
y = random.randint(50, 200)
noise_level = 30
noise_level = 80
print("({}, {})".format(x, y))
pic = np.array(generator.generateClean(256, 256, 5, seed, True))
noisy_pic = np.array(generator.generateNoise(256, 256, 5, noise_level, seed, True))
pic, noisy_pic = np.abs(pic), np.abs(noisy_pic)

ev = Environment(pic, noisy_pic, 50, center=(x, y))

masked = ev.generate()

vi = Visualizer('./ML/models/synthnav-model-0.pth', pic)
vi = Visualizer("./DNoise/models/synthnav-model-0.pth", pic)

vi.dNoiseVis(masked)
7 changes: 3 additions & 4 deletions ML/array2img.py → DNoise/array2img.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
import math
from Terrain import timers
import os
import cv2


def array2image(x, y, octaves, weight, seed: int = 0, iD: int = 0):
Expand All @@ -22,7 +21,7 @@ def array2image(x, y, octaves, weight, seed: int = 0, iD: int = 0):
print(img)
timer.stop()
timer = timers.FunctionTimer("Clean - Image Save")
img.save('./val_images/clean/' + str(iD) + '_clean.jpeg', bits=1, optimize=True)
img.save("./val_images/clean/" + str(iD) + "_clean.jpeg", bits=1, optimize=True)
timer.stop()
timer = timers.FunctionTimer("Noisy - Generate")
array = generator.generateNoise(x, y, octaves, weight, seed)
Expand All @@ -32,7 +31,7 @@ def array2image(x, y, octaves, weight, seed: int = 0, iD: int = 0):
img = PIL.Image.fromarray(bool_array)
timer.stop()
timer = timers.FunctionTimer("Noisy - Image Save")
img.save('./val_images/noisy/' + str(iD) + '_noisy.jpeg', bits=1, optimize=True)
img.save("./val_images/noisy/" + str(iD) + "_noisy.jpeg", bits=1, optimize=True)
timer.stop()


Expand All @@ -53,7 +52,7 @@ def convert_to_1bit(input_dir, output_dir):
print("Uncertain Image")
bool_array = np.array(img_array, dtype=bool)
img = PIL.Image.fromarray(bool_array)
img.save('./train_images/noisy/' + file, bits=1, optimize=True)
img.save("./train_images/noisy/" + file, bits=1, optimize=True)


threshold = 128
Expand Down
70 changes: 38 additions & 32 deletions ML/dnoise.py → DNoise/dnoise.py
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
import os.path
from pathlib import Path

import matplotlib.pyplot as plt
import numpy as np
import torch.nn as nn
import torch.utils.data
import torchsummary

device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print("Device: {}\n".format(device))


# 2. Define the CNN model
# Define the encoder-decoder model
class EncoderDecoder(nn.Module):
def __init__(self):
super(EncoderDecoder, self).__init__()
Expand All @@ -24,15 +21,15 @@ def __init__(self):
nn.ReLU(),
nn.MaxPool2d(2),
nn.Conv2d(64, 128, 3, padding=1),
nn.ReLU()
nn.ReLU(),
)

self.decoder = nn.Sequential(
nn.Conv2d(128, 64, 3, padding=1),
nn.ReLU(),
nn.ConvTranspose2d(64, 32, kernel_size=4, stride=2, padding=1),
nn.ReLU(),
nn.Conv2d(32, 1, 3, padding=1)
nn.Conv2d(32, 1, 3, padding=1),
)

def forward(self, x):
Expand All @@ -52,18 +49,18 @@ def forward(self, y_pred, y_true):


def saveModel(model, model_name):
torch.save(model.state_dict(), './models/{}'.format(model_name))
model_scripted = torch.jit.script(model) # Export to TorchScript
model_scripted.save('./models/synthnav-model-script.pt')
torch.save(model.state_dict(), "./models/{}".format(model_name))
model_scripted = torch.jit.script(model) # Export to TorchScript
model_scripted.save("./models/synthnav-model-script.pt")


def main():
loss_array = list()
# print(summary(model, (1, 1, 256, 256)))

if os.path.exists('./models/{}'.format(model_name)):
# Only load the model if it already exists
if os.path.exists("./models/{}".format(model_name)):
print("Loaded Model")
model.load_state_dict(torch.load(f='./models/{}'.format(model_name)))
model.load_state_dict(torch.load(f="./models/{}".format(model_name)))

# Create an instance of the custom MSE loss function
criterion = MAELoss()
Expand All @@ -76,14 +73,16 @@ def create_synced_dictionary(folder_name):
for sub_folder in folder[1]:
for file in os.listdir(os.path.join(folder_name, sub_folder)):
try:
name, image_type = file.split('_')
name, image_type = file.split("_")
except ValueError:
continue



except:
return
if image_type == 'clean.jpeg':
if image_type == "clean.jpeg":
# Add the clean image to the dictionary
sync_dir_inner[name] = file
elif image_type == 'noisy.jpeg':
elif image_type == "noisy.jpeg":
# Check if there is already a clean image for this pair in the dictionary
if name in sync_dir_inner:
# Add the noisy image to the dictionary
Expand All @@ -96,10 +95,10 @@ def create_synced_dictionary(folder_name):

dirname = os.path.dirname(__file__)

high_quality = os.path.join(dirname, 'train_images')
sync_dir = create_synced_dictionary('train_images')
high_quality = os.path.join(dirname, "train_images")
sync_dir = create_synced_dictionary("train_images")

val_dir = os.path.join(dirname, 'val_images')
val_dir = os.path.join(dirname, "val_images")
val_sync = create_synced_dictionary(val_dir)

# Training loop
Expand Down Expand Up @@ -136,8 +135,15 @@ def create_synced_dictionary(folder_name):
loss_array.append(loss.item())

if (i + 1) % batch_size == 0:
print("Epoch: {}/{}, Batch: {}/{}, Loss: {:.4f}%".format(epoch + 1, num_epochs, i + 1, batch_size,
(1 - loss.item()) * 100))
print(
"Epoch: {}/{}, Batch: {}/{}, Loss: {:.4f}%".format(
epoch + 1,
num_epochs,
i + 1,
batch_size,
(1 - loss.item()) * 100,
)
)
i += 1

if (epoch + 1) % 20 == 0:
Expand Down Expand Up @@ -192,22 +198,22 @@ def visualize_predictions(model, val_sync, val_dir):
noisy_image = noisy_image.cpu()
noisy_image = noisy_image.detach().numpy()

cmap = 'plasma_r'
cmap = "plasma_r"

# Visualize the clean, noisy, and de-noised images
fig, axs = plt.subplots(2, 3)
axs[0, 0].imshow(clean_image, cmap=cmap)
axs[0, 0].set_title('Input (Clean)')
axs[0, 0].set_title("Input (Clean)")
axs[1, 0].imshow(clean_deionised, cmap=cmap)
axs[1, 0].set_title('Output (Clean)')
axs[1, 0].set_title("Output (Clean)")
axs[0, 1].imshow(noisy_image, cmap=cmap)
axs[0, 1].set_title('Input (Noisy)')
axs[0, 1].set_title("Input (Noisy)")
axs[1, 1].imshow(de_noised_image, cmap=cmap)
axs[1, 1].set_title('Output (Noisy)')
axs[1, 1].set_title("Output (Noisy)")
axs[0, 2].imshow(clean_image - noisy_image, cmap=cmap)
axs[0, 2].set_title('Input Difference')
axs[0, 2].set_title("Input Difference")
axs[1, 2].imshow(clean_deionised - de_noised_image, cmap=cmap)
axs[1, 2].set_title('Output Difference')
axs[1, 2].set_title("Output Difference")
plt.show()
vis_iter = 1

Expand Down Expand Up @@ -242,11 +248,11 @@ def loss_graph(loss_array):
# Iterate directory
dirname = os.path.dirname(__file__)

high_quality = os.path.join(dirname, 'train_images/noisy')
model_name = 'synthnav-model-0.pth'
high_quality = os.path.join(dirname, "train_images/noisy")
model_name = "synthnav-model-0.pth"
for path in os.listdir(high_quality):
# check if current path is a file
if os.path.isfile(os.path.join('train_images/noisy', path)):
if os.path.isfile(os.path.join("train_images/noisy", path)):
count += 1

batch_size = 128
Expand Down
Loading

0 comments on commit 8cf3b81

Please sign in to comment.