From b465845bf7a3992e55561efdd569a9cbef02e56e Mon Sep 17 00:00:00 2001 From: Tanner Swanson Date: Mon, 3 Feb 2025 12:38:29 -0500 Subject: [PATCH] Adjusted Arguments and refactored code --- PopulateTrainingData.py | 57 ++++++++++++++---------- main.py | 98 +++++++++++++++++++++++++++-------------- 2 files changed, 99 insertions(+), 56 deletions(-) diff --git a/PopulateTrainingData.py b/PopulateTrainingData.py index b3cca48..3ab7e9f 100644 --- a/PopulateTrainingData.py +++ b/PopulateTrainingData.py @@ -1,4 +1,6 @@ import numpy as np +from numpy.random import default_rng +import skimage.exposure from perlin_noise import PerlinNoise import random import sys @@ -15,23 +17,37 @@ def ShipHull_Gen(): # creates a 256x256 map of gradient result_array = np.tile(row_values[:, None], (1, 256)) return PossibleAnomaly(result_array) # possibly add anomaly to the result -def Add_Anomaly(img, xSize, ySize, xPos, yPos, shape): - anomaly_size = (xSize, ySize) - center = (xPos, yPos) +def Add_Anomaly(img): + height, width = img.shape[:2] - mask = np.zeros_like(img, dtype=np.uint8) - - if (shape == 0): # ellipse - cv2.ellipse(mask, center, anomaly_size, angle=0, startAngle=0, endAngle=360, color=255, thickness=-1) - elif (shape == 1): #square - print("Unimpemeneted: square anomaly") - #return - elif (shape == 2): # other? - print("unimplemented: other anomaly") - #return - - img[mask == 255] = 1.0 # set all values in mask range to 1.0 - return img + # define random seed to change the pattern + seedval = random.randint(0, 100) + rng = default_rng(seed=seedval) + + # create random noise image + noise = rng.integers(0, 255, (height,width), np.uint8, True) + + # blur the noise image to control the size + blur = cv2.GaussianBlur(noise, (0,0), sigmaX=15, sigmaY=15, borderType = cv2.BORDER_DEFAULT) + + # stretch the blurred image to full dynamic range + stretch = skimage.exposure.rescale_intensity(blur, in_range='image', out_range=(0,255)).astype(np.uint8) + + # threshold stretched image to control the size + thresh = cv2.threshold(stretch, 175, 255, cv2.THRESH_BINARY)[1] + + # apply morphology open and close to smooth out and make 3 channels + kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9,9)) + mask = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel) + mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel) + mask = cv2.merge([mask,mask,mask]) + + # add mask to input + + print(img[1:]) + print(mask[1:]) + result = cv2.add(img, mask) + return result def WriteToFile(fileName, fileval): with open(fileName, "w") as f: @@ -46,18 +62,11 @@ def WriteToFile(fileName, fileval): def PossibleAnomaly(img): # TODO: - Xsize, Ysize = img.shape[0], img.shape[1] if random.randint(0, 1) == 1: # if random int = 1, we add anomaly print("Adding anomaly") - xPos = random.randint(0, Xsize) - yPos = random.randint(0, Ysize) - - shape = random.randint(0, 2) - - img = Add_Anomaly(img, Xsize, Ysize, xPos, yPos, shape) + img = Add_Anomaly(img) return img - if __name__ == "__main__": filePath = "TrainingData/" diff --git a/main.py b/main.py index f4fe5e7..7fb142a 100644 --- a/main.py +++ b/main.py @@ -1,11 +1,12 @@ import numpy as np from scipy.ndimage import gaussian_laplace, convolve import matplotlib -matplotlib.use('Agg') +#matplotlib.use('Agg') import matplotlib.pyplot as plt import cv2 import ast import sys +import argparse def get_anomaly_map(img, params): f_bank = np.zeros((img.shape[0], img.shape[1], params['n_scales'])) # create a filter bank @@ -32,37 +33,70 @@ def scale_up(img, target_shape): # scale back up for the filter bank img_su = cv2.resize(img, (target_shape[0], target_shape[1]), interpolation=cv2.INTER_LINEAR) return img_su + +def run_detection(fileLocation, clip): + with open(fileLocation, "r") as f: + strData = f.read() + npArray = np.array(ast.literal_eval(strData), dtype=np.float32) + + params = { + 'n_scales': 1, + 'scales': [1], # Scale factors + 'log_kernel': 1.5 # LoG kernel size + } + anomaly_map_value = get_anomaly_map(npArray, params) + if (clip == 1): + anomaly_map_value = np.clip(anomaly_map_value, 0, 1) + # limit range from 0 - 1. If outside, round to that value + elif (clip == 2): + anomaly_map_value = np.where(anomaly_map_value >= 0.5, 1, 0) + # set value to either 0 or 1. rounds up if >= 0.5, else down + return (npArray, anomaly_map_value) # returns original, and analyzed version for comparison. + +def display_result(orig, res, fileName): + #''' + fig, ax = plt.subplots(1, 2, figsize=(12, 6)) + + # Display the original map + ax[0].imshow(orig, cmap='hot') + ax[0].set_title("Original Map") + fig.colorbar(ax[0].imshow(orig, cmap='hot'), ax=ax[0]) + + # Display the anomaly map + ax[1].imshow(res, cmap='hot') + ax[1].set_title("Anomaly Map") + fig.colorbar(ax[1].imshow(res, cmap='hot'), ax=ax[1]) + + plt.tight_layout() # Adjust layout for better spacing + plt.show() + ''' + + plt.imshow(orig, cmap='hot') + plt.title("Original Map") + plt.colorbar() + plt.show() + #plt.savefig(f"OutputData/{fileName}_original") + + plt.imshow(res, cmap='hot') + plt.title("Anomaly Map") + plt.colorbar() + plt.show() + #plt.savefig(f"OutputData/{fileName}_analyzed")''' + + if __name__ == "__main__": - if (len(sys.argv) < 3): - print("Error!") + parser = argparse.ArgumentParser(description="Process some data with an optional clip argument.") + + parser.add_argument('-p', '--path', required=True, help="Path to the input file. Should be InputFolder.../...") + parser.add_argument('-c', '--clip', type=int, help="Integer 0-2 for clip value. 0 = none, 1 = standard, 2 = binary.", default=0) + args = parser.parse_args() + + if (args.clip not in [0, 1, 2]): + clipValue = 0 else: - inputData = sys.argv[1] - clippingValue = int(sys.argv[2]) - fileName = inputData.split("/")[1] # get the file name, drop the TrainingData/ + clipValue = args.clip - with open(inputData, "r") as f: - strData = f.read() - npArray = np.array(ast.literal_eval(strData), dtype=np.float32) - - params = { - 'n_scales': 1, - 'scales': [1], # Scale factors - 'log_kernel': 1.5 # LoG kernel size - } - - anomaly_map = get_anomaly_map(npArray, params) - anomaly_map_clipped = anomaly_map # dont clip - if clippingValue == 2: - anomaly_map_clipped = np.clip(anomaly_map, 0, 1) # limit range from 0 - 1. If outside, round to that value - elif clippingValue == 3: - anomaly_map_clipped = np.where(anomaly_map >= 0.5, 1, 0) # set value to either 0 or 1. rounds up if >= 0.5, else down - - plt.imshow(npArray, cmap='hot') - plt.title("Original Map") - plt.colorbar() - plt.savefig(f"OutputData/{fileName}_{clippingValue}_original") - - plt.imshow(anomaly_map_clipped, cmap='hot') - plt.title("Anomaly Map") - plt.colorbar() - plt.savefig(f"OutputData/{fileName}_{clippingValue}_analyzed") \ No newline at end of file + fileName = args.path.split("/")[-1] # get the file name from Path. Used to label output. + + (orig, res) = run_detection(args.path, args.clip) + display_result(orig, res, fileName) \ No newline at end of file