autoforge 1.3.1__tar.gz → 1.3.3__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 (31) hide show
  1. {autoforge-1.3.1 → autoforge-1.3.3}/PKG-INFO +1 -2
  2. {autoforge-1.3.1 → autoforge-1.3.3}/README.md +0 -1
  3. {autoforge-1.3.1 → autoforge-1.3.3}/pyproject.toml +1 -1
  4. {autoforge-1.3.1 → autoforge-1.3.3}/src/AutoForge.egg-info/PKG-INFO +1 -2
  5. {autoforge-1.3.1 → autoforge-1.3.3}/src/AutoForge.egg-info/SOURCES.txt +2 -1
  6. autoforge-1.3.3/src/autoforge/Helper/ImageHelper.py +22 -0
  7. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Helper/OptimizerHelper.py +43 -7
  8. autoforge-1.3.3/src/autoforge/Misc/color_fit_all.py +1877 -0
  9. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Modules/Optimizer.py +0 -6
  10. autoforge-1.3.3/src/autoforge/__init__.py +0 -0
  11. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/auto_forge.py +14 -2
  12. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/auto_forge_gradio.py +1 -1
  13. autoforge-1.3.1/src/autoforge/Helper/ImageHelper.py +0 -13
  14. autoforge-1.3.1/src/autoforge/color_fit_bayesian.py +0 -225
  15. {autoforge-1.3.1 → autoforge-1.3.3}/setup.cfg +0 -0
  16. {autoforge-1.3.1 → autoforge-1.3.3}/src/AutoForge.egg-info/dependency_links.txt +0 -0
  17. {autoforge-1.3.1 → autoforge-1.3.3}/src/AutoForge.egg-info/entry_points.txt +0 -0
  18. {autoforge-1.3.1 → autoforge-1.3.3}/src/AutoForge.egg-info/requires.txt +0 -0
  19. {autoforge-1.3.1 → autoforge-1.3.3}/src/AutoForge.egg-info/top_level.txt +0 -0
  20. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Helper/FilamentHelper.py +0 -0
  21. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Helper/OutputHelper.py +0 -0
  22. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Helper/PruningHelper.py +0 -0
  23. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Helper/__init__.py +0 -0
  24. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Loss/LossFunctions.py +0 -0
  25. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Loss/PerceptionLoss.py +0 -0
  26. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/Loss/__init__.py +0 -0
  27. {autoforge-1.3.1/src/autoforge/Modules → autoforge-1.3.3/src/autoforge/Misc}/__init__.py +0 -0
  28. {autoforge-1.3.1/src/autoforge → autoforge-1.3.3/src/autoforge/Modules}/__init__.py +0 -0
  29. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/__main__.py +0 -0
  30. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/filamentcolors_library.py +0 -0
  31. {autoforge-1.3.1 → autoforge-1.3.3}/src/autoforge/old_jax_files.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: AutoForge
3
- Version: 1.3.1
3
+ Version: 1.3.3
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
@@ -162,7 +162,6 @@ Although I would love to be it fully color compatible with hueforge, I don't thi
162
162
  AutoForge © 2025 by Hendric Voss is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/).
163
163
  The software is provided as-is and comes with no warranty or guarantee of support.
164
164
 
165
- The
166
165
 
167
166
  ## Acknowledgements
168
167
 
@@ -142,7 +142,6 @@ Although I would love to be it fully color compatible with hueforge, I don't thi
142
142
  AutoForge © 2025 by Hendric Voss is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/).
143
143
  The software is provided as-is and comes with no warranty or guarantee of support.
144
144
 
145
- The
146
145
 
147
146
  ## Acknowledgements
148
147
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "AutoForge"
7
- version="1.3.1"
7
+ version="1.3.3"
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.2
2
2
  Name: AutoForge
