Spaces:
Running on Zero
Running on Zero
Make transpose_to_landscape picklable for ZeroGPU (closures -> __call__ classes)
Browse files- dust3r/dust3r/utils/misc.py +28 -17
dust3r/dust3r/utils/misc.py
CHANGED
|
@@ -51,19 +51,24 @@ def interleave(tensor1, tensor2):
|
|
| 51 |
return res1, res2
|
| 52 |
|
| 53 |
|
| 54 |
-
|
| 55 |
-
"""
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
assert true_shape[0:1].allclose(true_shape), 'true_shape must be all identical'
|
| 62 |
H, W = true_shape[0].cpu().tolist()
|
| 63 |
-
|
| 64 |
-
|
| 65 |
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
B = len(true_shape)
|
| 68 |
# by definition, the batch is in landscape mode so W >= H
|
| 69 |
H, W = int(true_shape.min()), int(true_shape.max())
|
|
@@ -72,16 +77,15 @@ def transpose_to_landscape(head, activate=True):
|
|
| 72 |
is_landscape = (width >= height)
|
| 73 |
is_portrait = ~is_landscape
|
| 74 |
|
| 75 |
-
# true_shape = true_shape.cpu()
|
| 76 |
if is_landscape.all():
|
| 77 |
-
return head(decout, (H, W))
|
| 78 |
if is_portrait.all():
|
| 79 |
-
return transposed(head(decout, (W, H)))
|
| 80 |
|
| 81 |
-
# batch is a mix of both
|
| 82 |
def selout(ar): return [d[ar] for d in decout]
|
| 83 |
-
l_result = head(selout(is_landscape), (H, W))
|
| 84 |
-
p_result = transposed(head(selout(is_portrait), (W, H)))
|
| 85 |
|
| 86 |
# allocate full result
|
| 87 |
result = {}
|
|
@@ -93,7 +97,14 @@ def transpose_to_landscape(head, activate=True):
|
|
| 93 |
|
| 94 |
return result
|
| 95 |
|
| 96 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 97 |
|
| 98 |
|
| 99 |
def transposed(dic):
|
|
|
|
| 51 |
return res1, res2
|
| 52 |
|
| 53 |
|
| 54 |
+
class _TransposeToLandscapeNo:
|
| 55 |
+
"""Picklable replacement for the `wrapper_no` closure — needed so the
|
| 56 |
+
model can be pickled across processes (e.g. ZeroGPU's worker fork)."""
|
| 57 |
+
def __init__(self, head):
|
| 58 |
+
self.head = head
|
| 59 |
+
|
| 60 |
+
def __call__(self, decout, true_shape):
|
| 61 |
assert true_shape[0:1].allclose(true_shape), 'true_shape must be all identical'
|
| 62 |
H, W = true_shape[0].cpu().tolist()
|
| 63 |
+
return self.head(decout, (H, W))
|
| 64 |
+
|
| 65 |
|
| 66 |
+
class _TransposeToLandscapeYes:
|
| 67 |
+
"""Picklable replacement for the `wrapper_yes` closure."""
|
| 68 |
+
def __init__(self, head):
|
| 69 |
+
self.head = head
|
| 70 |
+
|
| 71 |
+
def __call__(self, decout, true_shape):
|
| 72 |
B = len(true_shape)
|
| 73 |
# by definition, the batch is in landscape mode so W >= H
|
| 74 |
H, W = int(true_shape.min()), int(true_shape.max())
|
|
|
|
| 77 |
is_landscape = (width >= height)
|
| 78 |
is_portrait = ~is_landscape
|
| 79 |
|
|
|
|
| 80 |
if is_landscape.all():
|
| 81 |
+
return self.head(decout, (H, W))
|
| 82 |
if is_portrait.all():
|
| 83 |
+
return transposed(self.head(decout, (W, H)))
|
| 84 |
|
| 85 |
+
# batch is a mix of both portrait & landscape
|
| 86 |
def selout(ar): return [d[ar] for d in decout]
|
| 87 |
+
l_result = self.head(selout(is_landscape), (H, W))
|
| 88 |
+
p_result = transposed(self.head(selout(is_portrait), (W, H)))
|
| 89 |
|
| 90 |
# allocate full result
|
| 91 |
result = {}
|
|
|
|
| 97 |
|
| 98 |
return result
|
| 99 |
|
| 100 |
+
|
| 101 |
+
def transpose_to_landscape(head, activate=True):
|
| 102 |
+
"""Predict in the correct aspect-ratio, then transpose the result in
|
| 103 |
+
landscape and stack everything back together.
|
| 104 |
+
Returns a picklable callable (important for ZeroGPU, which sends the model
|
| 105 |
+
across a multiprocessing boundary and can't pickle local-function closures).
|
| 106 |
+
"""
|
| 107 |
+
return _TransposeToLandscapeYes(head) if activate else _TransposeToLandscapeNo(head)
|
| 108 |
|
| 109 |
|
| 110 |
def transposed(dic):
|