Yang2001 commited on
Commit
8d595ff
·
verified ·
1 Parent(s): 2620da1

Upload folder using huggingface_hub

Browse files
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitattributes +73 -0
  2. .gitignore +19 -0
  3. README.md +4 -2
  4. app.py +584 -0
  5. assets/app/basecolor.png +0 -0
  6. assets/app/clay.png +0 -0
  7. assets/app/hdri_city.png +0 -0
  8. assets/app/hdri_courtyard.png +0 -0
  9. assets/app/hdri_forest.png +0 -0
  10. assets/app/hdri_interior.png +0 -0
  11. assets/app/hdri_night.png +0 -0
  12. assets/app/hdri_studio.png +0 -0
  13. assets/app/hdri_sunrise.png +0 -0
  14. assets/app/hdri_sunset.png +0 -0
  15. assets/app/normal.png +0 -0
  16. assets/example_image/0a34fae7ba57cb8870df5325b9c30ea474def1b0913c19c596655b85a79fdee4.webp +3 -0
  17. assets/example_image/0e4984a9b3765ce80e9853443f9319ecedf90885c74b56cccfebc09402740f8a.webp +3 -0
  18. assets/example_image/0f168a4b1b6e96c72e9627c97a212c27a4572250ff58e25703b9d0c2bc74191a.webp +3 -0
  19. assets/example_image/130c2b18f1651a70f8aa15b2c99f8dba29bb943044d92871f9223bd3e989e8b1.webp +3 -0
  20. assets/example_image/154c88671d9e8785bd909e9283bc87fb2709ac7ce13890832603ea7533981a46.webp +0 -0
  21. assets/example_image/1c359e94f2d699055c78487c90626cf5f1d7460c8fc04e60a286507e5286a28d.webp +0 -0
  22. assets/example_image/22a868bac8e62511fccd2bc82ed31ae77ed31ae2a8a149be7150957f11b30c9b.webp +3 -0
  23. assets/example_image/25d412fe36aab9f33913bc9f5e2fb1ff6458bdb286bf14397162c672c95d3697.webp +3 -0
  24. assets/example_image/26717a7dad644a5cf7554e8e6d06cf82d3dd9bbae31620b36cc7eb38b8de7ac9.webp +3 -0
  25. assets/example_image/290af2dd390c95db88a35b8062fdd2ac1a9c28edc6533bc6a26ab2c83c523c61.webp +3 -0
  26. assets/example_image/2bb0932314bae71eec94d0d01a20d3f761ade9664e013b9a9a43c00a2f44163a.webp +3 -0
  27. assets/example_image/3723615e3766742ae35b09517152a58c36d62b707bc60d7f76f8a6c922add2c0.webp +3 -0
  28. assets/example_image/3903b87907a6b4947006e6fc7c0c64f40cd98932a02bf0ecf7d6dfae776f3a38.webp +0 -0
  29. assets/example_image/39488b45bb4820ff0f31bb07cb8d0a19ebd991adbcb22a10fc89ee41c59219ee.webp +0 -0
  30. assets/example_image/454e7d8a30486c0635369936e7bec5677b78ae5f436d0e46af0d533738be859f.webp +3 -0
  31. assets/example_image/4bc7abe209c8673dd3766ee4fad14d40acbed02d118e7629f645c60fd77313f1.webp +3 -0
  32. assets/example_image/4dae7ef0224e9305533c4801ce8144d5b3a89d883ca5d35bdb0aebb860ff705f.webp +3 -0
  33. assets/example_image/50b70c5f88a5961d2c786158655d2fce5c3b214b2717956500a66a4e5b5fbe37.webp +3 -0
  34. assets/example_image/51b1b31d40476b123db70a51ae0b5f8b8d0db695b616bc2ec4e6324eb178fc14.webp +3 -0
  35. assets/example_image/52284bf45134c59a94be150a5b18b9cc3619ada4b30ded8d8d0288383b8c016f.webp +3 -0
  36. assets/example_image/5a020584b95cf3db3b6420e9b09fb93e7c0f4046e61076e5b4c65c63dc1f5837.webp +3 -0
  37. assets/example_image/5a6c81d3b2afca4323e4b8b379e2cf06d18371a57fc8c5dc24b57e60e3216690.webp +3 -0
  38. assets/example_image/5c80e5e03a3b60b6f03eaf555ba1dafc0e4230c472d7e8c8e2c5ca0a0dfcef10.webp +3 -0
  39. assets/example_image/61fea9d08e0bd9a067c9f696621dc89165afb5aab318d0701bc025d7863dabf0.webp +3 -0
  40. assets/example_image/65433d02fc56dae164719ec29cb9646c0383aa1d0e24f0bb592899f08428d68e.webp +3 -0
  41. assets/example_image/6b6d89d46d7f53e6409dbe695a9ef8f97c5257e641da35015a78579e903acdad.webp +0 -0
  42. assets/example_image/74fe541e8c8eac8d0b5d8ba144307f6c07ed832cd19bf1d431c74292002028cd.webp +0 -0
  43. assets/example_image/799ab13a23fe319a6876b8bf48007d0374d514f5e7aa31210e9b2cecfbace082.webp +3 -0
  44. assets/example_image/7b540da337f576ffce2adc36c7459b9bbbfd845ab2160a6abbe986f1f906f6cd.webp +0 -0
  45. assets/example_image/7baa867b4790b8596ee120f9b171b727fd9428c41980577a518505507c99d8a0.webp +3 -0
  46. assets/example_image/7bd0521d20ee4805d1462a0ffb7d9aacc15180c2b741c9ac42a0d82ad3d340cb.webp +3 -0
  47. assets/example_image/7d585a8475db078593486367d98b5efa9368a60a3528c555b96026a1a674aa54.webp +3 -0
  48. assets/example_image/7d6f4da4eafcc60243daf6ed210853df394a8bad7e701cadf551e21abcc77869.webp +3 -0
  49. assets/example_image/7d7659d5943e85a73a4ffe33c6dd48f5d79601e9bf11b103516f419ce9fbf713.webp +3 -0
  50. assets/example_image/80ad7988fc2ce62fc655b21a8950865566ec3f5a8b4398f2502db6414a3e6834.webp +3 -0
