diff --git a/requirements.txt b/requirements.txt index 643f072..7e35ed2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -5,4 +5,3 @@ opencv-python==4.7.0.72 scikit-image==0.19.3 scipy==1.9.3 stl==0.0.3 - diff --git a/src/main.py b/src/main.py index 105aa96..447e862 100644 --- a/src/main.py +++ b/src/main.py @@ -8,6 +8,7 @@ import argparse as ap import sys import json from os.path import exists +import hashlib # Libraries for image processing import numpy as np @@ -18,7 +19,6 @@ from stl import mesh # Import custom image filter library import filters as flt - class app: def __init__(self): # Parse arguments from command line @@ -286,7 +286,7 @@ class app: plt.show() self.save_stl() - print(f"Saving model to ", self.stl_path, file=sys.stderr) + print(f"Saving model to ", self.stl_filename, file=sys.stderr) def prepare_heightmap(self): '''Modify image values to get usable height/depth values. @@ -327,18 +327,70 @@ class app: self.meshgrid = np.meshgrid(x, y) + def write_stl_header(self): + '''Write stl header. + ''' + + # Truncate if necessary + if (len(self.param_string) > 80): + self.param_string = self.param_string[:80] + print("Warning: Parameter string too long, truncating", file=sys.stderr) + + # Overwrite stl header (which is only 80 bytes) + print("Writing info to stl header", file=sys.stderr) + with open(self.stl_filename, "r+") as f: + f.write(self.param_string) + def get_ID(self): - '''Get unique ID for the model. - Consists of pair input_file + preset_name. + '''Get unique ID for the model, used in filename and on the model backside. + Also create parameter string for stl header, which is used to create ID using hash function SHA512. ''' - # TODO: somehow compress this to fit it onto the model - self.id = self.input_file.split("/")[-1].split(".")[0] + "_" + self.preset_name - # TODO: hash is not unique, find a better way - # TODO: stl file format has 80 chars for header, use that space to store info - # python generates a random value for security reasons, it has to be turned off - self.id = str(hash(self.id)) - #print(self.id) + # these are the same for all types of models + param_list = [self.input_file, str(self.dpi)] + + # add parameters specific to the model creation process + if self.args.config: + param_list.append(self.config_file) + param_list.append(self.preset_name) + else: + # add filters with their params + filter_list = [] + for i in range(len(self.filters)): + tmp_params = [] + for j in self.params[i+1]: + if self.params[i+1][j] != None: + tmp_params.append(str(j[:3] + ":" + str(self.params[i+1][j]))) + tmp_params = ",".join(tmp_params) + tmp = str(self.filters[i][0:3]) + if tmp_params != "": + tmp = tmp + ";" + str(tmp_params) + filter_list.append(tmp) + filter_string = ">".join(filter_list) + param_list.append(filter_string) + + # these are the same for all types of models + param_list.append(str(self.height_line)) + param_list.append(str(self.height_base)) + + # add parameters specific to the model type + if self.mode == "curved": + param_list.append(str(self.curv_rate_x)) + param_list.append(str(self.curv_rate_y)) + + if self.mode == "planar": + param_list.append("P") + + if self.args.mirror: + param_list.append("M") + + # string that will later be put inside the header of an stl file + self.param_string = "\\".join(param_list) + "\n" + + # hash the param string to get unique ID, this will be put in filename and on the back of the model + # not using built-in hash function because it's seed cannot be set to constant number + # don't need to worry about collisions and security, just need a relatively unique ID + self.id = str(hashlib.sha512(self.param_string.encode('utf-8')).hexdigest())[:10] def append_faces(self, faces, c): # Function to add faces to the list @@ -501,7 +553,7 @@ class app: count = self.append_faces(faces, count) self.create_stl_mesh(faces, vertices) - + def make_stl_curved(self): '''Map fingerprint to finger model. ''' @@ -612,18 +664,10 @@ class app: '''Save final mesh to stl file. ''' - # TODO: add a hash function to create ID specific to - # input image + preset from config. file or from console + input params - # TODO: add the full parameters and filters to a file inside output dir. - # TODO: somehow add the full params to the stl file header if possible. - # TODO: add the ID to backplate - # TODO: add the ID to stl file name - - # for now only path + id(input filename + preset name) + .stl is used - # TODO: add output filename to the filename, hash the ID - # stl_filename = self.stl_path.rsplit("/")[0] + self.output_file.split("/"))[-1] + "_" + self.id + ".stl" - stl_filename = self.output_file.split(".")[0] + "_" + self.id + ".stl" - self.stl_model.save(stl_filename) + # create output file name, save it and write header with file info + self.stl_filename = self.output_file.split(".")[0] + "_" + self.id + ".stl" + self.stl_model.save(self.stl_filename) + self.write_stl_header() # run the application