python - PoseWarping:如何矢量化这个 for 循环(z 缓冲区)
问题描述
我正在尝试使用地面实况深度图、姿势信息和相机矩阵将帧从 view1 扭曲到 view2。我已经能够删除大部分 for 循环并将其矢量化,除了一个 for 循环。变形时,由于遮挡,view1 中的多个像素可能会映射到 view2 中的单个位置。在这种情况下,我需要选择深度值最低的像素(前景对象)。我无法对这部分代码进行矢量化。感谢任何帮助向量化这个 for 循环。
语境:
考虑到地面真实姿势、深度和相机矩阵,我正在尝试将图像变形为新视图。在计算了扭曲的位置之后,我将它们四舍五入。也欢迎任何实现逆双线性插值的建议。我的图像是全高清分辨率。因此,将帧扭曲到新视图需要花费大量时间。如果我可以矢量化,我打算将代码转换为 TensorFlow 或 PyTorch 并在 GPU 上运行。也欢迎任何其他加快变形的建议或现有实现。代码:
def warp_frame_04(frame1: numpy.ndarray, depth: numpy.ndarray, intrinsic: numpy.ndarray, transformation1: numpy.ndarray,
transformation2: numpy.ndarray, convert_to_uint: bool = True, verbose_log: bool = True):
"""
Vectorized Forward warping. Nearest Neighbor.
Offset requirement of warp_frame_03() overcome.
mask: 1 if pixel found, 0 if no pixel found
Drawback: Nearest neighbor, collision resolving not vectorized
"""
height, width, _ = frame1.shape
assert depth.shape == (height, width)
transformation = numpy.matmul(transformation2, numpy.linalg.inv(transformation1))
y1d = numpy.array(range(height))
x1d = numpy.array(range(width))
x2d, y2d = numpy.meshgrid(x1d, y1d)
ones_2d = numpy.ones(shape=(height, width))
ones_4d = ones_2d[:, :, None, None]
pos_vectors_homo = numpy.stack([x2d, y2d, ones_2d], axis=2)[:, :, :, None]
intrinsic_inv = numpy.linalg.inv(intrinsic)
intrinsic_4d = intrinsic[None, None]
intrinsic_inv_4d = intrinsic_inv[None, None]
depth_4d = depth[:, :, None, None]
trans_4d = transformation[None, None]
unnormalized_pos = numpy.matmul(intrinsic_inv_4d, pos_vectors_homo)
world_points = depth_4d * unnormalized_pos
world_points_homo = numpy.concatenate([world_points, ones_4d], axis=2)
trans_world_homo = numpy.matmul(trans_4d, world_points_homo)
trans_world = trans_world_homo[:, :, :3]
trans_norm_points = numpy.matmul(intrinsic_4d, trans_world)
trans_pos = trans_norm_points[:, :, :2, 0] / trans_norm_points[:, :, 2:3, 0]
trans_pos_int = numpy.round(trans_pos).astype('int')
# Solve occlusions
a = trans_pos_int.reshape(-1, 2)
d = depth.ravel()
b = numpy.unique(a, axis=0, return_index=True, return_counts=True)
collision_indices = b[1][b[2] >= 2] # Unique indices which are involved in collision
for c1 in tqdm(collision_indices, disable=not verbose_log):
cl = a[c1].copy() # Collision Location
ci = numpy.where((a[:, 0] == cl[0]) & (a[:, 1] == cl[1]))[0] # Colliding Indices: Indices colliding for cl
cci = ci[numpy.argmin(d[ci])] # Closest Collision Index: Index of the nearest point among ci
a[ci] = [-1, -1]
a[cci] = cl
trans_pos_solved = a.reshape(height, width, 2)
# Offset both axes by 1 and set any out of frame motion to edge. Then crop 1-pixel thick edge
trans_pos_offset = trans_pos_solved + 1
trans_pos_offset[:, :, 0] = numpy.clip(trans_pos_offset[:, :, 0], a_min=0, a_max=width + 1)
trans_pos_offset[:, :, 1] = numpy.clip(trans_pos_offset[:, :, 1], a_min=0, a_max=height + 1)
warped_image = numpy.ones(shape=(height + 2, width + 2, 3)) * numpy.nan
warped_image[trans_pos_offset[:, :, 1], trans_pos_offset[:, :, 0]] = frame1
cropped_warped_image = warped_image[1:-1, 1:-1]
mask = numpy.isfinite(cropped_warped_image)
cropped_warped_image[~mask] = 0
if convert_to_uint:
final_warped_image = cropped_warped_image.astype('uint8')
else:
final_warped_image = cropped_warped_image
mask = mask[:, :, 0]
return final_warped_image, mask
代码说明
- 我正在使用方程式 [1,2] 来获取 view2 中的像素位置
- 一旦我有了像素位置,我需要确定是否有任何遮挡,如果有,我必须选择前景像素。
- `b = numpy.unique(a, axis=0, return_index=True, return_counts=True)` 给了我独特的位置。
- 如果 view1 中的多个像素映射到 view2 中的单个像素(碰撞),`return_counts` 将给出大于 1 的值。
- `collision_indices = b[1][b[2] >= 2]` 给出了涉及碰撞的索引。请注意,每次碰撞仅给出一个索引。
- 对于每个这样的碰撞点,`ci = numpy.where((a[:, 0] == cl[0]) & (a[:, 1] == cl[1]))[0]` 提供索引来自 view1 的所有像素映射到 view2 中的同一点。
- `cci = ci[numpy.argmin(d[ci])]` 给出深度值最低的像素索引。
- `a[ci] = [-1, -1]` 和 `a[cci] = cl` 将所有其他背景像素映射到超出帧的位置 (-1,-1),因此将被忽略。
[1] https://i.stack.imgur.com/s1D9t.png
[2] https://dsp.stackexchange.com/q/69890/32876
解决方案
推荐阅读
- android - 在 Android Studio 中运行 Flutter App 时出现错误:任务 ':app:generateDebugBuildConfig' 执行失败
- javascript - 如何从 firefox 插件访问 firebase firestore?
- javascript - platform.js 还是 api.js?谷歌API
- c# - 存储动作规则
- python - 如何在熊猫中使用带移位功能的最小值/最大值?
- python - 在列表列表中查找共同元素
- javascript - 在向下滚动时显示组件中的某个元素并在向上滚动时隐藏 Reactjs
- django - 在 django 的“for”循环中使用“if”调用函数不起作用
- pine-script - tradingview pine 中的不规则交易执行顺序
- javascript - html 元素正在选择超出其范围的点击事件