From b1ba61346820c9a4c4861f24375ac6af0f25e31f Mon Sep 17 00:00:00 2001 From: Mikayla Dobson <93477693+innocuous-symmetry@users.noreply.github.com> Date: Sat, 7 Jan 2023 19:53:23 -0600 Subject: [PATCH] to do: debug existing JSON file feature --- config.py | 40 +++++++++++++++++----------- formatresult.py | 69 ++++++++++++++++++++++++++++++++++--------------- main.py | 34 ++++++++++++------------ 3 files changed, 91 insertions(+), 52 deletions(-) diff --git a/config.py b/config.py index d93f237..7674334 100644 --- a/config.py +++ b/config.py @@ -3,10 +3,16 @@ import psycopg2 class Config: # store all user input - def __init__(self): - self.data_path = None - self.pg_config = None - self.sort_by_match_strength = False + def __init__(self, format=None): + if format: + self = format + else: + self.data_path: str = "" + self.pg_config = None + self.sort_by_match_strength: bool = False + + def __repr__(self): + return f"data path: {self.data_path}, pg_config: {self.pg_config}, sorted: {str(self.sort_by_match_strength)}" def run(self): """Completes new config process or uses an existing one. Dumps new data into a JSON file if it is generated, and returns either an old instance of `Config` or the new one as `self`""" @@ -15,14 +21,14 @@ class Config: if prev_config is not None: return prev_config else: - self.get_data_path() + self.receive_data_path() self.set_pg_config() self.output_formatting() with open("./config.json", "w") as outfile: json.dump(self.__encode(), outfile) return self else: - self.get_data_path() + self.receive_data_path() self.set_pg_config() self.output_formatting() with open("./config.json", "w") as outfile: @@ -35,26 +41,33 @@ class Config: response_for_prev_config = input("Use existing configuration file? y/n " ).lower() if response_for_prev_config == "y": - prev_data: Config = open("./config.json") - prev_data = json.load(prev_data) - return prev_data + with open("./config.json", "r") as infile: + config_data = json.load(infile) + + return Config(config_data) elif response_for_prev_config == "n": return None else: print("Invalid response.") self.handle_prev_config() - def get_data_path(self): + def receive_data_path(self): """Locates a valid directory from user input and stores it in Config state as `self.data_path`.""" data_path = input("Provide the location of the directory where we can find your photos: ") if not os.path.exists(data_path): print("We didn't find a directory by this name.") - self.data_path = self.get_data_path() + self.receive_data_path() else: print("Got it!") self.data_path = data_path + def get_data_path(self): + return self.data_path + + def set_data_path(self, value): + self.data_path = value + def set_pg_config(self): """Determine if data should be associated with a PostgreSQL instance, and, if so, record the required connection info""" elect_for_pg = input("Connect this program to a PostgreSQL instance? y/n ").lower() @@ -107,7 +120,4 @@ class Config: self.output_formatting() def __encode(self): - return json.dumps(self, default=lambda x: x.__dict__) - -new_config = Config() -new_config.run() \ No newline at end of file + return json.dumps(self, default=lambda x: x.__dict__) \ No newline at end of file diff --git a/formatresult.py b/formatresult.py index 2d18fec..5467599 100644 --- a/formatresult.py +++ b/formatresult.py @@ -1,47 +1,74 @@ import json, os, shutil +from config import Config -def format_result(src_path, json_path): +def format_result(app_config: Config, json_path): + # dictionary to hold and later display our results insertions_by_label = {} + data_path = app_config.data_path + + # if pg_config is not None, run the postgres prediction[0] of this code + pg_config = app_config.pg_config + + # if this is True, run the prediction[0] "for line in contents:" below + sort_by_match_strength = app_config.sort_by_match_strength + weak_results = 0 total_count = 0 + # store analysis results in contents with open(json_path) as results: contents = json.load(results) - for qualifier in ['strong', 'moderate', 'fair', 'weak']: - if not os.path.exists("./predictions/" + qualifier): - os.makedirs('./predictions/' + qualifier) + # prepare individual locations for match strengths if sort is enabled + if sort_by_match_strength: + for qualifier in ['strong', 'moderate', 'fair', 'weak']: + if not os.path.exists("./predictions/" + qualifier): + os.makedirs('./predictions/' + qualifier) + # handles data for each photo for line in contents: - img_path = src_path + line['path'] + img_path = data_path + line['path'] prediction = line['prediction'] - for section in prediction: - total_count += 1 - guess_label = section[0][1] - match_strength = 'weak/' - if float(section[0][2]) > 0.9: - match_strength = 'strong/' - elif float(section[0][2]) > 0.75: - match_strength = 'moderate/' - elif float(section[0][2]) > 0.5: - match_strength = 'fair/' - elif match_strength == 'weak/': - weak_results += 1 + # handles data for first prediction for a given photo + total_count += 1 + guess_label = prediction[0][0][1] + match_strength = 'weak' - if not guess_label in insertions_by_label: - insertions_by_label[guess_label] = 0 + # assign value for match strength + if float(prediction[0][0][2]) > 0.9: + match_strength = 'strong' + elif float(prediction[0][0][2]) > 0.7: + match_strength = 'moderate' + elif float(prediction[0][0][2]) > 0.4: + match_strength = 'fair' + elif match_strength == 'weak': + weak_results += 1 + # modify variable for path + match_strength = match_strength + "/" + + if not guess_label in insertions_by_label: + insertions_by_label[guess_label] = 0 + + # copy file to appropriate location, depending on if sorting + if sort_by_match_strength: if (not os.path.exists("./predictions/" + match_strength + guess_label)): os.makedirs("./predictions/" + match_strength + guess_label) - if (not os.path.exists('./predictions/' + match_strength + guess_label + '/' + img_path)): shutil.copy(img_path, "./predictions/" + match_strength + guess_label) insertions_by_label[guess_label] = insertions_by_label[guess_label] + 1 + else: + if (not os.path.exists("./predictions/" + guess_label)): + os.makedirs("./predictions/" + guess_label) + if (not os.path.exists('./predictions/' + guess_label + '/' + img_path)): + shutil.copy(img_path, "./predictions/" + guess_label) + insertions_by_label[guess_label] = insertions_by_label[guess_label] + 1 + print(str(weak_results) + " weak result(s) of a total " + str(total_count) + " input(s)\n") - print("By subject:\n\n") + print("By subject:\n") for k, v in insertions_by_label.items(): print(k + ": " + str(v) + " file(s) found") diff --git a/main.py b/main.py index 4249ed3..1cfe725 100644 --- a/main.py +++ b/main.py @@ -6,36 +6,30 @@ import os, json from config import Config from time import time -from predict import predict -from formatresult import format_result -from keras.applications.vgg16 import VGG16 -print("\n\nImage Sorting Utility\n") +print("\nImage Sorting Utility\n") print("Script by Mikayla Dobson\n") print("\n\n") ############################## CONFIG print("Running app config...") -appconfig = Config() +appconfig: Config = Config() config_file = appconfig.run() -############################## SETUP -############################## SETUP -############################## SETUP +if (config_file.get_data_path()[-1] != "/"): + config_file.set_data_path(config_file.get_data_path() + "/") # create the target directory if it doesn't exist if (not os.path.exists("./predictions")): print("Did not find predictions directory, creating...\n\n") os.makedirs("./predictions") -# receive directory path as CLI argument and get a list of all files in path -src_path = config_file.data_path +############################## SETUP +############################## SETUP +############################## SETUP -if (src_path[-1] != "/"): - src_path += "/" - -files = os.listdir(src_path) +files = os.listdir(config_file.data_path) # generate current time for use in identifying outfiles cur_time = str(int(time())) @@ -47,6 +41,14 @@ all_results = [] ############################## ANALYSIS ############################## ANALYSIS +print("Attempting TF imports...\n\n") + +from predict import predict +from formatresult import format_result +from keras.applications.vgg16 import VGG16 + +print("Success!") + # declare model to be used for each prediction model = VGG16(weights='imagenet') @@ -54,7 +56,7 @@ print("Running image analysis. This may take some time...\n\n") # for each file in directory, append its prediction result to main list for file in files: - result = predict(model, src_path + file) + result = predict(model, config_file.data_path + file) if result is not None: all_results.append({ "path": file, "prediction": result }) @@ -72,6 +74,6 @@ print("Analysis complete! Beginning sort process...\n\n") ############################## SORTING ############################## SORTING -format_result(src_path, json_path) +format_result(appconfig, json_path) print("File sort successful! Process complete.")