.gitattributes CHANGED
@@ -33,3 +33,76 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ *.webp filter=xet diff=xet merge=xet -text
37
+ *.exr filter=xet diff=xet merge=xet -text
38
+ *.png filter=xet diff=xet merge=xet -text
39
+ *.ply filter=xet diff=xet merge=xet -text
40
+ assets/example_image/0a34fae7ba57cb8870df5325b9c30ea474def1b0913c19c596655b85a79fdee4.webp filter=lfs diff=lfs merge=lfs -text
41
+ assets/example_image/0e4984a9b3765ce80e9853443f9319ecedf90885c74b56cccfebc09402740f8a.webp filter=lfs diff=lfs merge=lfs -text
42
+ assets/example_image/0f168a4b1b6e96c72e9627c97a212c27a4572250ff58e25703b9d0c2bc74191a.webp filter=lfs diff=lfs merge=lfs -text
43
+ assets/example_image/130c2b18f1651a70f8aa15b2c99f8dba29bb943044d92871f9223bd3e989e8b1.webp filter=lfs diff=lfs merge=lfs -text
44
+ assets/example_image/22a868bac8e62511fccd2bc82ed31ae77ed31ae2a8a149be7150957f11b30c9b.webp filter=lfs diff=lfs merge=lfs -text
45
+ assets/example_image/25d412fe36aab9f33913bc9f5e2fb1ff6458bdb286bf14397162c672c95d3697.webp filter=lfs diff=lfs merge=lfs -text
46
+ assets/example_image/26717a7dad644a5cf7554e8e6d06cf82d3dd9bbae31620b36cc7eb38b8de7ac9.webp filter=lfs diff=lfs merge=lfs -text
47
+ assets/example_image/290af2dd390c95db88a35b8062fdd2ac1a9c28edc6533bc6a26ab2c83c523c61.webp filter=lfs diff=lfs merge=lfs -text
48
+ assets/example_image/2bb0932314bae71eec94d0d01a20d3f761ade9664e013b9a9a43c00a2f44163a.webp filter=lfs diff=lfs merge=lfs -text
49
+ assets/example_image/3723615e3766742ae35b09517152a58c36d62b707bc60d7f76f8a6c922add2c0.webp filter=lfs diff=lfs merge=lfs -text
50
+ assets/example_image/454e7d8a30486c0635369936e7bec5677b78ae5f436d0e46af0d533738be859f.webp filter=lfs diff=lfs merge=lfs -text
51
+ assets/example_image/4bc7abe209c8673dd3766ee4fad14d40acbed02d118e7629f645c60fd77313f1.webp filter=lfs diff=lfs merge=lfs -text
52
+ assets/example_image/4dae7ef0224e9305533c4801ce8144d5b3a89d883ca5d35bdb0aebb860ff705f.webp filter=lfs diff=lfs merge=lfs -text
53
+ assets/example_image/50b70c5f88a5961d2c786158655d2fce5c3b214b2717956500a66a4e5b5fbe37.webp filter=lfs diff=lfs merge=lfs -text
54
+ assets/example_image/51b1b31d40476b123db70a51ae0b5f8b8d0db695b616bc2ec4e6324eb178fc14.webp filter=lfs diff=lfs merge=lfs -text
55
+ assets/example_image/52284bf45134c59a94be150a5b18b9cc3619ada4b30ded8d8d0288383b8c016f.webp filter=lfs diff=lfs merge=lfs -text
56
+ assets/example_image/5a020584b95cf3db3b6420e9b09fb93e7c0f4046e61076e5b4c65c63dc1f5837.webp filter=lfs diff=lfs merge=lfs -text
57
+ assets/example_image/5a6c81d3b2afca4323e4b8b379e2cf06d18371a57fc8c5dc24b57e60e3216690.webp filter=lfs diff=lfs merge=lfs -text
58
+ assets/example_image/5c80e5e03a3b60b6f03eaf555ba1dafc0e4230c472d7e8c8e2c5ca0a0dfcef10.webp filter=lfs diff=lfs merge=lfs -text
59
+ assets/example_image/61fea9d08e0bd9a067c9f696621dc89165afb5aab318d0701bc025d7863dabf0.webp filter=lfs diff=lfs merge=lfs -text
60
+ assets/example_image/65433d02fc56dae164719ec29cb9646c0383aa1d0e24f0bb592899f08428d68e.webp filter=lfs diff=lfs merge=lfs -text
61
+ assets/example_image/799ab13a23fe319a6876b8bf48007d0374d514f5e7aa31210e9b2cecfbace082.webp filter=lfs diff=lfs merge=lfs -text
62
+ assets/example_image/7baa867b4790b8596ee120f9b171b727fd9428c41980577a518505507c99d8a0.webp filter=lfs diff=lfs merge=lfs -text
63
+ assets/example_image/7bd0521d20ee4805d1462a0ffb7d9aacc15180c2b741c9ac42a0d82ad3d340cb.webp filter=lfs diff=lfs merge=lfs -text
64
+ assets/example_image/7d585a8475db078593486367d98b5efa9368a60a3528c555b96026a1a674aa54.webp filter=lfs diff=lfs merge=lfs -text
65
+ assets/example_image/7d6f4da4eafcc60243daf6ed210853df394a8bad7e701cadf551e21abcc77869.webp filter=lfs diff=lfs merge=lfs -text
66
+ assets/example_image/7d7659d5943e85a73a4ffe33c6dd48f5d79601e9bf11b103516f419ce9fbf713.webp filter=lfs diff=lfs merge=lfs -text
67
+ assets/example_image/80ad7988fc2ce62fc655b21a8950865566ec3f5a8b4398f2502db6414a3e6834.webp filter=lfs diff=lfs merge=lfs -text
68
+ assets/example_image/8aa698c59aab48d4ce69a558d9159107890e3d64e522af404d9635ad0be21f88.webp filter=lfs diff=lfs merge=lfs -text
69
+ assets/example_image/8ce83f6a28910e755902de10918672e77dd23476f43f0f1521c48667de6cea84.webp filter=lfs diff=lfs merge=lfs -text
70
+ assets/example_image/8e12cf0977c0476396e7112f04b73d4d73569421173fcb553213d45030bddec3.webp filter=lfs diff=lfs merge=lfs -text
71
+ assets/example_image/901d8de4c2011a8502a0decd0adec0fc7418f26165cd52ced64fd44f720353ef.webp filter=lfs diff=lfs merge=lfs -text
72
+ assets/example_image/95db3c13622788ec311ae4dfa24dd88732c66ca5e340a0bf3465d2a528204037.webp filter=lfs diff=lfs merge=lfs -text
73
+ assets/example_image/9c306c7bd0e857285f536fb500c0828e5fad4e23c3ceeab92c888c568fa19101.webp filter=lfs diff=lfs merge=lfs -text
74
+ assets/example_image/T.png filter=lfs diff=lfs merge=lfs -text
75
+ assets/example_image/a13d176cd7a7d457b42d1b32223bcff1a45dafbbb42c6a272b97d65ac2f2eb52.webp filter=lfs diff=lfs merge=lfs -text
76
+ assets/example_image/a306e2ee5cbc3da45e7db48d75a0cade0bb7eee263a74bc6820c617afaba1302.webp filter=lfs diff=lfs merge=lfs -text
77
+ assets/example_image/a3d0c28c7d9c6f23adb941c4def2523572c903a94469abcaa7dd1398d28af8f1.webp filter=lfs diff=lfs merge=lfs -text
78
+ assets/example_image/a63d2595e10229067b19cb167fe2bdc152dabfd8b62ae45fc1655a4cf66509bc.webp filter=lfs diff=lfs merge=lfs -text
79
+ assets/example_image/ab3bb3e183991253ae66c06d44dc6105f3c113a1a1f819ab57a93c6f60b0d32b.webp filter=lfs diff=lfs merge=lfs -text
80
+ assets/example_image/b205f4483c47bd1fec8e229163361e4fdff9f77923c5e968343b8f1dd76b61dc.webp filter=lfs diff=lfs merge=lfs -text
81
+ assets/example_image/b358d0eb96a68ac4ba1f2fb6d44ea2225f95fdfbf9cf4e0da08650c3704f1d23.webp filter=lfs diff=lfs merge=lfs -text
82
+ assets/example_image/bb3190891dd8341c9d6d3d4faa6525c6ecdac19945526904928f6bcd2f3f45f1.webp filter=lfs diff=lfs merge=lfs -text
83
+ assets/example_image/be7deb26f4fdd2080d4288668af4c39e526564282c579559ff8a4126ca4ed6c1.webp filter=lfs diff=lfs merge=lfs -text
84
+ assets/example_image/c2125d086c2529638841f38918ae1defbf33e6796d827253885b4c51e601034f.webp filter=lfs diff=lfs merge=lfs -text
85
+ assets/example_image/c3d714bc125f06ce1187799d5ca10736b4064a24c141e627089aad2bdedf7aa5.webp filter=lfs diff=lfs merge=lfs -text
86
+ assets/example_image/c9340e744541f310bf89838f652602961d3e5950b31cd349bcbfc7e59e15cd2e.webp filter=lfs diff=lfs merge=lfs -text
87
+ assets/example_image/cd3c309f17eee5ad6afe4e001765893ade20b653f611365c93d158286b4cee96.webp filter=lfs diff=lfs merge=lfs -text
88
+ assets/example_image/cdf996a6cc218918eeb90209891ce306a230e6d9cca2a3d9bbb37c6d7b6bd318.webp filter=lfs diff=lfs merge=lfs -text
89
+ assets/example_image/d39c2bd426456bd686de33f924524d18eb47343a5f080826aa3cb8e77de5147b.webp filter=lfs diff=lfs merge=lfs -text
90
+ assets/example_image/d64c94dffdadf82d46004d11412b5a3b2a17f1b4ddb428477a7ba38652adf973.webp filter=lfs diff=lfs merge=lfs -text
91
+ assets/example_image/e134444178eae855cfdefb9e5259d076df5e34f780ee44d4ad604483ff69cc74.webp filter=lfs diff=lfs merge=lfs -text
92
+ assets/example_image/e3c57169ce3d5ce10b3c10acef20b81ca774b54a17aabe74e8aca320c7b07b55.webp filter=lfs diff=lfs merge=lfs -text
93
+ assets/example_image/e4d6b2f3a18c3e0f5146a5b40cda6c95d7f69372b2e741c023e5ec9661deda2b.webp filter=lfs diff=lfs merge=lfs -text
94
+ assets/example_image/ebd09565cf0b6593aced573dffdfff34915aa359c60ec5dd0b30cd91a7f153c8.webp filter=lfs diff=lfs merge=lfs -text
95
+ assets/example_image/ee8ecf658fde9c58830c021b2e30d0d5e7e492ef52febe7192a6c74fbf1b0472.webp filter=lfs diff=lfs merge=lfs -text
96
+ assets/example_image/f351569ddc61116da4a7b929bccdab144d011f56b9603e6e72abea05236160f4.webp filter=lfs diff=lfs merge=lfs -text
97
+ assets/example_image/f5332118a0cda9cd13fe13d4be2b00437e702d1f9af51ebb6b75219a572a6ce9.webp filter=lfs diff=lfs merge=lfs -text
98
+ assets/example_image/f8920788b704531f7a7e875afd7c5c423d62e0a987e9495c63893c2cb4d2b5dc.webp filter=lfs diff=lfs merge=lfs -text
99
+ assets/example_image/f8a7eafe26a4f3ebd26a9e7d0289e4a40b5a93e9234e94ec3e1071c352acc65a.webp filter=lfs diff=lfs merge=lfs -text
100
+ assets/example_texturing/the_forgotten_knight.ply filter=lfs diff=lfs merge=lfs -text
101
+ assets/hdri/city.exr filter=lfs diff=lfs merge=lfs -text
102
+ assets/hdri/courtyard.exr filter=lfs diff=lfs merge=lfs -text
103
+ assets/hdri/forest.exr filter=lfs diff=lfs merge=lfs -text
104
+ assets/hdri/interior.exr filter=lfs diff=lfs merge=lfs -text
105
+ assets/hdri/night.exr filter=lfs diff=lfs merge=lfs -text
106
+ assets/hdri/sunrise.exr filter=lfs diff=lfs merge=lfs -text
107
+ assets/hdri/sunset.exr filter=lfs diff=lfs merge=lfs -text
108
+ assets/teaser.webp filter=lfs diff=lfs merge=lfs -text
.gitignore ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ __pycache__/
2
+ *.pyc
3
+ .venv/
4
+ venv/
5
+ *.ckpt
6
+ *.pt
7
+ *.bin
8
+ *.safetensors
9
+ wandb/
10
+ .wandb/
11
+ node_modules/
12
+ *.egg-info/
13
+ .gradio/
14
+ example.py
15
+
16
+ outputs*/
17
+ results*/
18
+ ckpts*/
19
+ tmp/example.py
README.md CHANGED
@@ -1,12 +1,14 @@
1
  ---
