singam96 commited on
Commit
28abe10
·
verified ·
1 Parent(s): f45f8bc

singam96/ShadeNet-5-35M: upload hf_draft

Browse files
README.md CHANGED
@@ -94,7 +94,7 @@ The six-pass average is better than a single pass but costs six forward passes.
94
  - **Against the labels:** see the Results table: normals recover about 94% of the six-pass gain, albedo about 60%, depth about 8%. The refiner does not reproduce the six-pass average's changes to the overall depth levels, so depth is essentially the single pass's.
95
  - **Cost:** about 12 ms per image on top of the single pass (PyTorch, A4000) and about 0.26 s on a CPU for the 448x448 ONNX version.
96
 
97
- Files: `refiner/refiner.pt` (PyTorch weights) and `onnx/shadenet5_refiner.onnx` (fp32, fixed 448x448). Run it after the main model: `python inference/run_onnx.py photos/ --refine`.
98
 
99
  On the shipped 4/8-bit MIX ONNX model (CPU, same 23 images, unit-length normals): single pass 0.1755, single pass + refiner **0.1676**, six passes 0.1645. The refiner was trained on full-precision outputs, so this is the number for the file you would download.
100
 
@@ -275,6 +275,16 @@ python inference/run_onnx.py photos/ --refine --out out/
275
 
