Align `depth_src` to `depth_tgt` with given constant weights. ### Parameters: - `depth_src: torch.Tensor` of shape (..., N) - `depth_tgt: torch.Tensor` of shape (..., N) - `weight: torch.Tensor` of shape (..., N) - `trunc: float` or tensor of shape (..., N) or None ###
(depth_src: torch.Tensor, depth_tgt: torch.Tensor, weight: Optional[torch.Tensor], trunc: Optional[Union[float, torch.Tensor]] = None)
| 161 | |
| 162 | |
| 163 | def align_depth_affine(depth_src: torch.Tensor, depth_tgt: torch.Tensor, weight: Optional[torch.Tensor], trunc: Optional[Union[float, torch.Tensor]] = None): |
| 164 | """ |
| 165 | Align `depth_src` to `depth_tgt` with given constant weights. |
| 166 | |
| 167 | ### Parameters: |
| 168 | - `depth_src: torch.Tensor` of shape (..., N) |
| 169 | - `depth_tgt: torch.Tensor` of shape (..., N) |
| 170 | - `weight: torch.Tensor` of shape (..., N) |
| 171 | - `trunc: float` or tensor of shape (..., N) or None |
| 172 | |
| 173 | ### Returns: |
| 174 | - `scale: torch.Tensor` of shape (...). |
| 175 | - `shift: torch.Tensor` of shape (...). |
| 176 | """ |
| 177 | dtype, device = depth_src.dtype, depth_src.device |
| 178 | |
| 179 | # Flatten batch dimensions for simplicity |
| 180 | batch_shape, n = depth_src.shape[:-1], depth_src.shape[-1] |
| 181 | batch_size = math.prod(batch_shape) |
| 182 | depth_src, depth_tgt, weight = depth_src.reshape(batch_size, n), depth_tgt.reshape(batch_size, n), weight.reshape(batch_size, n) |
| 183 | |
| 184 | # Here, we take anchors only for non-zero weights. |
| 185 | # Although the results will be still correct even anchor points have zero weight, |
| 186 | # it is wasting computation and may cause instability in some cases, e.g. too many extrema. |
| 187 | anchors_where_batch, anchors_where_n = torch.where(weight > 0) |
| 188 | |
| 189 | # Stop gradient when solving optimal anchors |
| 190 | with torch.no_grad(): |
| 191 | depth_src_anchor = depth_src[anchors_where_batch, anchors_where_n] # (anchors) |
| 192 | depth_tgt_anchor = depth_tgt[anchors_where_batch, anchors_where_n] # (anchors) |
| 193 | |
| 194 | depth_src_anchored = depth_src[anchors_where_batch, :] - depth_src_anchor[..., None] # (anchors, n) |
| 195 | depth_tgt_anchored = depth_tgt[anchors_where_batch, :] - depth_tgt_anchor[..., None] # (anchors, n) |
| 196 | weight_anchored = weight[anchors_where_batch, :] # (anchors, n) |
| 197 | |
| 198 | scale, loss, index = align(depth_src_anchored, depth_tgt_anchored, weight_anchored, trunc) # (anchors) |
| 199 | |
| 200 | loss, index_anchor = scatter_min(size=batch_size, dim=0, index=anchors_where_batch, src=loss) # (batch_size,) |
| 201 | |
| 202 | # Reproduce by indexing for shorter compute graph |
| 203 | index_1 = anchors_where_n[index_anchor] # (batch_size,) |
| 204 | index_2 = index[index_anchor] # (batch_size,) |
| 205 | |
| 206 | tgt_1, src_1 = torch.gather(depth_tgt, dim=1, index=index_1[..., None]).squeeze(-1), torch.gather(depth_src, dim=1, index=index_1[..., None]).squeeze(-1) |
| 207 | tgt_2, src_2 = torch.gather(depth_tgt, dim=1, index=index_2[..., None]).squeeze(-1), torch.gather(depth_src, dim=1, index=index_2[..., None]).squeeze(-1) |
| 208 | |
| 209 | scale = (tgt_2 - tgt_1) / torch.where(src_2 != src_1, src_2 - src_1, 1e-7) |
| 210 | shift = tgt_1 - scale * src_1 |
| 211 | |
| 212 | scale, shift = scale.reshape(batch_shape), shift.reshape(batch_shape) |
| 213 | |
| 214 | return scale, shift |
| 215 | |
| 216 | def align_depth_affine_irls(depth_src: torch.Tensor, depth_tgt: torch.Tensor, weight: Optional[torch.Tensor], max_iter: int = 100, eps: float = 1e-12): |
| 217 | """ |
nothing calls this directly
no test coverage detected