autoforge 1.7.4__tar.gz → 1.7.6__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. {autoforge-1.7.4 → autoforge-1.7.6}/PKG-INFO +11 -4
  2. {autoforge-1.7.4 → autoforge-1.7.6}/README.md +10 -3
  3. {autoforge-1.7.4 → autoforge-1.7.6}/pyproject.toml +1 -1
  4. {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/PKG-INFO +11 -4
  5. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/FilamentHelper.py +43 -10
  6. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/OutputHelper.py +10 -10
  7. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/auto_forge.py +127 -80
  8. {autoforge-1.7.4 → autoforge-1.7.6}/setup.cfg +0 -0
  9. {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/SOURCES.txt +0 -0
  10. {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/dependency_links.txt +0 -0
  11. {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/entry_points.txt +0 -0
  12. {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/requires.txt +0 -0
  13. {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/top_level.txt +0 -0
  14. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/__init__.py +0 -0
  15. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/Views/__init__.py +0 -0
  16. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/Views/backend_database.py +0 -0
  17. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/Views/filament_editor.py +0 -0
  18. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/app.py +0 -0
  19. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/main.py +0 -0
  20. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/CAdamW.py +0 -0
  21. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/ChristofidesHeightMap.py +0 -0
  22. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/DepthEstimateHeightMap.py +0 -0
  23. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/OldHeightmap.py +0 -0
  24. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/__init__.py +0 -0
  25. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/ImageHelper.py +0 -0
  26. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/OptimizerHelper.py +0 -0
  27. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/PruningHelper.py +0 -0
  28. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/__init__.py +0 -0
  29. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/filamentcolors_library.py +0 -0
  30. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Init_comparer/__init__.py +0 -0
  31. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Init_comparer/auto_forge_init_check.py +0 -0
  32. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Init_comparer/plot_results.py +0 -0
  33. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Loss/LossFunctions.py +0 -0
  34. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Loss/PerceptionLoss.py +0 -0
  35. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Loss/__init__.py +0 -0
  36. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Misc/__init__.py +0 -0
  37. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Misc/color_fit_all.py +0 -0
  38. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Modules/Optimizer.py +0 -0
  39. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Modules/__init__.py +0 -0
  40. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/__init__.py +0 -0
  41. {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/__main__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AutoForge
3
- Version: 1.7.4
3
+ Version: 1.7.6
4
4
  Summary: AutoForge is a Python tool for generating 3D printed layered models from an input image.
5
5
  Author-email: Hendric Voss <hvoss@techfak.uni-bielefeld.de>
6
6
  License: CC BY-NC-SA 4.0
@@ -26,7 +26,7 @@ Requires-Dist: joblib>=1.4.2
26
26
 
27
27
  # AutoForge
28
28
 
29
- AutoForge is a Python tool for generating 3D printed layered models from an input image. Using a learned optimization strategy with a Gumbel softmax formulation, AutoForge assigns materials per layer and produces both a discretized composite image and a 3D-printable STL file. It also generates swap instructions to guide the printer through material changes during a multi-material print. \
29
+ AutoForge is a Python tool for generating 3D printed layered models from an input image. Using a learned optimization strategy with a Gumbel softmax formulation, AutoForge assigns materials per layer and produces both a discretized composite image and a 3D-printable STL file. It also generates swap instructions to guide the printer through material changes during a multi-material print.
30
30
 
31
31
  **TLDR:** It uses a picture to generate a 3D layer image that you can print with a 3d printer. Similar to [Hueforge](https://shop.thehueforge.com/), but without the manual work (and without the artistic control).
32
32
 
@@ -97,11 +97,16 @@ The script is run from the command line and accepts several arguments. Below is
97
97
  > **Note:** You will need [Hueforge](https://shop.thehueforge.com/) installed to export your filament CSV.
98
98
  > To get your CSV file, simply go to the "Filaments" menu in Hueforge, click the export button, select your filaments, and export them as a CSV file.
99
99
 
100
-
101
100
  ```bash
102
101
  autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
103
102
  ```
104
103
 
104
+ We also support json files. If you want to use your personal Hueforge library (found in %APPDATA%\HueForge\Filaments\personal_library.json) you can run the command with:
105
+ ```bash
106
+ autoforge --input_image path/to/input_image.jpg --json_file %APPDATA%\HueForge\Filaments\personal_library.json
107
+ ```
108
+
109
+
105
110
  > If you want to limit the amount of colors the program can use, you can set these as command line arguments. \
106
111
  > For Example: 8 colors and a maximum of 20 swaps:
107
112
 
@@ -116,7 +121,9 @@ autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
116
121
 
117
122
 
118
123
  - `--input_image` **(Required)** Path to the input image.
119
- - `--csv_file` **(Required)** Path to the CSV file containing material data. The CSV should include columns for the brand, name, color (hex code), and TD values.
124
+ - `--csv_file` Path to the CSV file containing material data. The CSV should include columns for the brand, name, color (hex code), and TD values.
125
+ - `--json_file` Path to the json file containing material data. \
126
+ **Note:** Either a csv or json file has to be given.
120
127
 
121
128
  - `--output_folder` Folder where output files will be saved (default: `output`).
122
129
  - `--iterations` Number of optimization iterations (default: 2000).
@@ -1,6 +1,6 @@
1
1
  # AutoForge
2
2
 
3
- AutoForge is a Python tool for generating 3D printed layered models from an input image. Using a learned optimization strategy with a Gumbel softmax formulation, AutoForge assigns materials per layer and produces both a discretized composite image and a 3D-printable STL file. It also generates swap instructions to guide the printer through material changes during a multi-material print. \
3
+ AutoForge is a Python tool for generating 3D printed layered models from an input image. Using a learned optimization strategy with a Gumbel softmax formulation, AutoForge assigns materials per layer and produces both a discretized composite image and a 3D-printable STL file. It also generates swap instructions to guide the printer through material changes during a multi-material print.
4
4
 
5
5
  **TLDR:** It uses a picture to generate a 3D layer image that you can print with a 3d printer. Similar to [Hueforge](https://shop.thehueforge.com/), but without the manual work (and without the artistic control).
6
6
 
@@ -71,11 +71,16 @@ The script is run from the command line and accepts several arguments. Below is
71
71
  > **Note:** You will need [Hueforge](https://shop.thehueforge.com/) installed to export your filament CSV.
72
72
  > To get your CSV file, simply go to the "Filaments" menu in Hueforge, click the export button, select your filaments, and export them as a CSV file.
73
73
 
74
-
75
74
  ```bash
76
75
  autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
77
76
  ```
78
77
 
78
+ We also support json files. If you want to use your personal Hueforge library (found in %APPDATA%\HueForge\Filaments\personal_library.json) you can run the command with:
79
+ ```bash
80
+ autoforge --input_image path/to/input_image.jpg --json_file %APPDATA%\HueForge\Filaments\personal_library.json
81
+ ```
82
+
83
+
79
84
  > If you want to limit the amount of colors the program can use, you can set these as command line arguments. \
80
85
  > For Example: 8 colors and a maximum of 20 swaps:
81
86
 
@@ -90,7 +95,9 @@ autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
90
95
 
91
96
 
92
97
  - `--input_image` **(Required)** Path to the input image.
93
- - `--csv_file` **(Required)** Path to the CSV file containing material data. The CSV should include columns for the brand, name, color (hex code), and TD values.
98
+ - `--csv_file` Path to the CSV file containing material data. The CSV should include columns for the brand, name, color (hex code), and TD values.
99
+ - `--json_file` Path to the json file containing material data. \
100
+ **Note:** Either a csv or json file has to be given.
94
101
 
95
102
  - `--output_folder` Folder where output files will be saved (default: `output`).
96
103
  - `--iterations` Number of optimization iterations (default: 2000).
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "AutoForge"
7
- version="1.7.4"
7
+ version="1.7.6"
8
8
  description = "AutoForge is a Python tool for generating 3D printed layered models from an input image."
9
9
  authors = [{ name = "Hendric Voss", email = "hvoss@techfak.uni-bielefeld.de" }]
10
10
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AutoForge
3
- Version: 1.7.4
3
+ Version: 1.7.6
4
4
  Summary: AutoForge is a Python tool for generating 3D printed layered models from an input image.
5
5
  Author-email: Hendric Voss <hvoss@techfak.uni-bielefeld.de>
6
6
  License: CC BY-NC-SA 4.0
@@ -26,7 +26,7 @@ Requires-Dist: joblib>=1.4.2
26
26
 
27
27
  # AutoForge
28
28
 
29
- AutoForge is a Python tool for generating 3D printed layered models from an input image. Using a learned optimization strategy with a Gumbel softmax formulation, AutoForge assigns materials per layer and produces both a discretized composite image and a 3D-printable STL file. It also generates swap instructions to guide the printer through material changes during a multi-material print. \
29
+ AutoForge is a Python tool for generating 3D printed layered models from an input image. Using a learned optimization strategy with a Gumbel softmax formulation, AutoForge assigns materials per layer and produces both a discretized composite image and a 3D-printable STL file. It also generates swap instructions to guide the printer through material changes during a multi-material print.
30
30
 
31
31
  **TLDR:** It uses a picture to generate a 3D layer image that you can print with a 3d printer. Similar to [Hueforge](https://shop.thehueforge.com/), but without the manual work (and without the artistic control).
32
32
 
@@ -97,11 +97,16 @@ The script is run from the command line and accepts several arguments. Below is
97
97
  > **Note:** You will need [Hueforge](https://shop.thehueforge.com/) installed to export your filament CSV.
98
98
  > To get your CSV file, simply go to the "Filaments" menu in Hueforge, click the export button, select your filaments, and export them as a CSV file.
99
99
 
100
-
101
100
  ```bash
102
101
  autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
103
102
  ```
104
103
 
104
+ We also support json files. If you want to use your personal Hueforge library (found in %APPDATA%\HueForge\Filaments\personal_library.json) you can run the command with:
105
+ ```bash
106
+ autoforge --input_image path/to/input_image.jpg --json_file %APPDATA%\HueForge\Filaments\personal_library.json
107
+ ```
108
+
109
+
105
110
  > If you want to limit the amount of colors the program can use, you can set these as command line arguments. \
106
111
  > For Example: 8 colors and a maximum of 20 swaps:
107
112
 
@@ -116,7 +121,9 @@ autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
116
121
 
117
122
 
118
123
  - `--input_image` **(Required)** Path to the input image.
119
- - `--csv_file` **(Required)** Path to the CSV file containing material data. The CSV should include columns for the brand, name, color (hex code), and TD values.
124
+ - `--csv_file` Path to the CSV file containing material data. The CSV should include columns for the brand, name, color (hex code), and TD values.
125
+ - `--json_file` Path to the json file containing material data. \
126
+ **Note:** Either a csv or json file has to be given.
120
127
 
121
128
  - `--output_folder` Folder where output files will be saved (default: `output`).
122
129
  - `--iterations` Number of optimization iterations (default: 2000).
@@ -1,11 +1,14 @@
1
+ import sys
2
+ import traceback
1
3
  import uuid
2
4
 
3
5
  import numpy as np
4
6
  import pandas as pd
5
7
  import torch
8
+ import json
6
9
 
7
10
 
8
- def load_materials(csv_filename):
11
+ def load_materials(args):
9
12
  """
10
13
  Load material data from a CSV file.
11
14
 
@@ -19,13 +22,13 @@ def load_materials(csv_filename):
19
22
  - material_names (list): List of material names.
20
23
  - colors_list (list): List of color hex strings.
21
24
  """
22
- df = pd.read_csv(csv_filename)
25
+ df = load_materials_pandas(args)
23
26
  material_names = [
24
- brand + " - " + name
25
- for brand, name in zip(df["Brand"].tolist(), df[" Name"].tolist())
27
+ str(brand) + " - " + str(name)
28
+ for brand, name in zip(df["Brand"].tolist(), df["Name"].tolist())
26
29
  ]
27
- material_TDs = (df[" TD"].astype(float)).to_numpy()
28
- colors_list = df[" Color"].tolist()
30
+ material_TDs = (df["Transmissivity"].astype(float)).to_numpy()
31
+ colors_list = df["Color"].tolist()
29
32
  # Use float64 for material colors.
30
33
  material_colors = np.array(
31
34
  [hex_to_rgb(color) for color in colors_list], dtype=np.float64
@@ -33,8 +36,38 @@ def load_materials(csv_filename):
33
36
  material_TDs = np.array(material_TDs, dtype=np.float64)
34
37
  return material_colors, material_TDs, material_names, colors_list
35
38
 
36
-
37
- def load_materials_data(csv_filename):
39
+ def load_materials_pandas(args):
40
+ csv_filename = args.csv_file
41
+ json_filename = args.json_file
42
+
43
+ if csv_filename != "":
44
+ try:
45
+ df = pd.read_csv(csv_filename)
46
+ except Exception as e:
47
+ traceback.print_exc()
48
+ print("Error reading filament CSV file:", e)
49
+ sys.exit(1)
50
+ # rename all columns that start with a whitespace
51
+ df.columns = [col.strip() for col in df.columns]
52
+ # if TD in columns rename to Transmissivity
53
+ if "TD" in df.columns:
54
+ df.rename(columns={"TD": "Transmissivity"}, inplace=True)
55
+ else:
56
+ # read json
57
+ with open(json_filename, "r") as f:
58
+ data = json.load(f)
59
+ if "Filaments" in data.keys():
60
+ data = data["Filaments"]
61
+ else:
62
+ print(
63
+ "Warning: No Filaments key found in JSON data. We can't use this json data."
64
+ )
65
+ sys.exit(1)
66
+ # list to dataframe
67
+ df = pd.DataFrame(data)
68
+ return df
69
+
70
+ def load_materials_data(args):
38
71
  """
39
72
  Load the full material data from the CSV file.
40
73
 
@@ -45,7 +78,7 @@ def load_materials_data(csv_filename):
45
78
  list: A list of dictionaries (one per material) with keys such as
46
79
  "Brand", "Type", "Color", "Name", "TD", "Owned", and "Uuid".
47
80
  """
48
- df = pd.read_csv(csv_filename)
81
+ df = load_materials_pandas(args)
49
82
  # Use a consistent key naming. For example, convert 'TD' to 'Transmissivity' and 'Uuid' to 'uuid'
50
83
  records = df.to_dict(orient="records")
51
84
  return records
@@ -79,7 +112,7 @@ def extract_colors_from_swatches(swatch_data):
79
112
  out[(brand, name)] = (color, td)
80
113
 
81
114
  # convert to the same format as the hueforge csv files
82
- material_names = [brand + " - " + name for (brand, name) in out.keys()]
115
+ material_names = [str(brand) + " - " + str(name) for (brand, name) in out.keys()]
83
116
  material_colors = np.array(
84
117
  [hex_to_rgb("#" + color) for color, _ in out.values()], dtype=np.float64
85
118
  )
@@ -81,7 +81,7 @@ def generate_project_file(
81
81
  background_layers = int(args.background_height / args.layer_height)
82
82
 
83
83
  # Load full material data from CSV
84
- material_data = load_materials_data(csv_filename)
84
+ material_data = load_materials_data(args)
85
85
 
86
86
  # Extract the swap points from the discrete solution
87
87
  filament_indices, slider_values = extract_filament_swaps(
@@ -95,17 +95,17 @@ def generate_project_file(
95
95
  mat = material_data[idx]
96
96
  filament_entry = {
97
97
  "Brand": mat["Brand"],
98
- "Color": mat[" Color"],
99
- "Name": mat[" Name"],
98
+ "Color": mat["Color"],
99
+ "Name": mat["Name"],
100
100
  # Convert Owned to a boolean (in case it is read as a string)
101
- "Owned": str(mat[" Owned"]).strip().lower() == "true"
102
- if " Owned" in mat
101
+ "Owned": str(mat["Owned"]).strip().lower() == "true"
102
+ if "Owned" in mat
103
103
  else False,
104
- "Transmissivity": float(mat[" TD"])
105
- if not float(mat[" TD"]).is_integer()
106
- else int(mat[" TD"]),
107
- "Type": mat[" Type"] if " Type" in mat else "PLA",
108
- "uuid": mat[" Uuid"] if " Uuid" in mat else str(uuid.uuid4()),
104
+ "Transmissivity": float(mat["Transmissivity"])
105
+ if not float(mat["Transmissivity"]).is_integer()
106
+ else int(mat["Transmissivity"]),
107
+ "Type": mat["Type"] if "Type" in mat else "PLA",
108
+ "uuid": mat["Uuid"] if "Uuid" in mat else str(uuid.uuid4()),
109
109
  }
110
110
  filament_set.append(filament_entry)
111
111
 
@@ -8,6 +8,7 @@ import torch
8
8
  import numpy as np
9
9
  from tqdm import tqdm
10
10
 
11
+
11
12
  from autoforge.Helper.FilamentHelper import hex_to_rgb, load_materials
12
13
  from autoforge.Helper.Heightmaps.ChristofidesHeightMap import (
13
14
  run_init_threads,
@@ -43,9 +44,15 @@ def main():
43
44
  parser.add_argument(
44
45
  "--csv_file",
45
46
  type=str,
46
- required=True,
47
+ default="",
47
48
  help="Path to CSV file with material data",
48
49
  )
50
+ parser.add_argument(
51
+ "--json_file",
52
+ type=str,
53
+ default="",
54
+ help="Path to json file with material data",
55
+ )
49
56
  parser.add_argument(
50
57
  "--output_folder", type=str, default="output", help="Folder to write outputs"
51
58
  )
@@ -128,9 +135,17 @@ def main():
128
135
  parser.add_argument(
129
136
  "--stl_output_size",
130
137
  type=int,
131
- default=150,
138
+ default=200,
132
139
  help="Size of the longest dimension of the output STL file in mm",
133
140
  )
141
+
142
+ parser.add_argument(
143
+ "--processing_size",
144
+ type=int,
145
+ default=100,
146
+ help="Internal image processing size in mm",
147
+ )
148
+
134
149
  parser.add_argument(
135
150
  "--nozzle_diameter",
136
151
  type=float,
@@ -266,6 +281,11 @@ def main():
266
281
  if args.num_init_cluster_layers == -1:
267
282
  args.num_init_cluster_layers = args.max_layers // 2
268
283
 
284
+ # check if csv or json is given
285
+ if args.csv_file == "" and args.json_file == "":
286
+ print("Error: No CSV or JSON file given. Please provide one of them.")
287
+ sys.exit(1)
288
+
269
289
  if torch.cuda.is_available():
270
290
  device = torch.device("cuda")
271
291
  elif args.mps and torch.backends.mps.is_available():
@@ -288,9 +308,12 @@ def main():
288
308
  print(f"Error: Input image '{args.input_image}' not found.", file=sys.stderr)
289
309
  sys.exit(1)
290
310
 
291
- if not os.path.exists(args.csv_file):
311
+ if args.csv_file != "" and not os.path.exists(args.csv_file):
292
312
  print(f"Error: CSV file '{args.csv_file}' not found.", file=sys.stderr)
293
313
  sys.exit(1)
314
+ if args.json_file != "" and not os.path.exists(args.json_file):
315
+ print(f"Error: Json file '{args.json_file}' not found.", file=sys.stderr)
316
+ sys.exit(1)
294
317
 
295
318
  random_seed = args.random_seed
296
319
  if random_seed == 0:
@@ -303,9 +326,7 @@ def main():
303
326
  background = torch.tensor(bgr_tuple, dtype=torch.float32, device=device)
304
327
 
305
328
  # Load materials
306
- material_colors_np, material_TDs_np, material_names, _ = load_materials(
307
- args.csv_file
308
- )
329
+ material_colors_np, material_TDs_np, material_names, _ = load_materials(args)
309
330
  material_colors = torch.tensor(
310
331
  material_colors_np, dtype=torch.float32, device=device
311
332
  )
@@ -314,7 +335,10 @@ def main():
314
335
  # Read input image
315
336
  img = imread(args.input_image, cv2.IMREAD_UNCHANGED)
316
337
  computed_output_size = int(round(args.stl_output_size * 2 / args.nozzle_diameter))
317
- print(f"Computed solving pixel size: {computed_output_size}")
338
+ computed_processing_size = int(
339
+ round(args.processing_size * 2 / args.nozzle_diameter)
340
+ )
341
+ print(f"Computed solving pixel size: {computed_processing_size}")
318
342
  alpha = None
319
343
  if img.shape[2] == 4:
320
344
  # Extract alpha channel
@@ -328,6 +352,8 @@ def main():
328
352
 
329
353
  # Convert image from BGR to RGB
330
354
  img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
355
+ processing_img_np = resize_image(img, computed_processing_size)
356
+ processing_img = torch.tensor(processing_img_np, dtype=torch.float32, device=device)
331
357
 
332
358
  # For the final resolution
333
359
  output_img_np = resize_image(img, computed_output_size)
@@ -366,6 +392,10 @@ def main():
366
392
  if alpha is not None:
367
393
  pixel_height_logits_init[alpha < 128] = -13.815512
368
394
 
395
+ # resize the pixel_height_logits to the processing_size
396
+ pixel_height_logits_process = resize_image(
397
+ np.expand_dims(pixel_height_logits_init, -1), computed_processing_size
398
+ )
369
399
  # VGG Perceptual Loss
370
400
  # We currently disable this as it is not used in the optimization.
371
401
  perception_loss_module = None # MultiLayerVGGPerceptualLoss().to(device).eval()
@@ -373,8 +403,8 @@ def main():
373
403
  # Create an optimizer instance
374
404
  optimizer = FilamentOptimizer(
375
405
  args=args,
376
- target=output_target,
377
- pixel_height_logits_init=pixel_height_logits_init,
406
+ target=processing_img,
407
+ pixel_height_logits_init=pixel_height_logits_process,
378
408
  global_logits_init=global_logits_init,
379
409
  material_colors=material_colors,
380
410
  material_TDs=material_TDs,
@@ -410,82 +440,99 @@ def main():
410
440
 
411
441
  post_opt_step = 0
412
442
 
413
- optimizer.log_to_tensorboard(
414
- interval=1, namespace="post_opt", step=(post_opt_step := post_opt_step + 1)
415
- )
416
-
417
- if args.perform_pruning:
418
- optimizer.prune(
419
- max_colors_allowed=args.pruning_max_colors,
420
- max_swaps_allowed=args.pruning_max_swaps,
421
- min_layers_allowed=args.min_layers,
422
- max_layers_allowed=args.pruning_max_layer,
423
- search_seed=True,
424
- fast_pruning=args.fast_pruning,
425
- fast_pruning_percent=args.fast_pruning_percent,
426
- )
427
- optimizer.log_to_tensorboard(
428
- interval=1,
429
- namespace="post_opt",
430
- step=(post_opt_step := post_opt_step + 1),
431
- )
432
-
433
- disc_global, disc_height_image = optimizer.get_discretized_solution(best=True)
434
-
435
- print("Done. Saving outputs...")
436
- # Save Image
437
- comp_disc = optimizer.get_best_discretized_image()
438
- args.max_layers = optimizer.max_layers
443
+ # change processing pixel heights to large output pixel heights
444
+ optimizer.pixel_height_logits = torch.from_numpy(pixel_height_logits_init)
445
+ optimizer.best_params["pixel_height_logits"] = torch.from_numpy(
446
+ pixel_height_logits_init
447
+ ).to(device)
448
+ optimizer.target = output_target
439
449
 
440
450
  optimizer.log_to_tensorboard(
441
451
  interval=1, namespace="post_opt", step=(post_opt_step := post_opt_step + 1)
442
452
  )
443
453
 
444
- comp_disc_np = comp_disc.cpu().numpy().astype(np.uint8)
445
- comp_disc_np = cv2.cvtColor(comp_disc_np, cv2.COLOR_RGB2BGR)
446
- cv2.imwrite(os.path.join(args.output_folder, "final_model.png"), comp_disc_np)
447
-
448
- stl_filename = os.path.join(args.output_folder, "final_model.stl")
449
- height_map_mm = (
450
- disc_height_image.cpu().numpy().astype(np.float32)
451
- ) * args.layer_height
452
- generate_stl(
453
- height_map_mm,
454
- stl_filename,
455
- args.background_height,
456
- maximum_x_y_size=args.stl_output_size,
457
- alpha_mask=alpha,
458
- )
459
-
460
- # Swap instructions
461
- background_layers = int(args.background_height // args.layer_height)
462
- swap_instructions = generate_swap_instructions(
463
- disc_global.cpu().numpy(),
464
- disc_height_image.cpu().numpy(),
465
- args.layer_height,
466
- background_layers,
467
- args.background_height,
468
- material_names,
469
- )
470
- with open(os.path.join(args.output_folder, "swap_instructions.txt"), "w") as f:
471
- for line in swap_instructions:
472
- f.write(line + "\n")
473
-
474
- # Project file
475
- project_filename = os.path.join(args.output_folder, "project_file.hfp")
476
- generate_project_file(
477
- project_filename,
478
- args,
479
- disc_global.cpu().numpy(),
480
- disc_height_image.cpu().numpy(),
481
- output_target.shape[1],
482
- output_target.shape[0],
483
- stl_filename,
484
- args.csv_file,
485
- )
486
-
487
- print("All done. Outputs in:", args.output_folder)
488
- print("Happy Printing!")
454
+ with torch.no_grad():
455
+ with torch.autocast(device.type, dtype=torch.bfloat16):
456
+ if args.perform_pruning:
457
+ optimizer.prune(
458
+ max_colors_allowed=args.pruning_max_colors,
459
+ max_swaps_allowed=args.pruning_max_swaps,
460
+ min_layers_allowed=args.min_layers,
461
+ max_layers_allowed=args.pruning_max_layer,
462
+ search_seed=True,
463
+ fast_pruning=args.fast_pruning,
464
+ fast_pruning_percent=args.fast_pruning_percent,
465
+ )
466
+ optimizer.log_to_tensorboard(
467
+ interval=1,
468
+ namespace="post_opt",
469
+ step=(post_opt_step := post_opt_step + 1),
470
+ )
471
+
472
+ disc_global, disc_height_image = optimizer.get_discretized_solution(
473
+ best=True
474
+ )
475
+
476
+ print("Done. Saving outputs...")
477
+ # Save Image
478
+ comp_disc = optimizer.get_best_discretized_image()
479
+ args.max_layers = optimizer.max_layers
480
+
481
+ optimizer.log_to_tensorboard(
482
+ interval=1,
483
+ namespace="post_opt",
484
+ step=(post_opt_step := post_opt_step + 1),
485
+ )
486
+
487
+ comp_disc_np = comp_disc.cpu().numpy().astype(np.uint8)
488
+ comp_disc_np = cv2.cvtColor(comp_disc_np, cv2.COLOR_RGB2BGR)
489
+ cv2.imwrite(
490
+ os.path.join(args.output_folder, "final_model.png"), comp_disc_np
491
+ )
492
+
493
+ stl_filename = os.path.join(args.output_folder, "final_model.stl")
494
+ height_map_mm = (
495
+ disc_height_image.cpu().numpy().astype(np.float32)
496
+ ) * args.layer_height
497
+ generate_stl(
498
+ height_map_mm,
499
+ stl_filename,
500
+ args.background_height,
501
+ maximum_x_y_size=args.stl_output_size,
502
+ alpha_mask=alpha,
503
+ )
504
+
505
+ # Swap instructions
506
+ background_layers = int(args.background_height // args.layer_height)
507
+ swap_instructions = generate_swap_instructions(
508
+ disc_global.cpu().numpy(),
509
+ disc_height_image.cpu().numpy(),
510
+ args.layer_height,
511
+ background_layers,
512
+ args.background_height,
513
+ material_names,
514
+ )
515
+ with open(
516
+ os.path.join(args.output_folder, "swap_instructions.txt"), "w"
517
+ ) as f:
518
+ for line in swap_instructions:
519
+ f.write(line + "\n")
520
+
521
+ # Project file
522
+ project_filename = os.path.join(args.output_folder, "project_file.hfp")
523
+ generate_project_file(
524
+ project_filename,
525
+ args,
526
+ disc_global.cpu().numpy(),
527
+ disc_height_image.cpu().numpy(),
528
+ output_target.shape[1],
529
+ output_target.shape[0],
530
+ stl_filename,
531
+ args.csv_file,
532
+ )
533
+
534
+ print("All done. Outputs in:", args.output_folder)
535
+ print("Happy Printing!")
489
536
 
490
537
 
491
538
  if __name__ == "__main__":
File without changes