python - Python OpenCV实时图像拼接(n=5)性能优化
问题描述
我需要即时拼接五个视频流。录制视频的摄像机并排安装在机架上,彼此之间的相对位置永远不会改变。因此,单应矩阵是静态的。
我正在遵循这个 github repo的方法:
从中心图像开始,您首先缝合到左侧,然后将剩余的图像缝合到右侧。
该仓库中的代码有效,但速度非常慢。我已经能够显着提高它的性能(300 倍),但仍然需要 0.25 秒来拼接一张包含五张图像的全景图(在 2015 年的 Macbook Pro 上)。
缓慢的部分:将每个结果cv2.warpPerspective(...)
应用于拼接到该点的图像。我目前正在通过使用 alpha 通道并混合两个图像来做到这一点,灵感来自这个 SO answer。正是这种混合使缝合变慢。
(伪)代码:
def blend_transparent(background, foreground):
overlay_img = foreground[:, :, :3] # Grab the BRG planes
overlay_mask = foreground[:, :, 3:] # And the alpha plane
# Again calculate the inverse mask
background_mask = 255 - overlay_mask
# Turn the masks into three channel, so we can use them as weights
overlay_mask = cv2.cvtColor(overlay_mask, cv2.COLOR_GRAY2BGR)
background_mask = cv2.cvtColor(background_mask, cv2.COLOR_GRAY2BGR)
# Create a masked out background image, and masked out overlay
# We convert the images to floating point in range 0.0 - 1.0
background_part = (background * (1 / 255.0)) * (background_mask * (1 / 255.0))
overlay_part = (overlay_img * (1 / 255.0)) * (overlay_mask * (1 / 255.0))
# And finally just add them together, and rescale it back to an 8bit integer image
return np.uint8(
cv2.addWeighted(background_part, 255.0, overlay_part, 255.0, 0.0)
)
for image in right_images:
warped_image = cv2.warpPerspective(image, ...)
mask = np.zeros(
(warped_image.shape[0], warped_image.shape[1], 4),
dtype="uint8"
)
mask[0 : previously_stitched.shape[0], 0 : previously_stitched.shape[1]] = previously_stitched
mask_rgb = mask[:, :, :3] # Grab the BRG planes
previously_stitched = blend_transparent(mask_rgb, warped_image)
所以我的问题是:有没有办法以更有效的方式将扭曲的图像应用于现有的全景图?
我的完整工作代码在这个存储库中。
免责声明:我是一名网络开发人员,我对计算机视觉的了解非常有限。
解决方案
当您的图像具有透明度时,Alpha 通道很有用,但在这里您可以通过转换手动添加 Alpha 通道。该通道可用于存储计算,但我认为您会失去性能。我建议为 blend_transparent 使用以下函数:
def blend_transparent(self, background, foreground):
# Split out the transparency mask from the colour info
overlay_img = foreground[:, :, :3] # Grab the BRG planes
res = background
only_right = np.nonzero((np.sum(overlay_img, 2) != 0) * (np.sum(background,2) == 0))
left_and_right = np.nonzero((np.sum(overlay_img, 2) != 0) * (np.sum(background,2) != 0))
res[only_right] = overlay_img[only_right]
res[left_and_right] = res[left_and_right]*0.5 + overlay_img[left_and_right]*0.5
return res
如果当前未设置任何值,则在此处设置结果中右图像像素的值。如果已经设置了一个值,则计算左右值的平均值。计算时间除以 1.6 倍。
由于您的投影已冻结,因此不需要每次都计算索引 only_right 和 left_and_right,我们可以计算一次并存储它们。这样做,您应该将计算时间除以 4。
推荐阅读
- unity3d - 丢失场景文件
- docker - 从 Dockerfile 构建映像时无法连接 debian prod
- haskell - Haskell 自己的递归 concat 方法
- python - 网站克隆脚本忽略没有文件扩展名的链接,例如 about-us/
- java - 如何在 PKCE 中使用 Keycloak
- php - 使用 MySQL 连接的 laravel 关系
- filepond - 为什么使用filepond组件无法两次上传文件?
- php - Laravel 中间件创建重定向循环
- java - Java 8 Stream API:如何使用 GroupingBy 在多个组中拥有相同的对象?
- java - 为代码中的特定行设置不同的等待时间