276
  Each photo becomes a panel image: input, albedo, depth, normal. `--refine` runs the single pass and then the small refiner (about 12 ms more; the recommended mode, see The refiner). `--enhanced` is the six-pass post-processing described above in one switch (mirror average, rotations of ±4 degrees, unit-length normals; six forward passes); leave both flags out for the plain single pass. The whole photo is kept: its long side is scaled to 448 and the rest of the 448x448 input is filled by mirroring the photo's own edge, then the padding is cut off the maps again, so the outputs have the photo's own shape. A photo that is not square therefore uses fewer than 448 pixels on its short side. (The PyTorch model runs at 448 and 896 square; the ONNX files are fixed at 448x448.) `torch` is only used for the rotation resampling of `--enhanced`. Set `--threads` to the number of CPU cores you have: more threads than cores is slower, not faster. A hosted demo runs the same code: [ShadeNet-5 Space](https://huggingface.co/spaces/singam96/ShadeNet-5).
277
 
 
 
 
 
 
 
 
 
 
 
278
  The PyTorch checkpoint (`checkpoints/best-l1-pruned10-ep19.ckpt`) is the full-precision reference. Loading it needs the training code, which is not published yet (the `--enhanced` switch of its `infer.py` is the same recipe), so use the ONNX file unless you have that code.
279
 
280
  `config.json` in this repository lists the architecture, the input and output convention (7 maps in [-1, 1]: albedo, depth, normal), the supported sizes and the recommended inference settings.
 
94
  - **Against the labels:** see the Results table: normals recover about 94% of the six-pass gain, albedo about 60%, depth about 8%. The refiner does not reproduce the six-pass average's changes to the overall depth levels, so depth is essentially the single pass's.
95
  - **Cost:** about 12 ms per image on top of the single pass (PyTorch, A4000) and about 0.26 s on a CPU for the 448x448 ONNX version.
96
 
97
+ Files: `refiner/refiner.pt` (PyTorch weights), `onnx/shadenet5_refiner.onnx` (the refiner alone, fp32, fixed 448x448) and `onnx/shadenet5_mix_refined.onnx` (35 MB: the MIX model, the refiner, the clamp and the unit-length normals in **one file**, photo in and final maps out; its mean L1 is identical to running the two files one after the other). Run them with `python inference/run_onnx.py photos/ --refine` (two files) or `--merged` (the single file).
98
 
99
  On the shipped 4/8-bit MIX ONNX model (CPU, same 23 images, unit-length normals): single pass 0.1755, single pass + refiner **0.1676**, six passes 0.1645. The refiner was trained on full-precision outputs, so this is the number for the file you would download.
100
 
 
275
 
276
  Each photo becomes a panel image: input, albedo, depth, normal. `--refine` runs the single pass and then the small refiner (about 12 ms more; the recommended mode, see The refiner). `--enhanced` is the six-pass post-processing described above in one switch (mirror average, rotations of ±4 degrees, unit-length normals; six forward passes); leave both flags out for the plain single pass. The whole photo is kept: its long side is scaled to 448 and the rest of the 448x448 input is filled by mirroring the photo's own edge, then the padding is cut off the maps again, so the outputs have the photo's own shape. A photo that is not square therefore uses fewer than 448 pixels on its short side. (The PyTorch model runs at 448 and 896 square; the ONNX files are fixed at 448x448.) `torch` is only used for the rotation resampling of `--enhanced`. Set `--threads` to the number of CPU cores you have: more threads than cores is slower, not faster. A hosted demo runs the same code: [ShadeNet-5 Space](https://huggingface.co/spaces/singam96/ShadeNet-5).
277
 
278
+ Or call the single merged file directly:
279
+
280
+ ```python
281
+ import numpy as np, onnxruntime as ort
282
+ sess = ort.InferenceSession("shadenet5_mix_refined.onnx")
283
+ # photo: float32 [1, 3, 448, 448] in [-1, 1]
284
+ maps = sess.run(None, {"input_rgb": photo})[0] # [1, 7, 448, 448]
285
+ albedo, depth, normal = maps[:, 0:3], maps[:, 3:4], maps[:, 4:7]
286
+ ```
287
+
288
  The PyTorch checkpoint (`checkpoints/best-l1-pruned10-ep19.ckpt`) is the full-precision reference. Loading it needs the training code, which is not published yet (the `--enhanced` switch of its `infer.py` is the same recipe), so use the ONNX file unless you have that code.
289
 
290
  `config.json` in this repository lists the architecture, the input and output convention (7 maps in [-1, 1]: albedo, depth, normal), the supported sizes and the recommended inference settings.
config.json CHANGED
@@ -47,7 +47,8 @@
47
  "onnx": {
48
  "onnx/shadenet5_mix_int4_int8.onnx": "ViT fc1/fc2 int8, everything else int4",
49
  "onnx/shadenet5_mix2_int4_int8.onnx": "ViT fc2 int8, everything else int4",
50
- "onnx/shadenet5_refiner.onnx": "the small refiner, fp32, fixed 448x448 (inputs photo and maps, output refined maps)"
 
51
  },
52
  "recommended_inference": {
53
  "mode": "refine",
@@ -58,7 +59,9 @@
58
  "unit_normals": true,
59
  "forward_passes": 6,
60
  "command": "python inference/run_onnx.py <photos> --enhanced --out out/"
61
- }
 
 
62
  },
63
  "validation_mean_l1": {
64
  "single_pass_unit_normals": 0.1757,
@@ -66,7 +69,8 @@
66
  "six_passes": 0.1628,
67
  "mix_onnx_single": 0.1755,
68
  "mix_onnx_plus_refiner": 0.1676,
69
- "mix_onnx_six_passes": 0.1645
 
70
  },
71
  "refiner": {
72
  "pytorch": "refiner/refiner.pt",
 
47
  "onnx": {
48
  "onnx/shadenet5_mix_int4_int8.onnx": "ViT fc1/fc2 int8, everything else int4",
49
  "onnx/shadenet5_mix2_int4_int8.onnx": "ViT fc2 int8, everything else int4",
50
+ "onnx/shadenet5_refiner.onnx": "the small refiner, fp32, fixed 448x448 (inputs photo and maps, output refined maps)",
51
+ "onnx/shadenet5_mix_refined.onnx": "the MIX model + the refiner + clamp + unit-length normals in one file: input `input_rgb` [1,3,448,448] in [-1,1], output `refined` [1,7,448,448]"
52
  },
53
  "recommended_inference": {
54
  "mode": "refine",
 
59
  "unit_normals": true,
60
  "forward_passes": 6,
61
  "command": "python inference/run_onnx.py <photos> --enhanced --out out/"
62
+ },
63
+ "single_file": "onnx/shadenet5_mix_refined.onnx",
64
+ "single_file_command": "python inference/run_onnx.py <photos> --merged --out out/"
65
  },
66
  "validation_mean_l1": {
67
  "single_pass_unit_normals": 0.1757,
 
69
  "six_passes": 0.1628,
70
  "mix_onnx_single": 0.1755,
71
  "mix_onnx_plus_refiner": 0.1676,
72
+ "mix_onnx_six_passes": 0.1645,
73
+ "mix_onnx_single_merged_file": 0.1676
74
  },
75
  "refiner": {
76
  "pytorch": "refiner/refiner.pt",
inference/run_onnx.py CHANGED
@@ -27,6 +27,7 @@ from framing import crop_to_box, display_size, letterbox, resize_maps # noqa: E
27
  REPO = "singam96/ShadeNet-5-35M"
28
  ONNX_FILE = "onnx/shadenet5_mix_int4_int8.onnx"
29
  REFINER_FILE = "onnx/shadenet5_refiner.onnx"
 
30
  SIZE = 448 # the ONNX files are fixed at 448x448
31
  ROT_DEG = 4.0
32
 
@@ -50,6 +51,9 @@ def main():
50
  ap.add_argument("--onnx", default=None, help="local .onnx (default: download)")
51
  ap.add_argument("--size", type=int, default=SIZE, choices=[448],
52
  help="the ONNX files are fixed at 448x448")
 
 
 
53
  ap.add_argument("--refine", action="store_true",
54
  help="single pass, then the small refiner (recommended)")
55
  ap.add_argument("--refiner-onnx", default=None, help="local refiner .onnx (default: download)")
@@ -60,13 +64,13 @@ def main():
60
  ap.add_argument("--threads", type=int, default=8,
61
  help="ONNX Runtime threads (more than your cores is slower)")
62
  args = ap.parse_args()
63
- if args.refine and args.enhanced:
64
- ap.error('use --refine or --enhanced, not both')
65
 
66
  path = args.onnx
67
  if path is None:
68
  from huggingface_hub import hf_hub_download
69
- path = hf_hub_download(REPO, ONNX_FILE)
70
  so = ort.SessionOptions()
71
  so.intra_op_num_threads = args.threads
72
  sess = ort.InferenceSession(path, so, providers=["CPUExecutionProvider"])
@@ -94,7 +98,9 @@ def main():
94
  square, box = letterbox(img, args.size)
95
  x = to_tensor(square)
96
  with torch.no_grad():
97
- if args.refine:
 
 
98
  single = refine(x)
99
  out = ref_sess.run(None, {"photo": np.ascontiguousarray(x.numpy()),
100
  "maps": np.ascontiguousarray(single.numpy())})[0]
 
27
  REPO = "singam96/ShadeNet-5-35M"
28
  ONNX_FILE = "onnx/shadenet5_mix_int4_int8.onnx"
29
  REFINER_FILE = "onnx/shadenet5_refiner.onnx"
30
+ MERGED_FILE = "onnx/shadenet5_mix_refined.onnx"
31
  SIZE = 448 # the ONNX files are fixed at 448x448
32
  ROT_DEG = 4.0
33
 
 
51
  ap.add_argument("--onnx", default=None, help="local .onnx (default: download)")
52
  ap.add_argument("--size", type=int, default=SIZE, choices=[448],
53
  help="the ONNX files are fixed at 448x448")
54
+ ap.add_argument("--merged", action="store_true",
55
+ help="the single file with the MIX model, refiner and unit normals in one graph "
56
+ "(same result as --refine, one session)")
57
  ap.add_argument("--refine", action="store_true",
58
  help="single pass, then the small refiner (recommended)")
59
  ap.add_argument("--refiner-onnx", default=None, help="local refiner .onnx (default: download)")
 
64
  ap.add_argument("--threads", type=int, default=8,
65
  help="ONNX Runtime threads (more than your cores is slower)")
66
  args = ap.parse_args()
67
+ if sum([args.refine, args.enhanced, args.merged]) > 1:
68
+ ap.error('use one of --refine, --enhanced, --merged')
69
 
70
  path = args.onnx
71
  if path is None:
72
  from huggingface_hub import hf_hub_download
73
+ path = hf_hub_download(REPO, MERGED_FILE if args.merged else ONNX_FILE)
74
  so = ort.SessionOptions()
75
  so.intra_op_num_threads = args.threads
76
  sess = ort.InferenceSession(path, so, providers=["CPUExecutionProvider"])
 
98
  square, box = letterbox(img, args.size)
99
  x = to_tensor(square)
100
  with torch.no_grad():
101
+ if args.merged:
102
+ maps = refine(x) # already refined, clamped, unit-length normals
103
+ elif args.refine:
104
  single = refine(x)
105
  out = ref_sess.run(None, {"photo": np.ascontiguousarray(x.numpy()),
106
  "maps": np.ascontiguousarray(single.numpy())})[0]
onnx/shadenet5_mix_refined.onnx ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f273b36084478f6294f9acb7ec6bae50aacf973b4881e97aabdc35ed32ce2b3d
3
+ size 35061482
refiner/eval_onnx_mix_cpu.json CHANGED
@@ -1,23 +1,30 @@
1
  {
2
  "MIX single pass": {
3
- "albedo": 0.1782670166829358,
4
- "depth": 0.17611026375190073,
5
- "normal": 0.17200583511072656,
6
- "mean": 0.17546103851518768,
7
- "ms": 1041.167746890675
8
  },
9
  "MIX + refiner": {
10
- "albedo": 0.17474121535601822,
11
- "depth": 0.17591332482255023,
12
- "normal": 0.15225264818772025,
13
- "mean": 0.1676357294554296,
14
- "ms": 1300.2352497794413
15
  },
16
  "MIX six passes": {
17
- "albedo": 0.1728826994481294,
18
- "depth": 0.17006371332251508,
19
- "normal": 0.1506343720399815,
20
- "mean": 0.16452692827020868,
21
- "ms": 6070.682460611517
 
 
 
 
 
 
 
22
  }
23
  }
 
1
  {
2
  "MIX single pass": {
3
+ "albedo": 0.1782614407332047,
4
+ "depth": 0.17611568907032843,
5
+ "normal": 0.1720099980416505,
6
+ "mean": 0.17546237594839462,
7
+ "ms": 1329.7054225748234
8
  },
9
  "MIX + refiner": {
10
+ "albedo": 0.17473657526399777,
11
+ "depth": 0.1759216370789901,
12
+ "normal": 0.15225956880527994,
13
+ "mean": 0.16763926038275595,
14
+ "ms": 1649.118575182828
15
  },
16
  "MIX six passes": {
17
+ "albedo": 0.17288330618454062,
18
+ "depth": 0.1700636342815731,
19
+ "normal": 0.15063375072634738,
20
+ "mean": 0.1645268970641537,
21
+ "ms": 8918.771418658169
22
+ },
23
+ "one merged file": {
24
+ "albedo": 0.17473587231791537,
25
+ "depth": 0.175918893645639,
26
+ "normal": 0.15225798798644025,
27
+ "mean": 0.16763758464999826,
28
+ "ms": 1721.9356731934981
29
  }
30
  }