2
  title: Pixal3D T
3
- emoji: 📈
4
  colorFrom: indigo
5
- colorTo: green
6
  sdk: gradio
7
  sdk_version: 6.13.0
 
8
  app_file: app.py
9
  pinned: false
 
10
  ---
11
 
12
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
  title: Pixal3D T
3
+ emoji: 🏆
4
  colorFrom: indigo
5
+ colorTo: gray
6
  sdk: gradio
7
  sdk_version: 6.13.0
8
+ python_version: "3.10"
9
  app_file: app.py
10
  pinned: false
11
+ license: mit
12
  ---
13
 
14
  Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
app.py ADDED
@@ -0,0 +1,584 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Pixal3D (TRELLIS.2 Backbone) - Gradio App
3
+
4
+ Image-to-3D generation using Proj-mode Cascade inference (512->1024/1536).
5
+
6
+ """
7
+
8
+ import gradio as gr
9
+
10
+ import os
11
+ import subprocess
12
+ subprocess.run([
13
+ "pip", "install", "--force-reinstall", "--no-deps",
14
+ "https://github.com/LDYang694/Storages/releases/download/20260430/utils3d-0.0.2-py3-none-any.whl"
15
+ ], check=True)
16
+
17
+ os.environ['OPENCV_IO_ENABLE_OPENEXR'] = '1'
18
+ os.environ["PYTORCH_CUDA_ALLOC_CONF"] = "expandable_segments:True"
19
+ import argparse
20
+ import math
21
+ import time
22
+ from datetime import datetime
23
+ import shutil
24
+ import cv2
25
+ from typing import *
26
+ import torch
27
+ import numpy as np
28
+ from PIL import Image
29
+ import base64
30
+ import io
31
+ from trellis2.modules.sparse import SparseTensor
32
+ from trellis2.pipelines import Pixal3DImageTo3DPipeline
33
+ from trellis2.renderers import EnvMap
34
+ from trellis2.utils import render_utils
35
+ import o_voxel
36
+
37
+
38
+ # ============================================================================
39
+ # Constants & Defaults
40
+ # ============================================================================
41
+
42
+ MAX_SEED = np.iinfo(np.int32).max
43
+ TMP_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'tmp')
44
+ MODES = [
45
+ {"name": "Normal", "icon": "assets/app/normal.png", "render_key": "normal"},
46
+ {"name": "Clay render", "icon": "assets/app/clay.png", "render_key": "clay"},
47
+ {"name": "Base color", "icon": "assets/app/basecolor.png", "render_key": "base_color"},
48
+ {"name": "HDRI forest", "icon": "assets/app/hdri_forest.png", "render_key": "shaded_forest"},
49
+ {"name": "HDRI sunset", "icon": "assets/app/hdri_sunset.png", "render_key": "shaded_sunset"},
50
+ {"name": "HDRI courtyard", "icon": "assets/app/hdri_courtyard.png", "render_key": "shaded_courtyard"},
51
+ ]
52
+ STEPS = 8
53
+ DEFAULT_MODE = 3
54
+ DEFAULT_STEP = 3
55
+
56
+ # Cascade parameters
57
+ CASCADE_LR_RESOLUTION = 512
58
+ CASCADE_MAX_NUM_TOKENS = 49152
59
+
60
+ # MoGe defaults
61
+ MOGE_MODEL_NAME = "Ruicheng/moge-2-vitl"
62
+ WILD_MESH_SCALE = 1.0
63
+ WILD_EXTEND_PIXEL = 0
64
+ WILD_IMAGE_RESOLUTION = 512
65
+
66
+ # Image Cond Model configs (extracted from training configs, hardcoded)
67
+ IMAGE_COND_CONFIGS = {
68
+ "ss": {
69
+ "model_name": "camenduru/dinov3-vitl16-pretrain-lvd1689m",
70
+ "image_size": 512,
71
+ "grid_resolution": 16,
72
+ },
73
+ "shape_512": {
74
+ "model_name": "camenduru/dinov3-vitl16-pretrain-lvd1689m",
75
+ "image_size": 512,
76
+ "grid_resolution": 32,
77
+ "use_naf_upsample": True,
78
+ "naf_target_size": 512,
79
+ },
80
+ "shape_1024": {
81
+ "model_name": "camenduru/dinov3-vitl16-pretrain-lvd1689m",
82
+ "image_size": 1024,
83
+ "grid_resolution": 64,
84
+ "use_naf_upsample": True,
85
+ "naf_target_size": 512,
86
+ },
87
+ "tex_1024": {
88
+ "model_name": "camenduru/dinov3-vitl16-pretrain-lvd1689m",
89
+ "image_size": 1024,
90
+ "grid_resolution": 64,
91
+ "use_naf_upsample": True,
92
+ "naf_target_size": 1024,
93
+ },
94
+ }
95
+
96
+
97
+ # ============================================================================
98
+ # CSS & JS
99
+ # ============================================================================
100
+
101
+ css = """
102
+ .stepper-wrapper { padding: 0; }
103
+ .stepper-container { padding: 0; align-items: center; }
104
+ .step-button { flex-direction: row; }
105
+ .step-connector { transform: none; }
106
+ .step-number { width: 16px; height: 16px; }
107
+ .step-label { position: relative; bottom: 0; }
108
+ .wrap.center.full { inset: 0; height: 100%; }
109
+ .wrap.center.full.translucent { background: var(--block-background-fill); }
110
+ .meta-text-center {
111
+ display: block !important; position: absolute !important;
112
+ top: unset !important; bottom: 0 !important; right: 0 !important; transform: unset !important;
113
+ }
114
+ .previewer-container {
115
+ position: relative;
116
+ font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
117
+ width: 100%; height: 722px; margin: 0 auto; padding: 20px;
118
+ display: flex; flex-direction: column; align-items: center; justify-content: center;
119
+ }
120
+ .previewer-container .tips-icon {
121
+ position: absolute; right: 10px; top: 10px; z-index: 10;
122
+ border-radius: 10px; color: #fff; background-color: var(--color-accent); padding: 3px 6px; user-select: none;
123
+ }
124
+ .previewer-container .tips-text {
125
+ position: absolute; right: 10px; top: 50px; color: #fff; background-color: var(--color-accent);
126
+ border-radius: 10px; padding: 6px; text-align: left; max-width: 300px; z-index: 10;
127
+ transition: all 0.3s; opacity: 0%; user-select: none;
128
+ }
129
+ .previewer-container .tips-text p { font-size: 14px; line-height: 1.2; }
130
+ .tips-icon:hover + .tips-text { display: block; opacity: 100%; }
131
+ .previewer-container .mode-row {
132
+ width: 100%; display: flex; gap: 8px; justify-content: center; margin-bottom: 20px; flex-wrap: wrap;
133
+ }
134
+ .previewer-container .mode-btn {
135
+ width: 24px; height: 24px; border-radius: 50%; cursor: pointer; opacity: 0.5;
136
+ transition: all 0.2s; border: 2px solid #ddd; object-fit: cover;
137
+ }
138
+ .previewer-container .mode-btn:hover { opacity: 0.9; transform: scale(1.1); }
139
+ .previewer-container .mode-btn.active { opacity: 1; border-color: var(--color-accent); transform: scale(1.1); }
140
+ .previewer-container .display-row {
141
+ margin-bottom: 20px; min-height: 400px; width: 100%; flex-grow: 1;
142
+ display: flex; justify-content: center; align-items: center;
143
+ }
144
+ .previewer-container .previewer-main-image {
145
+ max-width: 100%; max-height: 100%; flex-grow: 1; object-fit: contain; display: none;
146
+ }
147
+ .previewer-container .previewer-main-image.visible { display: block; }
148
+ .previewer-container .slider-row {
149
+ width: 100%; display: flex; flex-direction: column; align-items: center; gap: 10px; padding: 0 10px;
150
+ }
151
+ .previewer-container input[type=range] { -webkit-appearance: none; width: 100%; max-width: 400px; background: transparent; }
152
+ .previewer-container input[type=range]::-webkit-slider-runnable-track {
153
+ width: 100%; height: 8px; cursor: pointer; background: #ddd; border-radius: 5px;
154
+ }
155
+ .previewer-container input[type=range]::-webkit-slider-thumb {
156
+ height: 20px; width: 20px; border-radius: 50%; background: var(--color-accent);
157
+ cursor: pointer; -webkit-appearance: none; margin-top: -6px;
158
+ box-shadow: 0 2px 5px rgba(0,0,0,0.2); transition: transform 0.1s;
159
+ }
160
+ .previewer-container input[type=range]::-webkit-slider-thumb:hover { transform: scale(1.2); }
161
+ .gradio-container .padded:has(.previewer-container) { padding: 0 !important; }
162
+ .gradio-container:has(.previewer-container) [data-testid="block-label"] { position: absolute; top: 0; left: 0; }
163
+ """
164
+
165
+ head = """
166
+ <script>
167
+ function refreshView(mode, step) {
168
+ const allImgs = document.querySelectorAll('.previewer-main-image');
169
+ for (let i = 0; i < allImgs.length; i++) {
170
+ const img = allImgs[i];
171
+ if (img.classList.contains('visible')) {
172
+ const id = img.id;
173
+ const [_, m, s] = id.split('-');
174
+ if (mode === -1) mode = parseInt(m.slice(1));
175
+ if (step === -1) step = parseInt(s.slice(1));
176
+ break;
177
+ }
178
+ }
179
+ allImgs.forEach(img => img.classList.remove('visible'));
180
+ const targetId = 'view-m' + mode + '-s' + step;
181
+ const targetImg = document.getElementById(targetId);
182
+ if (targetImg) targetImg.classList.add('visible');
183
+ const allBtns = document.querySelectorAll('.mode-btn');
184
+ allBtns.forEach((btn, idx) => {
185
+ if (idx === mode) btn.classList.add('active');
186
+ else btn.classList.remove('active');
187
+ });
188
+ }
189
+ function selectMode(mode) { refreshView(mode, -1); }
190
+ function onSliderChange(val) { refreshView(-1, parseInt(val)); }
191
+ </script>
192
+ """
193
+
194
+ empty_html = f"""
195
+ <div class="previewer-container">
196
+ <svg style=" opacity: .5; height: var(--size-5); color: var(--body-text-color);"
197
+ xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="feather feather-image"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"></rect><circle cx="8.5" cy="8.5" r="1.5"></circle><polyline points="21 15 16 10 5 21"></polyline></svg>
198
+ </div>
199
+ """
200
+
201
+
202
+ # ============================================================================
203
+ # Model Loading Utilities
204
+ # ============================================================================
205
+
206
+ def build_image_cond_model(config: dict):
207
+ """Build DinoV3ProjFeatureExtractor."""
208
+ from trellis2.trainers.flow_matching.mixins.image_conditioned_proj import DinoV3ProjFeatureExtractor
209
+ model = DinoV3ProjFeatureExtractor(**config)
210
+ model.eval()
211
+ return model
212
+
213
+
214
+ # ============================================================================
215
+ # Camera Parameter Utilities
216
+ # ============================================================================
217
+
218
+ def compute_f_pixels(camera_angle_x: float, resolution: int) -> float:
219
+ focal_length = 16.0 / torch.tan(torch.tensor(camera_angle_x / 2.0))
220
+ f_pixels = focal_length * resolution / 32.0
221
+ return float(f_pixels.item())
222
+
223
+
224
+ def distance_from_fov(camera_angle_x, grid_point, target_point, mesh_scale, image_resolution):
225
+ rotation_matrix = torch.tensor([[1.0, 0.0, 0.0], [0.0, 0.0, -1.0], [0.0, 1.0, 0.0]])
226
+ gp = grid_point.to(torch.float32) @ rotation_matrix.T
227
+ gp = gp / mesh_scale / 2
228
+ xw, yw, zw = gp[0].item(), gp[1].item(), gp[2].item()
229
+ xt, yt = float(target_point[0].item()), float(target_point[1].item())
230
+ f_pixels = compute_f_pixels(camera_angle_x, image_resolution)
231
+ x_ndc = xt - image_resolution / 2.0
232
+ y_ndc = -(yt - image_resolution / 2.0)
233
+ distance_x = f_pixels * xw / x_ndc - yw
234
+ return {"distance_from_x": float(distance_x), "f_pixels": float(f_pixels)}
235
+
236
+
237
+ def load_moge_model(device="cuda", model_name=MOGE_MODEL_NAME):
238
+ print(f"[MoGe-2] Loading model {model_name}...")
239
+ from moge.model.v2 import MoGeModel
240
+ moge_model = MoGeModel.from_pretrained(model_name).to(device)
241
+ moge_model.eval()
242
+ print("[MoGe-2] Model loaded!")
243
+ return moge_model
244
+
245
+
246
+ def get_camera_params_wild_moge(image, moge_model, device="cuda",
247
+ mesh_scale=1.0, extend_pixel=0, image_resolution=512):
248
+ """Estimate camera parameters via MoGe-2."""
249
+ if isinstance(image, str):
250
+ pil_image = Image.open(image).convert("RGB")
251
+ elif isinstance(image, Image.Image):
252
+ pil_image = image.convert("RGB")
253
+ else:
254
+ raise ValueError(f"Unsupported image type: {type(image)}")
255
+ width, height = pil_image.size
256
+ image_np = np.array(pil_image).astype(np.float32) / 255.0
257
+ image_tensor = torch.from_numpy(image_np).permute(2, 0, 1).to(device)
258
+ with torch.no_grad():
259
+ output = moge_model.infer(image_tensor)
260
+ intrinsics = output["intrinsics"].squeeze().cpu().numpy()
261
+ fx_normalized = intrinsics[0, 0]
262
+ fx = fx_normalized * width
263
+ camera_angle_x = 2 * math.atan(width / (2 * fx))
264
+
265
+ grid_point = torch.tensor([-1.0, 0.0, 0.0])
266
+ distance = distance_from_fov(
267
+ camera_angle_x, grid_point,
268
+ torch.tensor([0 - extend_pixel, image_resolution - 1 + extend_pixel]),
269
+ mesh_scale, image_resolution
270
+ )["distance_from_x"]
271
+ return {'camera_angle_x': camera_angle_x, 'distance': distance, 'mesh_scale': mesh_scale}
272
+
273
+
274
+ # ============================================================================
275
+ # UI Utilities
276
+ # ============================================================================
277
+
278
+ def image_to_base64(image):
279
+ buffered = io.BytesIO()
280
+ image = image.convert("RGB")
281
+ image.save(buffered, format="jpeg", quality=85)
282
+ img_str = base64.b64encode(buffered.getvalue()).decode()
283
+ return f"data:image/jpeg;base64,{img_str}"
284
+
285
+
286
+ def start_session(req: gr.Request):
287
+ user_dir = os.path.join(TMP_DIR, str(req.session_hash))
288
+ os.makedirs(user_dir, exist_ok=True)
289
+
290
+
291
+ def end_session(req: gr.Request):
292
+ user_dir = os.path.join(TMP_DIR, str(req.session_hash))
293
+ if os.path.exists(user_dir):
294
+ shutil.rmtree(user_dir)
295
+
296
+
297
+ def preprocess_image(image: Image.Image) -> Image.Image:
298
+ return pipeline.preprocess_image(image)
299
+
300
+
301
+ def pack_state(shape_slat, tex_slat, res):
302
+ return {
303
+ 'shape_slat_feats': shape_slat.feats.cpu().numpy(),
304
+ 'tex_slat_feats': tex_slat.feats.cpu().numpy(),
305
+ 'coords': shape_slat.coords.cpu().numpy(),
306
+ 'res': res,
307
+ }
308
+
309
+
310
+ def unpack_state(state):
311
+ shape_slat = SparseTensor(
312
+ feats=torch.from_numpy(state['shape_slat_feats']).cuda(),
313
+ coords=torch.from_numpy(state['coords']).cuda(),
314
+ )
315
+ tex_slat = shape_slat.replace(torch.from_numpy(state['tex_slat_feats']).cuda())
316
+ return shape_slat, tex_slat, state['res']
317
+
318
+
319
+ def get_seed(randomize_seed, seed):
320
+ return np.random.randint(0, MAX_SEED) if randomize_seed else seed
321
+
322
+
323
+ # ============================================================================
324
+ # Core Inference
325
+ # ============================================================================
326
+
327
+ def image_to_3d(
328
+ image, seed, resolution,
329
+ ss_guidance_strength, ss_guidance_rescale, ss_sampling_steps, ss_rescale_t,
330
+ shape_slat_guidance_strength, shape_slat_guidance_rescale, shape_slat_sampling_steps, shape_slat_rescale_t,
331
+ tex_slat_guidance_strength, tex_slat_guidance_rescale, tex_slat_sampling_steps, tex_slat_rescale_t,
332
+ req: gr.Request,
333
+ progress=gr.Progress(track_tqdm=True),
334
+ ):
335
+ device = pipeline.device
336
+ torch.manual_seed(seed)
337
+ hr_resolution = int(resolution)
338
+
339
+ total_t0 = time.time()
340
+ print(f"\n{'='*60}")
341
+ print(f" [Generate] Start | seed={seed}, resolution={hr_resolution}")
342
+ print(f"{'='*60}")
343
+
344
+ # Preprocessing
345
+ image_preprocessed = pipeline.preprocess_image(image)
346
+
347
+ # Camera estimation via MoGe-2
348
+ camera_params = get_camera_params_wild_moge(
349
+ image_preprocessed, moge_model, device=str(device),
350
+ mesh_scale=WILD_MESH_SCALE, extend_pixel=WILD_EXTEND_PIXEL,
351
+ image_resolution=WILD_IMAGE_RESOLUTION,
352
+ )
353
+
354
+ ss_sampler_override = {"steps": ss_sampling_steps, "guidance_strength": ss_guidance_strength,
355
+ "guidance_rescale": ss_guidance_rescale, "rescale_t": ss_rescale_t}
356
+ shape_sampler_override = {"steps": shape_slat_sampling_steps, "guidance_strength": shape_slat_guidance_strength,
357
+ "guidance_rescale": shape_slat_guidance_rescale, "rescale_t": shape_slat_rescale_t}
358
+ tex_sampler_override = {"steps": tex_slat_sampling_steps, "guidance_strength": tex_slat_guidance_strength,
359
+ "guidance_rescale": tex_slat_guidance_rescale, "rescale_t": tex_slat_rescale_t}
360
+
361
+ # Run pipeline
362
+ pipeline_type = f"{hr_resolution}_cascade"
363
+ mesh_list, (shape_slat, tex_slat, res) = pipeline.run(
364
+ image_preprocessed,
365
+ camera_params=camera_params,
366
+ seed=seed,
367
+ sparse_structure_sampler_params=ss_sampler_override,
368
+ shape_slat_sampler_params=shape_sampler_override,
369
+ tex_slat_sampler_params=tex_sampler_override,
370
+ preprocess_image=False,
371
+ return_latent=True,
372
+ pipeline_type=pipeline_type,
373
+ max_num_tokens=CASCADE_MAX_NUM_TOKENS,
374
+ )
375
+ mesh = mesh_list[0]
376
+ state = pack_state(shape_slat, tex_slat, res)
377
+ del shape_slat, tex_slat, mesh_list
378
+ torch.cuda.empty_cache()
379
+
380
+ # Render
381
+ mesh.simplify(16777216)
382
+ images = render_utils.render_proj_aligned_video(
383
+ mesh, camera_angle_x=camera_params['camera_angle_x'],
384
+ distance=camera_params['distance'], resolution=1024,
385
+ num_frames=STEPS, envmap=envmap,
386
+ )
387
+ del mesh
388
+ torch.cuda.empty_cache()
389
+ print(f"\n [Generate] Total time: {time.time()-total_t0:.2f}s")
390
+
391
+ # Build HTML
392
+ images_html = ""
393
+ for m_idx, mode in enumerate(MODES):
394
+ for s_idx in range(STEPS):
395
+ unique_id = f"view-m{m_idx}-s{s_idx}"
396
+ is_visible = (m_idx == DEFAULT_MODE and s_idx == DEFAULT_STEP)
397
+ vis_class = "visible" if is_visible else ""
398
+ img_base64 = image_to_base64(Image.fromarray(images[mode['render_key']][s_idx]))
399
+ images_html += f'<img id="{unique_id}" class="previewer-main-image {vis_class}" src="{img_base64}" loading="eager">'
400
+
401
+ btns_html = ""
402
+ for idx, mode in enumerate(MODES):
403
+ active_class = "active" if idx == DEFAULT_MODE else ""
404
+ btns_html += f'<img src="{mode["icon_base64"]}" class="mode-btn {active_class}" onclick="selectMode({idx})" title="{mode["name"]}">'
405
+
406
+ full_html = f"""
407
+ <div class="previewer-container">
408
+ <div class="tips-wrapper">
409
+ <div class="tips-icon">Tips</div>
410
+ <div class="tips-text">
411
+ <p>Render Mode - Click circular buttons to switch render modes.</p>
412
+ <p>View Angle - Drag the slider to change the view angle.</p>
413
+ </div>
414
+ </div>
415
+ <div class="display-row">{images_html}</div>
416
+ <div class="mode-row" id="btn-group">{btns_html}</div>
417
+ <div class="slider-row">
418
+ <input type="range" id="custom-slider" min="0" max="{STEPS - 1}" value="{DEFAULT_STEP}" step="1" oninput="onSliderChange(this.value)">
419
+ </div>
420
+ </div>
421
+ """
422
+ return state, full_html
423
+
424
+
425
+ def extract_glb(state, decimation_target, texture_size, req: gr.Request, progress=gr.Progress(track_tqdm=True)):
426
+ user_dir = os.path.join(TMP_DIR, str(req.session_hash))
427
+ shape_slat, tex_slat, res = unpack_state(state)
428
+ mesh = pipeline.decode_latent(shape_slat, tex_slat, res)[0]
429
+ glb = o_voxel.postprocess.to_glb(
430
+ vertices=mesh.vertices, faces=mesh.faces, attr_volume=mesh.attrs,
431
+ coords=mesh.coords, attr_layout=pipeline.pbr_attr_layout,
432
+ grid_size=res, aabb=[[-0.5, -0.5, -0.5], [0.5, 0.5, 0.5]],
433
+ decimation_target=decimation_target, texture_size=texture_size,
434
+ remesh=True, remesh_band=1, remesh_project=0, use_tqdm=True,
435
+ )
436
+ now = datetime.now()
437
+ timestamp = now.strftime("%Y-%m-%dT%H%M%S") + f".{now.microsecond // 1000:03d}"
438
+ os.makedirs(user_dir, exist_ok=True)
439
+ glb_path = os.path.join(user_dir, f'sample_{timestamp}.glb')
440
+ glb.export(glb_path, extension_webp=True)
441
+ torch.cuda.empty_cache()
442
+ return glb_path, glb_path
443
+
444
+
445
+ # ============================================================================
446
+ # Gradio UI
447
+ # ============================================================================
448
+
449
+ with gr.Blocks(delete_cache=(600, 600)) as demo:
450
+ gr.Markdown("""
451
+ ## Image to 3D Asset with Pixal3D (TRELLIS.2 Backbone)
452
+ * Upload an image and click **Generate** to create a 3D asset using Pixal3D with TRELLIS.2 backbone.
453
+ * Click **Extract GLB** to export and download the generated GLB file.
454
+ * Camera parameters are estimated automatically via MoGe-2.
455
+ """)
456
+
457
+ with gr.Row():
458
+ with gr.Column(scale=1, min_width=360):
459
+ image_prompt = gr.Image(label="Image Prompt", format="png", image_mode="RGBA", type="pil", height=400)
460
+ resolution = gr.Radio(["1024", "1536"], label="Resolution", value="1536")
461
+ seed = gr.Slider(0, MAX_SEED, label="Seed", value=42, step=1)
462
+ randomize_seed = gr.Checkbox(label="Randomize Seed", value=True)
463
+ decimation_target = gr.Slider(100000, 1000000, label="Decimation Target", value=1000000, step=10000)
464
+ texture_size = gr.Slider(1024, 4096, label="Texture Size", value=4096, step=1024)
465
+ generate_btn = gr.Button("Generate")
466
+
467
+ with gr.Accordion(label="Advanced Settings", open=False):
468
+ gr.Markdown("Stage 1: Sparse Structure Generation")
469
+ with gr.Row():
470
+ ss_guidance_strength = gr.Slider(1.0, 10.0, label="Guidance Strength", value=7.5, step=0.1)
471
+ ss_guidance_rescale = gr.Slider(0.0, 1.0, label="Guidance Rescale", value=0.7, step=0.01)
472
+ ss_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
473
+ ss_rescale_t = gr.Slider(1.0, 6.0, label="Rescale T", value=5.0, step=0.1)
474
+ gr.Markdown("Stage 2: Shape Generation")
475
+ with gr.Row():
476
+ shape_slat_guidance_strength = gr.Slider(1.0, 10.0, label="Guidance Strength", value=7.5, step=0.1)
477
+ shape_slat_guidance_rescale = gr.Slider(0.0, 1.0, label="Guidance Rescale", value=0.5, step=0.01)
478
+ shape_slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
479
+ shape_slat_rescale_t = gr.Slider(1.0, 6.0, label="Rescale T", value=3.0, step=0.1)
480
+ gr.Markdown("Stage 3: Material Generation")
481
+ with gr.Row():
482
+ tex_slat_guidance_strength = gr.Slider(1.0, 10.0, label="Guidance Strength", value=1.0, step=0.1)
483
+ tex_slat_guidance_rescale = gr.Slider(0.0, 1.0, label="Guidance Rescale", value=0.0, step=0.01)
484
+ tex_slat_sampling_steps = gr.Slider(1, 50, label="Sampling Steps", value=12, step=1)
485
+ tex_slat_rescale_t = gr.Slider(1.0, 6.0, label="Rescale T", value=3.0, step=0.1)
486
+
487
+ with gr.Column(scale=10):
488
+ with gr.Walkthrough(selected=0) as walkthrough:
489
+ with gr.Step("Preview", id=0):
490
+ preview_output = gr.HTML(empty_html, label="3D Asset Preview", show_label=True, container=True)
491
+ extract_btn = gr.Button("Extract GLB")
492
+ with gr.Step("Extract", id=1):
493
+ glb_output = gr.Model3D(label="Extracted GLB", height=724, show_label=True, display_mode="solid", clear_color=(0.25, 0.25, 0.25, 1.0))
494
+ download_btn = gr.DownloadButton(label="Download GLB")
495
+
496
+ with gr.Column(scale=1, min_width=172):
497
+ examples = gr.Examples(
498
+ examples=[f'assets/example_image/{image}' for image in os.listdir("assets/example_image")],
499
+ inputs=[image_prompt], fn=preprocess_image, outputs=[image_prompt],
500
+ run_on_click=True, examples_per_page=18,
501
+ )
502
+
503
+ output_buf = gr.State()
504
+
505
+ demo.load(start_session)
506
+ demo.unload(end_session)
507
+ image_prompt.upload(preprocess_image, inputs=[image_prompt], outputs=[image_prompt])
508
+
509
+ generate_btn.click(get_seed, inputs=[randomize_seed, seed], outputs=[seed]).then(
510
+ lambda: gr.Walkthrough(selected=0), outputs=walkthrough
511
+ ).then(
512
+ image_to_3d,
513
+ inputs=[image_prompt, seed, resolution,
514
+ ss_guidance_strength, ss_guidance_rescale, ss_sampling_steps, ss_rescale_t,
515
+ shape_slat_guidance_strength, shape_slat_guidance_rescale, shape_slat_sampling_steps, shape_slat_rescale_t,
516
+ tex_slat_guidance_strength, tex_slat_guidance_rescale, tex_slat_sampling_steps, tex_slat_rescale_t],
517
+ outputs=[output_buf, preview_output],
518
+ )
519
+
520
+ extract_btn.click(lambda: gr.Walkthrough(selected=1), outputs=walkthrough).then(
521
+ extract_glb, inputs=[output_buf, decimation_target, texture_size], outputs=[glb_output, download_btn],
522
+ )
523
+
524
+
525
+ # ============================================================================
526
+ # Launch
527
+ # ============================================================================
528
+
529
+ def parse_args():
530
+ parser = argparse.ArgumentParser(description="Pixal3D Gradio App")
531
+ parser.add_argument("--model_path", type=str, default="TencentARC/Pixal3D-T",
532
+ help="HuggingFace repo ID or local path (default: TencentARC/Pixal3D-T)")
533
+ parser.add_argument("--port", type=int, default=7860)
534
+ parser.add_argument("--share", action="store_true", default=True)
535
+ return parser.parse_args()
536
+
537
+
538
+ if __name__ == "__main__":
539
+ args = parse_args()
540
+ os.makedirs(TMP_DIR, exist_ok=True)
541
+
542
+ # Construct UI icon base64
543
+ for i in range(len(MODES)):
544
+ icon = Image.open(MODES[i]['icon'])
545
+ MODES[i]['icon_base64'] = image_to_base64(icon)
546
+
547
+ # Load pipeline from HuggingFace or local path
548
+ print(f"[Pipeline] Loading from {args.model_path}...")
549
+ pipeline = Pixal3DImageTo3DPipeline.from_pretrained(args.model_path)
550
+
551
+ # Load environment maps
552
+ envmap = {
553
+ 'forest': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread('assets/hdri/forest.exr', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
554
+ 'sunset': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread('assets/hdri/sunset.exr', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
555
+ 'courtyard': EnvMap(torch.tensor(cv2.cvtColor(cv2.imread('assets/hdri/courtyard.exr', cv2.IMREAD_UNCHANGED), cv2.COLOR_BGR2RGB), dtype=torch.float32, device='cuda')),
556
+ }
557
+
558
+ # Build image cond models and set on pipeline
559
+ print("[ImageCond] Building DinoV3ProjFeatureExtractor models...")
560
+ pipeline.image_cond_model_ss = build_image_cond_model(IMAGE_COND_CONFIGS["ss"])
561
+ pipeline.image_cond_model_shape_512 = build_image_cond_model(IMAGE_COND_CONFIGS["shape_512"])
562
+ pipeline.image_cond_model_shape_1024 = build_image_cond_model(IMAGE_COND_CONFIGS["shape_1024"])
563
+ pipeline.image_cond_model_tex_1024 = build_image_cond_model(IMAGE_COND_CONFIGS["tex_1024"])
564
+
565
+ pipeline.cuda()
566
+
567
+ # Pre-download NAF model (avoid lazy-loading during inference)
568
+ print("[NAF] Pre-loading NAF upsampler model...")
569
+ for attr in ['image_cond_model_ss', 'image_cond_model_shape_512', 'image_cond_model_shape_1024', 'image_cond_model_tex_1024']:
570
+ model = getattr(pipeline, attr, None)
571
+ if model is not None and getattr(model, 'use_naf_upsample', False):
572
+ model._load_naf()
573
+ print("[NAF] NAF model loaded.")
574
+
575
+ # Load MoGe-2
576
+ print("\n[MoGe-2] Loading model for camera estimation...")
577
+ moge_model = load_moge_model(device="cuda")
578
+
579
+ print(f"\n{'=' * 60}")
580
+ print(f" Pixal3D ready! Model loaded from: {args.model_path}")
581
+ print(f" Cascade: {CASCADE_LR_RESOLUTION} -> 1024/1536")
582
+ print(f"{'=' * 60}\n")
583
+
584
+ demo.launch(css=css, head=head, server_port=args.port, share=args.share)
assets/app/basecolor.png ADDED
assets/app/clay.png ADDED
assets/app/hdri_city.png ADDED
assets/app/hdri_courtyard.png ADDED
assets/app/hdri_forest.png ADDED
assets/app/hdri_interior.png ADDED
assets/app/hdri_night.png ADDED
assets/app/hdri_studio.png ADDED
assets/app/hdri_sunrise.png ADDED
assets/app/hdri_sunset.png ADDED
assets/app/normal.png ADDED
assets/example_image/0a34fae7ba57cb8870df5325b9c30ea474def1b0913c19c596655b85a79fdee4.webp ADDED

Git LFS Details

  • SHA256: 83d3765ff57511f11054d62e6beaf52648d277006b6dcb3c1d5f9e03ef502c49
  • Pointer size: 131 Bytes
  • Size of remote file: 108 kB
assets/example_image/0e4984a9b3765ce80e9853443f9319ecedf90885c74b56cccfebc09402740f8a.webp ADDED

Git LFS Details

  • SHA256: a31ba3b084757faa66e4bb91a85bd956fcc1eaaaf298a091fd08044351cd0293
  • Pointer size: 131 Bytes
  • Size of remote file: 184 kB
assets/example_image/0f168a4b1b6e96c72e9627c97a212c27a4572250ff58e25703b9d0c2bc74191a.webp ADDED

Git LFS Details

  • SHA256: a8d419ac16852b73fbc7b92c6857ba5d4be2f2dd8056bf44af707e6af4d62207
  • Pointer size: 131 Bytes
  • Size of remote file: 157 kB
assets/example_image/130c2b18f1651a70f8aa15b2c99f8dba29bb943044d92871f9223bd3e989e8b1.webp ADDED

Git LFS Details

  • SHA256: f1a36d67f1cd7bba5c78b429c85346990aa3f269e19eee60b6d8b5d632cd743a
  • Pointer size: 131 Bytes
  • Size of remote file: 100 kB
assets/example_image/154c88671d9e8785bd909e9283bc87fb2709ac7ce13890832603ea7533981a46.webp ADDED
assets/example_image/1c359e94f2d699055c78487c90626cf5f1d7460c8fc04e60a286507e5286a28d.webp ADDED
assets/example_image/22a868bac8e62511fccd2bc82ed31ae77ed31ae2a8a149be7150957f11b30c9b.webp ADDED

Git LFS Details

  • SHA256: eb7cdcea3b238d40c7b838659288f5c12febd77292b22d44f54f785e2712d49a
  • Pointer size: 131 Bytes
  • Size of remote file: 160 kB
assets/example_image/25d412fe36aab9f33913bc9f5e2fb1ff6458bdb286bf14397162c672c95d3697.webp ADDED

Git LFS Details

  • SHA256: 4202eb19d6802319aa140e65385b3474d09aaa7f008218acf1e1f5186b923c90
  • Pointer size: 131 Bytes
  • Size of remote file: 167 kB
assets/example_image/26717a7dad644a5cf7554e8e6d06cf82d3dd9bbae31620b36cc7eb38b8de7ac9.webp ADDED

Git LFS Details

  • SHA256: d15269d0c0b427eabcca39d6d093cc2cfdaab19cb8a40b6158988a70a91ffe45
  • Pointer size: 131 Bytes
  • Size of remote file: 207 kB
assets/example_image/290af2dd390c95db88a35b8062fdd2ac1a9c28edc6533bc6a26ab2c83c523c61.webp ADDED

Git LFS Details

  • SHA256: 6cd45dd941dc559191c71f49ac5841fc6d06d32c7427fcf535f38c007611cd3f
  • Pointer size: 131 Bytes
  • Size of remote file: 109 kB
assets/example_image/2bb0932314bae71eec94d0d01a20d3f761ade9664e013b9a9a43c00a2f44163a.webp ADDED

Git LFS Details

  • SHA256: c4e26e3e2f3de96cf396c64f1cef39ac82c13f231e2567fe0fe902dc103bf949
  • Pointer size: 131 Bytes
  • Size of remote file: 170 kB
assets/example_image/3723615e3766742ae35b09517152a58c36d62b707bc60d7f76f8a6c922add2c0.webp ADDED

Git LFS Details

  • SHA256: 88c65db47f93beed7d6b184c32f9fa27c5f64ced2e3d4f535ad628179763cff8
  • Pointer size: 131 Bytes
  • Size of remote file: 116 kB
assets/example_image/3903b87907a6b4947006e6fc7c0c64f40cd98932a02bf0ecf7d6dfae776f3a38.webp ADDED
assets/example_image/39488b45bb4820ff0f31bb07cb8d0a19ebd991adbcb22a10fc89ee41c59219ee.webp ADDED
assets/example_image/454e7d8a30486c0635369936e7bec5677b78ae5f436d0e46af0d533738be859f.webp ADDED

Git LFS Details

  • SHA256: 47be8271d2d1d27fc334cc470d63534807ad44c6f50cee18a204125a1c6b66a4
  • Pointer size: 131 Bytes
  • Size of remote file: 140 kB
assets/example_image/4bc7abe209c8673dd3766ee4fad14d40acbed02d118e7629f645c60fd77313f1.webp ADDED

Git LFS Details

  • SHA256: ae7ad70cbb2a616fca63bc73d319172d5fda0930c4aaf9d897e21c09ccf17ad7
  • Pointer size: 131 Bytes
  • Size of remote file: 168 kB
assets/example_image/4dae7ef0224e9305533c4801ce8144d5b3a89d883ca5d35bdb0aebb860ff705f.webp ADDED

Git LFS Details

  • SHA256: 2b5ca8a0b47aa2dbd5480cd356e7ab574dadd565ed738ac5ed655f36a4349eea
  • Pointer size: 131 Bytes
  • Size of remote file: 175 kB
assets/example_image/50b70c5f88a5961d2c786158655d2fce5c3b214b2717956500a66a4e5b5fbe37.webp ADDED

Git LFS Details

  • SHA256: 933c10aeebb2920b08cb34a08ab1878817b64eb9e30efdcc3d76731069fc0849
  • Pointer size: 131 Bytes
  • Size of remote file: 131 kB
assets/example_image/51b1b31d40476b123db70a51ae0b5f8b8d0db695b616bc2ec4e6324eb178fc14.webp ADDED

Git LFS Details

  • SHA256: 2d5224235eeadadfdb93ab37664055ef55ffd930b085d268cd62c5faf9d101de
  • Pointer size: 131 Bytes
  • Size of remote file: 137 kB
assets/example_image/52284bf45134c59a94be150a5b18b9cc3619ada4b30ded8d8d0288383b8c016f.webp ADDED

Git LFS Details

  • SHA256: 86b909e6847118f2cec6e9c0945e6a78154ce5918f4ba14c0b0afa0be2e8647f
  • Pointer size: 131 Bytes
  • Size of remote file: 150 kB
assets/example_image/5a020584b95cf3db3b6420e9b09fb93e7c0f4046e61076e5b4c65c63dc1f5837.webp ADDED

Git LFS Details

  • SHA256: 62b7097ce57d01e730a0ce2cc120b6c9d27585026c3de84d6b1a0dcaf5fea9d3
  • Pointer size: 131 Bytes
  • Size of remote file: 129 kB
assets/example_image/5a6c81d3b2afca4323e4b8b379e2cf06d18371a57fc8c5dc24b57e60e3216690.webp ADDED

Git LFS Details

  • SHA256: 47cbe7b6f29adb0f7d02c2cd73f6f8bd90a54b12d416368499458a8c571e35c5
  • Pointer size: 131 Bytes
  • Size of remote file: 178 kB
assets/example_image/5c80e5e03a3b60b6f03eaf555ba1dafc0e4230c472d7e8c8e2c5ca0a0dfcef10.webp ADDED

Git LFS Details

  • SHA256: fbd98cf5da79c56f8efc6cf86804391e71bdad2e935d21a7262472653a0674dc
  • Pointer size: 131 Bytes
  • Size of remote file: 127 kB
assets/example_image/61fea9d08e0bd9a067c9f696621dc89165afb5aab318d0701bc025d7863dabf0.webp ADDED

Git LFS Details

  • SHA256: dfad86b88eb81da36a5acf77891822c042e991436bb004c7d75d8b19e89c45bd
  • Pointer size: 131 Bytes
  • Size of remote file: 111 kB
assets/example_image/65433d02fc56dae164719ec29cb9646c0383aa1d0e24f0bb592899f08428d68e.webp ADDED

Git LFS Details

  • SHA256: fd73dcc5ae5b42a442c87f1522f370869f3d2e63922e6ecf769fd90fdeed1e66
  • Pointer size: 131 Bytes
  • Size of remote file: 125 kB
assets/example_image/6b6d89d46d7f53e6409dbe695a9ef8f97c5257e641da35015a78579e903acdad.webp ADDED
assets/example_image/74fe541e8c8eac8d0b5d8ba144307f6c07ed832cd19bf1d431c74292002028cd.webp ADDED
assets/example_image/799ab13a23fe319a6876b8bf48007d0374d514f5e7aa31210e9b2cecfbace082.webp ADDED

Git LFS Details

  • SHA256: d0dd605ac2927b56f6ba5ced2d0b56aaba1be9f7dc2ab7f8d558d0f37856f6b5
  • Pointer size: 131 Bytes
  • Size of remote file: 170 kB
assets/example_image/7b540da337f576ffce2adc36c7459b9bbbfd845ab2160a6abbe986f1f906f6cd.webp ADDED
assets/example_image/7baa867b4790b8596ee120f9b171b727fd9428c41980577a518505507c99d8a0.webp ADDED

Git LFS Details

  • SHA256: 41fd0f2a1cd66f4615a3947b6fdbddf527d4d628935a6fd208ca32a3b46849b1
  • Pointer size: 131 Bytes
  • Size of remote file: 112 kB
assets/example_image/7bd0521d20ee4805d1462a0ffb7d9aacc15180c2b741c9ac42a0d82ad3d340cb.webp ADDED

Git LFS Details

  • SHA256: b5a7835a908470c1142678cddfbfbe093ba0ec1085852ed072ae597f1eae5c37
  • Pointer size: 131 Bytes
  • Size of remote file: 112 kB
assets/example_image/7d585a8475db078593486367d98b5efa9368a60a3528c555b96026a1a674aa54.webp ADDED

Git LFS Details

  • SHA256: 7807391ef76523dab937bfcae5f9fc4803a65b86ab49310c17df0714288b7c48
  • Pointer size: 131 Bytes
  • Size of remote file: 195 kB
assets/example_image/7d6f4da4eafcc60243daf6ed210853df394a8bad7e701cadf551e21abcc77869.webp ADDED

Git LFS Details

  • SHA256: 3977e4b323080e122ec297f2fafe1203e717fef8417e82b6ed523e8438f829c6
  • Pointer size: 131 Bytes
  • Size of remote file: 192 kB
assets/example_image/7d7659d5943e85a73a4ffe33c6dd48f5d79601e9bf11b103516f419ce9fbf713.webp ADDED

Git LFS Details

  • SHA256: 6707893380d3c791a9a2d33bc0caa5f10719f7168d25f8d447fa26f4420919db
  • Pointer size: 131 Bytes
  • Size of remote file: 109 kB
assets/example_image/80ad7988fc2ce62fc655b21a8950865566ec3f5a8b4398f2502db6414a3e6834.webp ADDED

Git LFS Details

  • SHA256: 9558307682a1e723f86291af377f0b53970c0d301304c1f43dec741fedc209d7
  • Pointer size: 131 Bytes
  • Size of remote file: 118 kB