I need to stitch five video streams on the fly. The cameras recording the videos are mounted onto a rack side by side and will never change their relative position to one another. Homography matrices are therefore static.
I'm following the approach from this github repo:
Starting from the center image, you first stitch to the left, and then stitch the remaining images to the right.
The code from that repo works, but it is painfully slow. I've been able to dramatically improve its performance (factor 300), but it still takes 0.25 seconds to stitch a panorama of five images (on a 2015 Macbook Pro).
The slow part: Applying each result of cv2.warpPerspective(...)
to the images stitched up to that point. I'm currently doing this by using the alpha channel and blending the two images, inspired by this SO answer. It is this blending that makes the stitching slow.
(Pseudo) code:
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)
So my question is: Is there a way to apply the warped image to the existing panorama in a more efficient way?
My full working code is in this repository.
Disclaimer: I'm a web developer and my knowledge on computer vision is very limited.