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.
- {autoforge-1.7.4 → autoforge-1.7.6}/PKG-INFO +11 -4
- {autoforge-1.7.4 → autoforge-1.7.6}/README.md +10 -3
- {autoforge-1.7.4 → autoforge-1.7.6}/pyproject.toml +1 -1
- {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/PKG-INFO +11 -4
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/FilamentHelper.py +43 -10
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/OutputHelper.py +10 -10
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/auto_forge.py +127 -80
- {autoforge-1.7.4 → autoforge-1.7.6}/setup.cfg +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/SOURCES.txt +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/dependency_links.txt +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/entry_points.txt +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/requires.txt +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/AutoForge.egg-info/top_level.txt +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/Views/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/Views/backend_database.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/Views/filament_editor.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/app.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Gui/browser_gui/main.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/CAdamW.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/ChristofidesHeightMap.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/DepthEstimateHeightMap.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/OldHeightmap.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/ImageHelper.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/OptimizerHelper.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/PruningHelper.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/filamentcolors_library.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Init_comparer/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Init_comparer/auto_forge_init_check.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Init_comparer/plot_results.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Loss/LossFunctions.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Loss/PerceptionLoss.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Loss/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Misc/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Misc/color_fit_all.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Modules/Optimizer.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Modules/__init__.py +0 -0
- {autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/__init__.py +0 -0
- {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.
|
|
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`
|
|
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`
|
|
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.
|
|
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.
|
|
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`
|
|
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(
|
|
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 =
|
|
25
|
+
df = load_materials_pandas(args)
|
|
23
26
|
material_names = [
|
|
24
|
-
brand + " - " + name
|
|
25
|
-
for brand, name in zip(df["Brand"].tolist(), df["
|
|
27
|
+
str(brand) + " - " + str(name)
|
|
28
|
+
for brand, name in zip(df["Brand"].tolist(), df["Name"].tolist())
|
|
26
29
|
]
|
|
27
|
-
material_TDs = (df["
|
|
28
|
-
colors_list = df["
|
|
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
|
-
|
|
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 =
|
|
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(
|
|
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["
|
|
99
|
-
"Name": mat["
|
|
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["
|
|
102
|
-
if "
|
|
101
|
+
"Owned": str(mat["Owned"]).strip().lower() == "true"
|
|
102
|
+
if "Owned" in mat
|
|
103
103
|
else False,
|
|
104
|
-
"Transmissivity": float(mat["
|
|
105
|
-
if not float(mat["
|
|
106
|
-
else int(mat["
|
|
107
|
-
"Type": mat["
|
|
108
|
-
"uuid": mat["
|
|
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
|
-
|
|
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=
|
|
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
|
-
|
|
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=
|
|
377
|
-
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
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
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
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/ChristofidesHeightMap.py
RENAMED
|
File without changes
|
{autoforge-1.7.4 → autoforge-1.7.6}/src/autoforge/Helper/Heightmaps/DepthEstimateHeightMap.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|