图像处理:如何在目的地使用简单的蒙版进行变形?

Image Processing: how to imwarp with simple mask on destination?

关注,这次只在Python-

我正在寻找一种方法来将纹理映射到目标图像中的一个小区域,该区域由 4 个角定义为 (x, y) 像素坐标。该区域不一定是矩形的。它是一些矩形在图像平面上的透视投影。

我想将一些(矩形)纹理映射到由这些角定义的蒙版中。


直接通过 forward-mapping 纹理 will not work properly 映射,因为源像素将映射到目标中的 non-integer 个位置。

这个问题一般是inverse-warping从目的到源,然后根据某种插值着色

Opencv 的 warpPerspective 在这里不起作用,因为它不能带掩码。

Inverse-warping 整个目的地然后掩码是不可接受的,因为大部分计算都是多余的。


  1. 是否有 built-in opencv(或其他)函数可以满足上述要求?
  2. 如果不是,有什么好方法可以从由角定义的 ROI 中获取像素列表,以便将其传递给 projectPoints

示例背景图片:

我想用其他纹理填充红线勾勒出的区域(由其角定义),比如这个

它们之间的映射可以通过使用 cv2.getPerspectiveTransform

将纹理的角点映射到 ROI 角点来获得

对于后代,这里是如何仅在扭曲角点的 bbox 内前后扭曲像素,正如@Micka 所建议的那样。

这里banner是草图,banner_coords_2dimage上红色区域的角,就是表情包

def transform_banner(banner_coords_2d, banner, image):
    # show_points_on_image("banner corners", image, banner_coords_2d)

    banner_height, banner_width, _ = banner.shape
    src_banner_points = np.float32([
        [0, 0],
        [banner_width - 1, 0],
        [0, banner_height - 1],
        [banner_width - 1, banner_height - 1],
    ])

    # only warp to size of bbox of warped corners, not all of the image
    warped_left = np.round(np.min(banner_coords_2d[:, 0])).astype(int)
    warped_right = np.round(np.max(banner_coords_2d[:, 0])).astype(int)
    warped_top = np.round(np.min(banner_coords_2d[:, 1])).astype(int)
    warped_bottom = np.round(np.max(banner_coords_2d[:, 1])).astype(int)
    warped_width = int(warped_right - warped_left)
    warped_height = int(warped_bottom - warped_top)

    dst_banner_points = banner_coords_2d.astype(np.float32)
    dst_banner_points[:, 0] -= warped_left
    dst_banner_points[:, 1] -= warped_top

    tform = cv2.getPerspectiveTransform(src_banner_points, dst_banner_points)

    warped_banner = cv2.warpPerspective(banner, tform, (warped_width, warped_height))
    # cv2.imshow("warped_banner", warped_banner)
    image_with_banner = image.copy()
    image_with_banner[warped_top: warped_bottom, warped_left: warped_right][warped_banner != 0] = warped_banner[
        warped_banner != 0]
    # cv2.imshow("image_with_banner", image_with_banner)

    return image_with_banner

可能,这可以做得更整洁,我愿意编辑。