autoforge 1.6.0__tar.gz → 1.6.2__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.6.0 → autoforge-1.6.2}/PKG-INFO +29 -13
- {autoforge-1.6.0 → autoforge-1.6.2}/README.md +28 -12
- {autoforge-1.6.0 → autoforge-1.6.2}/pyproject.toml +1 -1
- {autoforge-1.6.0 → autoforge-1.6.2}/src/AutoForge.egg-info/PKG-INFO +29 -13
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Init_comparer/auto_forge_init_check.py +50 -40
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Init_comparer/plot_results.py +53 -45
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Loss/LossFunctions.py +24 -28
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Modules/Optimizer.py +21 -2
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/auto_forge.py +30 -15
- {autoforge-1.6.0 → autoforge-1.6.2}/setup.cfg +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/AutoForge.egg-info/SOURCES.txt +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/AutoForge.egg-info/dependency_links.txt +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/AutoForge.egg-info/entry_points.txt +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/AutoForge.egg-info/requires.txt +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/AutoForge.egg-info/top_level.txt +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Gui/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Gui/browser_gui/Views/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Gui/browser_gui/Views/backend_database.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Gui/browser_gui/Views/filament_editor.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Gui/browser_gui/app.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Gui/browser_gui/main.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/CAdamW.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/FilamentHelper.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/Heightmaps/ChristofidesHeightMap.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/Heightmaps/DepthEstimateHeightMap.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/Heightmaps/OldHeightmap.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/Heightmaps/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/ImageHelper.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/OptimizerHelper.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/OutputHelper.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/PruningHelper.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/filamentcolors_library.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Init_comparer/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Loss/PerceptionLoss.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Loss/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Misc/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Misc/color_fit_all.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Modules/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/__init__.py +0 -0
- {autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/__main__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: AutoForge
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
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
|
|
@@ -48,10 +48,6 @@ The pruning is set to a maximum of 8 color and 20 swaps, so each image uses at m
|
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
50
50
|
|
|
51
|
-
If someone uses this program and 3d prints something with it, please let me know :) \
|
|
52
|
-
I would love to see what you made!
|
|
53
|
-
|
|
54
|
-
|
|
55
51
|
## Features
|
|
56
52
|
|
|
57
53
|
- **Image-to-Model Conversion**: Converts an input image into a layered model suitable for 3D printing.
|
|
@@ -63,8 +59,23 @@ I would love to see what you made!
|
|
|
63
59
|
- **Live Visualization**: (Optional) Displays live composite images during the optimization process.
|
|
64
60
|
- **Hueforge export**: Outputs a project file that can be opened with hueforge.
|
|
65
61
|
|
|
62
|
+
## [Google Colab Notebook](https://colab.research.google.com/drive/13sWCss9-ew2xnoJl4c4SSpComSNi-1ih)
|
|
63
|
+
|
|
64
|
+
If you're new to Google Colab, follow these simple steps to run the notebook:
|
|
65
|
+
|
|
66
|
+
1. **Open the Notebook:**
|
|
67
|
+
Click [here](https://colab.research.google.com/drive/13sWCss9-ew2xnoJl4c4SSpComSNi-1ih) to open the notebook in Google Colab.
|
|
68
|
+
|
|
69
|
+
2. **Select GPU Runtime:**
|
|
70
|
+
In Colab, go to the menu and click **Runtime → Change runtime type**. Under **Hardware accelerator**, choose **T4 GPU** (or any other available GPU type).
|
|
71
|
+
|
|
72
|
+
3. **Run All Cells:**
|
|
73
|
+
Once the notebook loads, click **Runtime → Run all** to execute the cells in sequence. Follow the on-screen prompts to configure the materials CSV, upload your image, and run Autoforge.
|
|
66
74
|
|
|
67
|
-
|
|
75
|
+
4. **Review and Download:**
|
|
76
|
+
After the process completes, you'll see a preview of the output image. Finally, the notebook will zip the output folder for you to download.
|
|
77
|
+
|
|
78
|
+
## Manual Installation
|
|
68
79
|
|
|
69
80
|
To install AutoForge, simply install the current version from PyPI:
|
|
70
81
|
```bash
|
|
@@ -81,13 +92,18 @@ The script is run from the command line and accepts several arguments. Below is
|
|
|
81
92
|
> **Note:** You will need [Hueforge](https://shop.thehueforge.com/) installed to export your filament CSV.
|
|
82
93
|
> 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.
|
|
83
94
|
|
|
84
|
-
> If you want to limit the amount of colors the program can use, you can simply delete the colors you don't want from the CSV file.
|
|
85
95
|
|
|
86
96
|
```bash
|
|
87
|
-
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
97
|
+
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> If you want to limit the amount of colors the program can use, you can set these as command line arguments. \
|
|
101
|
+
> For Example: 8 colors and a maximum of 20 swaps:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv --pruning_max_colors 8 --pruning_max_swaps 20
|
|
88
105
|
```
|
|
89
106
|
|
|
90
|
-
### Command Line Arguments
|
|
91
107
|
|
|
92
108
|
### Command Line Arguments
|
|
93
109
|
|
|
@@ -99,10 +115,10 @@ autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
|
99
115
|
|
|
100
116
|
- `--output_folder` Folder where output files will be saved (default: `output`).
|
|
101
117
|
- `--iterations` Number of optimization iterations (default: 5000).
|
|
102
|
-
- `--learning_rate` Learning rate for optimization (default:
|
|
118
|
+
- `--learning_rate` Learning rate for optimization (default: 0.015).
|
|
103
119
|
- `--layer_height` Layer thickness in millimeters (default: 0.04).
|
|
104
|
-
- `--max_layers` Maximum number of layers (default:
|
|
105
|
-
**Note:** This is about
|
|
120
|
+
- `--max_layers` Maximum number of layers (default: 75).
|
|
121
|
+
**Note:** This is about 3mm + the background height
|
|
106
122
|
- `--background_height` Height of the background in millimeters (default: 0.4).
|
|
107
123
|
**Note:** The background height must be divisible by the layer height.
|
|
108
124
|
- `--background_color` Background color in hexadecimal format (default: `#000000` aka Black).
|
|
@@ -24,10 +24,6 @@ The pruning is set to a maximum of 8 color and 20 swaps, so each image uses at m
|
|
|
24
24
|
</div>
|
|
25
25
|
</div>
|
|
26
26
|
|
|
27
|
-
If someone uses this program and 3d prints something with it, please let me know :) \
|
|
28
|
-
I would love to see what you made!
|
|
29
|
-
|
|
30
|
-
|
|
31
27
|
## Features
|
|
32
28
|
|
|
33
29
|
- **Image-to-Model Conversion**: Converts an input image into a layered model suitable for 3D printing.
|
|
@@ -39,8 +35,23 @@ I would love to see what you made!
|
|
|
39
35
|
- **Live Visualization**: (Optional) Displays live composite images during the optimization process.
|
|
40
36
|
- **Hueforge export**: Outputs a project file that can be opened with hueforge.
|
|
41
37
|
|
|
38
|
+
## [Google Colab Notebook](https://colab.research.google.com/drive/13sWCss9-ew2xnoJl4c4SSpComSNi-1ih)
|
|
39
|
+
|
|
40
|
+
If you're new to Google Colab, follow these simple steps to run the notebook:
|
|
41
|
+
|
|
42
|
+
1. **Open the Notebook:**
|
|
43
|
+
Click [here](https://colab.research.google.com/drive/13sWCss9-ew2xnoJl4c4SSpComSNi-1ih) to open the notebook in Google Colab.
|
|
44
|
+
|
|
45
|
+
2. **Select GPU Runtime:**
|
|
46
|
+
In Colab, go to the menu and click **Runtime → Change runtime type**. Under **Hardware accelerator**, choose **T4 GPU** (or any other available GPU type).
|
|
47
|
+
|
|
48
|
+
3. **Run All Cells:**
|
|
49
|
+
Once the notebook loads, click **Runtime → Run all** to execute the cells in sequence. Follow the on-screen prompts to configure the materials CSV, upload your image, and run Autoforge.
|
|
42
50
|
|
|
43
|
-
|
|
51
|
+
4. **Review and Download:**
|
|
52
|
+
After the process completes, you'll see a preview of the output image. Finally, the notebook will zip the output folder for you to download.
|
|
53
|
+
|
|
54
|
+
## Manual Installation
|
|
44
55
|
|
|
45
56
|
To install AutoForge, simply install the current version from PyPI:
|
|
46
57
|
```bash
|
|
@@ -57,13 +68,18 @@ The script is run from the command line and accepts several arguments. Below is
|
|
|
57
68
|
> **Note:** You will need [Hueforge](https://shop.thehueforge.com/) installed to export your filament CSV.
|
|
58
69
|
> 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.
|
|
59
70
|
|
|
60
|
-
> If you want to limit the amount of colors the program can use, you can simply delete the colors you don't want from the CSV file.
|
|
61
71
|
|
|
62
72
|
```bash
|
|
63
|
-
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
73
|
+
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
> If you want to limit the amount of colors the program can use, you can set these as command line arguments. \
|
|
77
|
+
> For Example: 8 colors and a maximum of 20 swaps:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv --pruning_max_colors 8 --pruning_max_swaps 20
|
|
64
81
|
```
|
|
65
82
|
|
|
66
|
-
### Command Line Arguments
|
|
67
83
|
|
|
68
84
|
### Command Line Arguments
|
|
69
85
|
|
|
@@ -75,10 +91,10 @@ autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
|
75
91
|
|
|
76
92
|
- `--output_folder` Folder where output files will be saved (default: `output`).
|
|
77
93
|
- `--iterations` Number of optimization iterations (default: 5000).
|
|
78
|
-
- `--learning_rate` Learning rate for optimization (default:
|
|
94
|
+
- `--learning_rate` Learning rate for optimization (default: 0.015).
|
|
79
95
|
- `--layer_height` Layer thickness in millimeters (default: 0.04).
|
|
80
|
-
- `--max_layers` Maximum number of layers (default:
|
|
81
|
-
**Note:** This is about
|
|
96
|
+
- `--max_layers` Maximum number of layers (default: 75).
|
|
97
|
+
**Note:** This is about 3mm + the background height
|
|
82
98
|
- `--background_height` Height of the background in millimeters (default: 0.4).
|
|
83
99
|
**Note:** The background height must be divisible by the layer height.
|
|
84
100
|
- `--background_color` Background color in hexadecimal format (default: `#000000` aka Black).
|
|
@@ -178,4 +194,4 @@ Example Images: \
|
|
|
178
194
|
<a href="https://www.vecteezy.com/free-photos/animal">Animal Stock photos by Vecteezy</a>
|
|
179
195
|
|
|
180
196
|
|
|
181
|
-
Happy printing!
|
|
197
|
+
Happy printing!
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "AutoForge"
|
|
7
|
-
version="1.6.
|
|
7
|
+
version="1.6.2"
|
|
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
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: AutoForge
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.2
|
|
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
|
|
@@ -48,10 +48,6 @@ The pruning is set to a maximum of 8 color and 20 swaps, so each image uses at m
|
|
|
48
48
|
</div>
|
|
49
49
|
</div>
|
|
50
50
|
|
|
51
|
-
If someone uses this program and 3d prints something with it, please let me know :) \
|
|
52
|
-
I would love to see what you made!
|
|
53
|
-
|
|
54
|
-
|
|
55
51
|
## Features
|
|
56
52
|
|
|
57
53
|
- **Image-to-Model Conversion**: Converts an input image into a layered model suitable for 3D printing.
|
|
@@ -63,8 +59,23 @@ I would love to see what you made!
|
|
|
63
59
|
- **Live Visualization**: (Optional) Displays live composite images during the optimization process.
|
|
64
60
|
- **Hueforge export**: Outputs a project file that can be opened with hueforge.
|
|
65
61
|
|
|
62
|
+
## [Google Colab Notebook](https://colab.research.google.com/drive/13sWCss9-ew2xnoJl4c4SSpComSNi-1ih)
|
|
63
|
+
|
|
64
|
+
If you're new to Google Colab, follow these simple steps to run the notebook:
|
|
65
|
+
|
|
66
|
+
1. **Open the Notebook:**
|
|
67
|
+
Click [here](https://colab.research.google.com/drive/13sWCss9-ew2xnoJl4c4SSpComSNi-1ih) to open the notebook in Google Colab.
|
|
68
|
+
|
|
69
|
+
2. **Select GPU Runtime:**
|
|
70
|
+
In Colab, go to the menu and click **Runtime → Change runtime type**. Under **Hardware accelerator**, choose **T4 GPU** (or any other available GPU type).
|
|
71
|
+
|
|
72
|
+
3. **Run All Cells:**
|
|
73
|
+
Once the notebook loads, click **Runtime → Run all** to execute the cells in sequence. Follow the on-screen prompts to configure the materials CSV, upload your image, and run Autoforge.
|
|
66
74
|
|
|
67
|
-
|
|
75
|
+
4. **Review and Download:**
|
|
76
|
+
After the process completes, you'll see a preview of the output image. Finally, the notebook will zip the output folder for you to download.
|
|
77
|
+
|
|
78
|
+
## Manual Installation
|
|
68
79
|
|
|
69
80
|
To install AutoForge, simply install the current version from PyPI:
|
|
70
81
|
```bash
|
|
@@ -81,13 +92,18 @@ The script is run from the command line and accepts several arguments. Below is
|
|
|
81
92
|
> **Note:** You will need [Hueforge](https://shop.thehueforge.com/) installed to export your filament CSV.
|
|
82
93
|
> 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.
|
|
83
94
|
|
|
84
|
-
> If you want to limit the amount of colors the program can use, you can simply delete the colors you don't want from the CSV file.
|
|
85
95
|
|
|
86
96
|
```bash
|
|
87
|
-
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
97
|
+
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
> If you want to limit the amount of colors the program can use, you can set these as command line arguments. \
|
|
101
|
+
> For Example: 8 colors and a maximum of 20 swaps:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv --pruning_max_colors 8 --pruning_max_swaps 20
|
|
88
105
|
```
|
|
89
106
|
|
|
90
|
-
### Command Line Arguments
|
|
91
107
|
|
|
92
108
|
### Command Line Arguments
|
|
93
109
|
|
|
@@ -99,10 +115,10 @@ autoforge --input_image path/to/input_image.jpg --csv_file path/to/materials.csv
|
|
|
99
115
|
|
|
100
116
|
- `--output_folder` Folder where output files will be saved (default: `output`).
|
|
101
117
|
- `--iterations` Number of optimization iterations (default: 5000).
|
|
102
|
-
- `--learning_rate` Learning rate for optimization (default:
|
|
118
|
+
- `--learning_rate` Learning rate for optimization (default: 0.015).
|
|
103
119
|
- `--layer_height` Layer thickness in millimeters (default: 0.04).
|
|
104
|
-
- `--max_layers` Maximum number of layers (default:
|
|
105
|
-
**Note:** This is about
|
|
120
|
+
- `--max_layers` Maximum number of layers (default: 75).
|
|
121
|
+
**Note:** This is about 3mm + the background height
|
|
106
122
|
- `--background_height` Height of the background in millimeters (default: 0.4).
|
|
107
123
|
**Note:** The background height must be divisible by the layer height.
|
|
108
124
|
- `--background_color` Background color in hexadecimal format (default: `#000000` aka Black).
|
|
@@ -24,15 +24,20 @@ class Config:
|
|
|
24
24
|
csv_file = "default_materials.csv" # Path to CSV file with material data
|
|
25
25
|
output_folder = "output"
|
|
26
26
|
iterations = 2000
|
|
27
|
-
learning_rate =
|
|
27
|
+
learning_rate = 0.015
|
|
28
|
+
|
|
29
|
+
warmup_fraction = 0.1 #[0.0, 1.0]
|
|
30
|
+
height_logits_learning_start_fraction = 0.1 #[0.0, 1.0] but should be less than height_logits_learning_full_fraction
|
|
31
|
+
height_logits_learning_full_fraction = 0.5 # [0.0, 1.0] but should be more than height_logits_learning_start_fraction
|
|
32
|
+
init_tau = 1.0 # [0.0, 1.0] needs to be more than final_tau
|
|
33
|
+
final_tau = 0.01 # [0.0, 1.0] needs to be less than init_tau
|
|
34
|
+
|
|
28
35
|
layer_height = 0.04
|
|
29
36
|
max_layers = 75
|
|
30
37
|
min_layers = 0
|
|
31
38
|
background_height = 0.4
|
|
32
39
|
background_color = "#000000"
|
|
33
40
|
output_size = 128
|
|
34
|
-
init_tau = 1.0
|
|
35
|
-
final_tau = 0.01
|
|
36
41
|
visualize = False
|
|
37
42
|
stl_output_size = 200
|
|
38
43
|
perform_pruning = True
|
|
@@ -52,12 +57,19 @@ class Config:
|
|
|
52
57
|
tensorboard = False
|
|
53
58
|
|
|
54
59
|
|
|
55
|
-
def main(input_image, csv_file,
|
|
56
|
-
# Create config object using default values
|
|
60
|
+
def main(input_image, csv_file, warmup, h_start, h_full, tau_init, tau_final):
|
|
61
|
+
# Create config object using default values and override with given hyperparameters.
|
|
57
62
|
args = Config()
|
|
58
63
|
args.input_image = input_image
|
|
59
64
|
args.csv_file = csv_file
|
|
60
65
|
|
|
66
|
+
# Set the hyperparameters for the grid search.
|
|
67
|
+
args.warmup_fraction = warmup
|
|
68
|
+
args.height_logits_learning_start_fraction = h_start
|
|
69
|
+
args.height_logits_learning_full_fraction = h_full
|
|
70
|
+
args.init_tau = tau_init
|
|
71
|
+
args.final_tau = tau_final
|
|
72
|
+
|
|
61
73
|
if torch.cuda.is_available():
|
|
62
74
|
device = torch.device("cuda")
|
|
63
75
|
elif args.mps and torch.backends.mps.is_available():
|
|
@@ -128,9 +140,9 @@ def main(input_image, csv_file, init_method, cluster_layers, lab_space):
|
|
|
128
140
|
args.layer_height,
|
|
129
141
|
bgr_tuple,
|
|
130
142
|
random_seed=random_seed,
|
|
131
|
-
init_method=
|
|
132
|
-
cluster_layers=
|
|
133
|
-
lab_space=
|
|
143
|
+
init_method="kmeans",
|
|
144
|
+
cluster_layers=20,
|
|
145
|
+
lab_space=False,
|
|
134
146
|
num_threads=8,
|
|
135
147
|
)
|
|
136
148
|
|
|
@@ -186,47 +198,41 @@ def main(input_image, csv_file, init_method, cluster_layers, lab_space):
|
|
|
186
198
|
return mse_loss.item()
|
|
187
199
|
|
|
188
200
|
|
|
189
|
-
def main_suppressed(input_image, csv_file,
|
|
201
|
+
def main_suppressed(input_image, csv_file, warmup, h_start, h_full, tau_init, tau_final):
|
|
190
202
|
with open(os.devnull, "w") as fnull:
|
|
191
203
|
with redirect_stdout(fnull), redirect_stderr(fnull):
|
|
192
|
-
result = main(input_image, csv_file,
|
|
204
|
+
result = main(input_image, csv_file, warmup, h_start, h_full, tau_init, tau_final)
|
|
193
205
|
return result
|
|
194
206
|
|
|
195
207
|
|
|
196
208
|
if __name__ == "__main__":
|
|
197
209
|
folder = "../../../images/test_images/"
|
|
198
210
|
csv_file = "../../../bambulab.csv"
|
|
199
|
-
images = [folder
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
]
|
|
215
|
-
use_lab_space = [True, False]
|
|
216
|
-
|
|
217
|
-
# test every permutation using itertools
|
|
211
|
+
images = [os.path.join(folder, img) for img in os.listdir(folder) if img.endswith(".jpg")]
|
|
212
|
+
fixed_lr = 1e-1
|
|
213
|
+
parallel_limit = 10
|
|
214
|
+
|
|
215
|
+
# Define grid search parameters
|
|
216
|
+
warmup_values = np.linspace(0, 1, 5) # 5 values for warmup_fraction
|
|
217
|
+
height_values = np.linspace(0, 1, 5) # 5 values for height fractions
|
|
218
|
+
tau_values = np.linspace(0, 1, 5) # 5 values for tau
|
|
219
|
+
|
|
220
|
+
# Build valid pairs for height fractions (start < full)
|
|
221
|
+
height_pairs = [(hs, hf) for hs in height_values for hf in height_values if hs < hf]
|
|
222
|
+
# Build valid pairs for tau (init_tau > final_tau)
|
|
223
|
+
tau_pairs = [(ti, tf) for ti in tau_values for tf in tau_values if ti > tf]
|
|
224
|
+
|
|
225
|
+
# Create grid: warmup x height_pairs x tau_pairs = 5 * 10 * 10 = 500 combinations
|
|
218
226
|
from itertools import product
|
|
227
|
+
hyperparam_grid = list(product(warmup_values, height_pairs, tau_pairs))
|
|
228
|
+
print(f"Total hyperparameter combinations: {len(hyperparam_grid)}")
|
|
219
229
|
|
|
220
230
|
out_dict = {}
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
for i, (method, cluster, lab) in enumerate(do_list):
|
|
231
|
+
# Loop over each hyperparameter combination
|
|
232
|
+
for idx, (warmup, (h_start, h_full), (tau_init, tau_final)) in enumerate(hyperparam_grid):
|
|
225
233
|
try:
|
|
226
|
-
out_dict_str = f"{
|
|
227
|
-
print(
|
|
228
|
-
f"Running {method} with {cluster} clusters and lab={lab}, {i + 1}/{len(do_list)}"
|
|
229
|
-
)
|
|
234
|
+
out_dict_str = f"w={warmup}_height_start={h_start}_height_full={h_full}_tau_init={tau_init}_tau_final={tau_final}"
|
|
235
|
+
print(f"Running {idx+1}/{len(hyperparam_grid)}: {out_dict_str}")
|
|
230
236
|
exec = ProcessPoolExecutor(max_workers=parallel_limit)
|
|
231
237
|
tlist = []
|
|
232
238
|
for img in images:
|
|
@@ -236,15 +242,19 @@ if __name__ == "__main__":
|
|
|
236
242
|
main_suppressed,
|
|
237
243
|
img,
|
|
238
244
|
csv_file,
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
245
|
+
warmup,
|
|
246
|
+
h_start,
|
|
247
|
+
h_full,
|
|
248
|
+
tau_init,
|
|
249
|
+
tau_final,
|
|
242
250
|
)
|
|
243
251
|
)
|
|
244
252
|
for t in tqdm(concurrent.futures.as_completed(tlist), total=len(tlist)):
|
|
245
253
|
result_list = out_dict.get(out_dict_str, [])
|
|
246
254
|
result_list.append(t.result())
|
|
247
255
|
out_dict[out_dict_str] = result_list
|
|
256
|
+
|
|
257
|
+
exec.shutdown()
|
|
248
258
|
# save out_dict as json
|
|
249
259
|
import json
|
|
250
260
|
|
|
@@ -14,10 +14,12 @@ for key, values in data.items():
|
|
|
14
14
|
arr = np.array(values)
|
|
15
15
|
mean_val = np.mean(arr)
|
|
16
16
|
std_val = np.std(arr)
|
|
17
|
+
#key is formatted as lr=float, we need to extract the float value and round it to 4 decimal values
|
|
18
|
+
key = round(float(key.split("=")[1]), 5)
|
|
17
19
|
stats.append((key, mean_val, std_val, arr))
|
|
18
20
|
|
|
19
21
|
# Sort the list of tuples based on the mean (ascending order)
|
|
20
|
-
stats.sort(key=lambda x: x[1])
|
|
22
|
+
#stats.sort(key=lambda x: x[1])
|
|
21
23
|
|
|
22
24
|
# Extract sorted lists of keys, means, stds, and store the sorted arrays in a dictionary
|
|
23
25
|
sorted_keys = [item[0] for item in stats]
|
|
@@ -53,7 +55,6 @@ fig.update_layout(
|
|
|
53
55
|
barmode="group",
|
|
54
56
|
)
|
|
55
57
|
|
|
56
|
-
|
|
57
58
|
# Function to generate significance stars based on the p-value.
|
|
58
59
|
def significance_label(p):
|
|
59
60
|
if p < 0.001:
|
|
@@ -65,50 +66,57 @@ def significance_label(p):
|
|
|
65
66
|
else:
|
|
66
67
|
return ""
|
|
67
68
|
|
|
69
|
+
# First, compute all significant pairwise comparisons
|
|
70
|
+
significant_pairs = [] # will hold tuples of (p_value, i, j)
|
|
71
|
+
for i in range(n_keys):
|
|
72
|
+
for j in range(i + 1, n_keys):
|
|
73
|
+
group1 = data_sorted[sorted_keys[i]]
|
|
74
|
+
group2 = data_sorted[sorted_keys[j]]
|
|
75
|
+
stat, p_value = ttest_ind(group1, group2)
|
|
76
|
+
if p_value < 0.05:
|
|
77
|
+
significant_pairs.append((p_value, i, j))
|
|
78
|
+
|
|
79
|
+
# Sort pairs by p-value (most significant first)
|
|
80
|
+
significant_pairs.sort(key=lambda x: x[0])
|
|
81
|
+
|
|
82
|
+
# To ensure each bar is annotated only once, track used indices.
|
|
83
|
+
used_bars = set()
|
|
84
|
+
base_margin = max(means) * 0.05 # margin above the error bars
|
|
85
|
+
|
|
86
|
+
significant_pairs = []
|
|
87
|
+
for p_value, i, j in significant_pairs:
|
|
88
|
+
# If either bar is already annotated, skip this pair.
|
|
89
|
+
if i in used_bars or j in used_bars:
|
|
90
|
+
continue
|
|
91
|
+
|
|
92
|
+
# Compute the base y-level from the higher error bar of the two.
|
|
93
|
+
base_y = max(means[i] + stds[i], means[j] + stds[j])
|
|
94
|
+
line_y = base_y + base_margin
|
|
95
|
+
|
|
96
|
+
# Mark these bars as used.
|
|
97
|
+
used_bars.update([i, j])
|
|
98
|
+
|
|
99
|
+
# Draw horizontal significance line between the two bars.
|
|
100
|
+
fig.add_shape(
|
|
101
|
+
type="line",
|
|
102
|
+
x0=x_positions[i],
|
|
103
|
+
x1=x_positions[j],
|
|
104
|
+
y0=line_y,
|
|
105
|
+
y1=line_y,
|
|
106
|
+
line=dict(color="black", width=1),
|
|
107
|
+
xref="x",
|
|
108
|
+
yref="y",
|
|
109
|
+
)
|
|
110
|
+
# Place the significance annotation (stars) above the line.
|
|
111
|
+
fig.add_annotation(
|
|
112
|
+
x=(x_positions[i] + x_positions[j]) / 2,
|
|
113
|
+
y=line_y + base_margin * 0.2,
|
|
114
|
+
text=significance_label(p_value),
|
|
115
|
+
showarrow=False,
|
|
116
|
+
font=dict(size=12),
|
|
117
|
+
)
|
|
118
|
+
|
|
68
119
|
|
|
69
|
-
# To avoid overlapping significance annotations when bars share a common index,
|
|
70
|
-
# keep track of the highest annotation drawn for each bar.
|
|
71
|
-
annotation_levels = {i: 0 for i in range(n_keys)}
|
|
72
|
-
# Base margin added above the highest error bar to start the significance line.
|
|
73
|
-
base_margin = max(means) * 0.05 # Adjust as needed
|
|
74
|
-
|
|
75
|
-
# Loop over adjacent pairs in the sorted order and perform t-tests.
|
|
76
|
-
for i in range(n_keys - 1):
|
|
77
|
-
group1 = data_sorted[sorted_keys[i]]
|
|
78
|
-
group2 = data_sorted[sorted_keys[i + 1]]
|
|
79
|
-
stat, p_value = ttest_ind(group1, group2)
|
|
80
|
-
|
|
81
|
-
# Only annotate if the difference is significant (p < 0.05)
|
|
82
|
-
if p_value < 0.05:
|
|
83
|
-
# Determine the base y-level from the taller of the two error bars.
|
|
84
|
-
base_y = max(means[i] + stds[i], means[i + 1] + stds[i + 1])
|
|
85
|
-
# Ensure new annotations are drawn above any previous ones.
|
|
86
|
-
current_level = max(annotation_levels[i], annotation_levels[i + 1])
|
|
87
|
-
line_y = base_y + base_margin + current_level
|
|
88
|
-
|
|
89
|
-
# Update annotation levels for these two bars.
|
|
90
|
-
annotation_levels[i] = line_y
|
|
91
|
-
annotation_levels[i + 1] = line_y
|
|
92
|
-
|
|
93
|
-
# Add a horizontal line between the two bars.
|
|
94
|
-
fig.add_shape(
|
|
95
|
-
type="line",
|
|
96
|
-
x0=x_positions[i],
|
|
97
|
-
x1=x_positions[i + 1],
|
|
98
|
-
y0=line_y,
|
|
99
|
-
y1=line_y,
|
|
100
|
-
line=dict(color="black", width=1),
|
|
101
|
-
xref="x",
|
|
102
|
-
yref="y",
|
|
103
|
-
)
|
|
104
|
-
# Add the significance stars annotation above the line.
|
|
105
|
-
fig.add_annotation(
|
|
106
|
-
x=(x_positions[i] + x_positions[i + 1]) / 2,
|
|
107
|
-
y=line_y + base_margin * 0.2,
|
|
108
|
-
text=significance_label(p_value),
|
|
109
|
-
showarrow=False,
|
|
110
|
-
font=dict(size=12),
|
|
111
|
-
)
|
|
112
120
|
fig.update_layout(
|
|
113
121
|
autosize=False,
|
|
114
122
|
width=1920,
|
|
@@ -50,46 +50,42 @@ def compute_loss(
|
|
|
50
50
|
add_penalty_loss: float = 0.0,
|
|
51
51
|
) -> torch.Tensor:
|
|
52
52
|
"""
|
|
53
|
-
Combined MSE + Perceptual + penalty losses.
|
|
53
|
+
Combined MSE + Perceptual + penalty losses with patch-based smoothness.
|
|
54
54
|
"""
|
|
55
|
-
# MSE
|
|
55
|
+
# MSE Loss
|
|
56
56
|
comp_mse = srgb_to_lab(comp)
|
|
57
|
-
# we slightly increase saturation of our target image to make the color matching more robust
|
|
58
|
-
# target = increase_saturation(target, 0.1)
|
|
59
57
|
target_mse = srgb_to_lab(target)
|
|
60
58
|
mse_loss = F.huber_loss(comp_mse, target_mse)
|
|
61
59
|
|
|
62
60
|
if pixel_height_logits is not None:
|
|
61
|
+
# Existing neighbor-based smoothness loss:
|
|
63
62
|
target_gray = target.mean(dim=2) # shape becomes [H, W]
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
weight_x = torch.exp(
|
|
67
|
-
-torch.abs(target_gray[:, 1:] - target_gray[:, :-1])
|
|
68
|
-
) # shape [H, W-1]
|
|
69
|
-
weight_y = torch.exp(
|
|
70
|
-
-torch.abs(target_gray[1:, :] - target_gray[:-1, :])
|
|
71
|
-
) # shape [H-1, W]
|
|
72
|
-
|
|
63
|
+
weight_x = torch.exp(-torch.abs(target_gray[:, 1:] - target_gray[:, :-1]))
|
|
64
|
+
weight_y = torch.exp(-torch.abs(target_gray[1:, :] - target_gray[:-1, :]))
|
|
73
65
|
weight_x = torch.clamp(weight_x, 0.5, 1.0)
|
|
74
66
|
weight_y = torch.clamp(weight_y, 0.5, 1.0)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
dx = torch.abs(
|
|
78
|
-
pixel_height_logits[:, 1:] - pixel_height_logits[:, :-1]
|
|
79
|
-
) # shape [H, W-1]
|
|
80
|
-
dy = torch.abs(
|
|
81
|
-
pixel_height_logits[1:, :] - pixel_height_logits[:-1, :]
|
|
82
|
-
) # shape [H-1, W]
|
|
83
|
-
|
|
84
|
-
# provide a target tensor (zeros) for the huber loss.
|
|
67
|
+
dx = torch.abs(pixel_height_logits[:, 1:] - pixel_height_logits[:, :-1])
|
|
68
|
+
dy = torch.abs(pixel_height_logits[1:, :] - pixel_height_logits[:-1, :])
|
|
85
69
|
loss_dx = torch.mean(F.huber_loss(dx * weight_x, torch.zeros_like(dx)))
|
|
86
70
|
loss_dy = torch.mean(F.huber_loss(dy * weight_y, torch.zeros_like(dy)))
|
|
87
|
-
|
|
88
|
-
# loss_dy = torch.mean(F.huber_loss(dy, torch.zeros_like(dy)))
|
|
71
|
+
smoothness_loss = (loss_dx + loss_dy) * (10 * add_penalty_loss)
|
|
89
72
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
73
|
+
# Additional patch-based smoothness loss (using a 3x3 Laplacian):
|
|
74
|
+
laplacian_kernel = (
|
|
75
|
+
torch.tensor(
|
|
76
|
+
[[0, 1, 0], [1, -4, 1], [0, 1, 0]],
|
|
77
|
+
dtype=pixel_height_logits.dtype,
|
|
78
|
+
device=pixel_height_logits.device,
|
|
79
|
+
)
|
|
80
|
+
.unsqueeze(0)
|
|
81
|
+
.unsqueeze(0)
|
|
82
|
+
)
|
|
83
|
+
height_map = pixel_height_logits.unsqueeze(0).unsqueeze(0)
|
|
84
|
+
laplacian_output = F.conv2d(height_map, laplacian_kernel, padding=1)
|
|
85
|
+
patch_smooth_loss = (
|
|
86
|
+
F.huber_loss(laplacian_output, torch.zeros_like(laplacian_output)) * 10
|
|
87
|
+
)
|
|
88
|
+
total_loss = mse_loss + smoothness_loss + add_penalty_loss * patch_smooth_loss
|
|
93
89
|
else:
|
|
94
90
|
total_loss = mse_loss
|
|
95
91
|
return total_loss
|
|
@@ -95,7 +95,7 @@ class FilamentOptimizer:
|
|
|
95
95
|
|
|
96
96
|
# Tau schedule
|
|
97
97
|
self.num_steps_done = 0
|
|
98
|
-
self.warmup_steps = args.iterations
|
|
98
|
+
self.warmup_steps = min(args.iterations-1,args.warmup_fraction * args.iterations)
|
|
99
99
|
self.decay_rate = (self.init_tau - self.final_tau) / (
|
|
100
100
|
args.iterations - self.warmup_steps
|
|
101
101
|
)
|
|
@@ -197,6 +197,18 @@ class FilamentOptimizer:
|
|
|
197
197
|
/ (self.args.iterations // 5),
|
|
198
198
|
)
|
|
199
199
|
|
|
200
|
+
#start_fraction = self.args.height_logits_learning_start_fraction
|
|
201
|
+
#full_fraction = self.args.height_logits_learning_full_fraction
|
|
202
|
+
|
|
203
|
+
# total_iters = self.args.iterations
|
|
204
|
+
# current_step = self.num_steps_done
|
|
205
|
+
# if current_step < start_fraction * total_iters:
|
|
206
|
+
# scaling = 0.0
|
|
207
|
+
# elif current_step < full_fraction * total_iters:
|
|
208
|
+
# scaling = (current_step - start_fraction * total_iters) / ((full_fraction - start_fraction) * total_iters)
|
|
209
|
+
# else:
|
|
210
|
+
# scaling = 1.0
|
|
211
|
+
|
|
200
212
|
loss = loss_fn(
|
|
201
213
|
self.params,
|
|
202
214
|
target=self.target,
|
|
@@ -208,10 +220,17 @@ class FilamentOptimizer:
|
|
|
208
220
|
material_TDs=self.material_TDs,
|
|
209
221
|
background=self.background,
|
|
210
222
|
perception_loss_module=self.perception_loss_module,
|
|
211
|
-
add_penalty_loss=
|
|
223
|
+
add_penalty_loss=1.0,
|
|
212
224
|
)
|
|
213
225
|
|
|
214
226
|
loss.backward()
|
|
227
|
+
|
|
228
|
+
# We scale the gradients for the height logits by a factor of 'scaling' to force no updates in the beginning
|
|
229
|
+
# and allow stronger and stronger updates as we go along.
|
|
230
|
+
if self.params["pixel_height_logits"].grad is not None:
|
|
231
|
+
self.params["pixel_height_logits"].grad.mul_(1e-8)
|
|
232
|
+
|
|
233
|
+
|
|
215
234
|
self.optimizer.step()
|
|
216
235
|
|
|
217
236
|
self.num_steps_done += 1
|
|
@@ -45,10 +45,38 @@ def main():
|
|
|
45
45
|
"--iterations", type=int, default=5000, help="Number of optimization iterations"
|
|
46
46
|
)
|
|
47
47
|
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--warmup_fraction",
|
|
50
|
+
type=float,
|
|
51
|
+
default=1.0,
|
|
52
|
+
help="Fraction of iterations for keeping the tau at the initial value",
|
|
53
|
+
)
|
|
54
|
+
#
|
|
55
|
+
# parser.add_argument(
|
|
56
|
+
# "--height_logits_learning_start_fraction", type=float, default=0.75, help="Fraction of iterations at which we start to learn the height map"
|
|
57
|
+
# )
|
|
58
|
+
#
|
|
59
|
+
# parser.add_argument(
|
|
60
|
+
# "--height_logits_learning_full_fraction", type=float, default=1.0, help="Fraction of iterations at which the height map learning is fully enabled"
|
|
61
|
+
# )
|
|
62
|
+
|
|
63
|
+
parser.add_argument(
|
|
64
|
+
"--init_tau",
|
|
65
|
+
type=float,
|
|
66
|
+
default=1.0,
|
|
67
|
+
help="Initial tau value for Gumbel-Softmax",
|
|
68
|
+
)
|
|
69
|
+
parser.add_argument(
|
|
70
|
+
"--final_tau",
|
|
71
|
+
type=float,
|
|
72
|
+
default=0.01,
|
|
73
|
+
help="Final tau value for Gumbel-Softmax",
|
|
74
|
+
)
|
|
75
|
+
|
|
48
76
|
parser.add_argument(
|
|
49
77
|
"--learning_rate",
|
|
50
78
|
type=float,
|
|
51
|
-
default=
|
|
79
|
+
default=0.015,
|
|
52
80
|
help="Learning rate for optimization",
|
|
53
81
|
)
|
|
54
82
|
parser.add_argument(
|
|
@@ -73,19 +101,6 @@ def main():
|
|
|
73
101
|
"--background_color", type=str, default="#000000", help="Background color"
|
|
74
102
|
)
|
|
75
103
|
|
|
76
|
-
parser.add_argument(
|
|
77
|
-
"--init_tau",
|
|
78
|
-
type=float,
|
|
79
|
-
default=1.0,
|
|
80
|
-
help="Initial tau value for Gumbel-Softmax",
|
|
81
|
-
)
|
|
82
|
-
parser.add_argument(
|
|
83
|
-
"--final_tau",
|
|
84
|
-
type=float,
|
|
85
|
-
default=0.01,
|
|
86
|
-
help="Final tau value for Gumbel-Softmax",
|
|
87
|
-
)
|
|
88
|
-
|
|
89
104
|
parser.add_argument(
|
|
90
105
|
"--visualize",
|
|
91
106
|
action="store_true",
|
|
@@ -289,7 +304,7 @@ def main():
|
|
|
289
304
|
random_seed=random_seed,
|
|
290
305
|
num_threads=16,
|
|
291
306
|
init_method="kmeans",
|
|
292
|
-
cluster_layers=
|
|
307
|
+
cluster_layers=18,
|
|
293
308
|
lab_space=True,
|
|
294
309
|
)
|
|
295
310
|
|
|
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
|
{autoforge-1.6.0 → autoforge-1.6.2}/src/autoforge/Helper/Heightmaps/ChristofidesHeightMap.py
RENAMED
|
File without changes
|
{autoforge-1.6.0 → autoforge-1.6.2}/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
|