3
- Version: 1.3.1
3
+ Version: 1.3.3
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
@@ -162,7 +162,6 @@ Although I would love to be it fully color compatible with hueforge, I don't thi
162
162
  AutoForge © 2025 by Hendric Voss is licensed under [CC BY-NC-SA 4.0](https://creativecommons.org/licenses/by-nc-sa/4.0/).
163
163
  The software is provided as-is and comes with no warranty or guarantee of support.
164
164
 
165
- The
166
165
 
167
166
  ## Acknowledgements
168
167
 
@@ -10,7 +10,6 @@ src/autoforge/__init__.py
10
10
  src/autoforge/__main__.py
11
11
  src/autoforge/auto_forge.py
12
12
  src/autoforge/auto_forge_gradio.py
13
- src/autoforge/color_fit_bayesian.py
14
13
  src/autoforge/filamentcolors_library.py
15
14
  src/autoforge/old_jax_files.py
16
15
  src/autoforge/Helper/FilamentHelper.py
@@ -22,5 +21,7 @@ src/autoforge/Helper/__init__.py
22
21
  src/autoforge/Loss/LossFunctions.py
23
22
  src/autoforge/Loss/PerceptionLoss.py
24
23
  src/autoforge/Loss/__init__.py
24
+ src/autoforge/Misc/__init__.py
25
+ src/autoforge/Misc/color_fit_all.py
25
26
  src/autoforge/Modules/Optimizer.py
26
27
  src/autoforge/Modules/__init__.py
@@ -0,0 +1,22 @@
1
+ import cv2
2
+
3
+
4
+ def resize_image(img, max_size):
5
+ h_img, w_img, _ = img.shape
6
+
7
+ # Compute the scaling factor based on the larger dimension
8
+ if w_img >= h_img:
9
+ scale = max_size / w_img
10
+ else:
11
+ scale = max_size / h_img
12
+
13
+ # Compute new dimensions and round them
14
+ new_w = int(round(w_img * scale))
15
+ new_h = int(round(h_img * scale))
16
+
17
+ # Resize the image with an appropriate interpolation method
18
+ img_out = cv2.resize(img, (new_w, new_h), interpolation=cv2.INTER_CUBIC)
19
+ # INTER_CUBIC is actually not a good choice for shrinking images. Except in our case.
20
+ # As we shrink the image, we lose information and the image becomes blurry with INTER_AREA. This is detrimental for the solver. If you want to try it out be my guest.
21
+ # INTER_AREA actually destroys a lot of the colors of our solver.
22
+ return img_out
@@ -1,4 +1,5 @@
1
1
  import random
2
+ from itertools import permutations
2
3
 
3
4
  import numpy as np
4
5
  import torch
@@ -7,6 +8,7 @@ from skimage.color import rgb2lab
7
8
  from sklearn.cluster import KMeans
8
9
  from sklearn.exceptions import ConvergenceWarning
9
10
  from sklearn.utils._testing import ignore_warnings
11
+ from tqdm import tqdm
10
12
  from transformers import pipeline
11
13
  from PIL import Image
12
14
  from sklearn.metrics import silhouette_score
@@ -110,9 +112,10 @@ def composite_image(
110
112
  comp = torch.zeros(H, W, 3, dtype=torch.float32, device=pixel_height.device)
111
113
  remaining = torch.ones(H, W, dtype=torch.float32, device=pixel_height.device)
112
114
 
113
- A = 0.1215
114
- k = 61.6970
115
- b = 0.4773
115
+ o = -1.1021105e-02
116
+ A = 1.0786635e00
117
+ k = 3.0878708e01
118
+ b = -5.0812101e00
116
119
 
117
120
  for i in range(max_layers):
118
121
  layer_idx = max_layers - 1 - i
@@ -146,7 +149,8 @@ def composite_image(
146
149
  color_i = torch.matmul(p_i, material_colors)
147
150
  TD_i = torch.matmul(p_i, material_TDs) * 0.1
148
151
  TD_i = torch.clamp(TD_i, 1e-8, 1e8)
149
- opac = A * torch.log1p(k * (eff_thick / TD_i)) + b * (eff_thick / TD_i)
152
+
153
+ opac = o + (A * torch.log1p(k * (eff_thick / TD_i)) + b * (eff_thick / TD_i))
150
154
  opac = torch.clamp(opac, 0.0, 1.0)
151
155
 
152
156
  comp = comp + ((remaining * opac).unsqueeze(-1) * color_i)
@@ -610,7 +614,7 @@ def init_height_map(target, max_layers, h, eps=1e-6, random_seed=None):
610
614
 
611
615
  # --- Step 2: Second clustering of centroids into bands ---
612
616
  num_bands = choose_optimal_num_bands(
613
- centroids, min_bands=5, max_bands=max_layers // 2, random_seed=random_seed
617
+ centroids, min_bands=5, max_bands=10, random_seed=random_seed
614
618
  )
615
619
  band_kmeans = KMeans(n_clusters=num_bands, random_state=random_seed).fit(centroids)
616
620
  band_labels = band_kmeans.labels_
@@ -643,7 +647,39 @@ def init_height_map(target, max_layers, h, eps=1e-6, random_seed=None):
643
647
  L_values = [lab[0] for lab in band_reps]
644
648
  start_band = np.argmin(L_values) # darkest band index
645
649
  end_band = np.argmax(L_values) # brightest band index
646
- best_order = tsp_simulated_annealing(band_reps, start_band, end_band)
650
+
651
+ # --- Step 5: Find the best ordering for the middle bands ---
652
+ # We want to order the bands so that the total perceptual difference (Euclidean distance in Lab)
653
+ # between consecutive bands is minimized, while forcing the darkest band first and brightest band last.
654
+ all_indices = list(range(len(bands)))
655
+ middle_indices = [i for i in all_indices if i not in (start_band, end_band)]
656
+
657
+ min_total_distance = np.inf
658
+ best_order = None
659
+ total = len(middle_indices) * len(middle_indices)
660
+ # Try all permutations of the middle bands
661
+ ie = 0
662
+ tbar = tqdm(
663
+ permutations(middle_indices),
664
+ total=total,
665
+ desc="Finding best ordering for color bands:",
666
+ )
667
+ for perm in tbar:
668
+ candidate = [start_band] + list(perm) + [end_band]
669
+ total_distance = 0
670
+ for i in range(len(candidate) - 1):
671
+ total_distance += np.linalg.norm(
672
+ band_reps[candidate[i]] - band_reps[candidate[i + 1]]
673
+ )
674
+ if total_distance < min_total_distance:
675
+ min_total_distance = total_distance
676
+ best_order = candidate
677
+ tbar.set_description(
678
+ f"Finding best ordering for color bands: Total distance = {min_total_distance:.2f}"
679
+ )
680
+ ie += 1
681
+ if ie > 500000:
682
+ break
647
683
 
648
684
  new_order = []
649
685
  for band_idx in best_order:
@@ -656,7 +692,7 @@ def init_height_map(target, max_layers, h, eps=1e-6, random_seed=None):
656
692
 
657
693
  new_labels = new_labels.astype(np.float32) / new_labels.max()
658
694
 
659
- normalized_lum = np.array(new_labels, dtype=np.float64)
695
+ normalized_lum = np.array(new_labels, dtype=np.float32)
660
696
  # convert out to inverse sigmoid logit function
661
697
  pixel_height_logits = np.log((normalized_lum + eps) / (1 - normalized_lum + eps))
662
698