python - 为什么 PyRotationWarper.warp 和 PyRotationWarper.warpPoint 似乎应用不同的变换?

标签 python opencv

我有一些 K 和 R 矩阵,我想应用于图像和该图像中某处的点,以便该点被投影到输出图像中的匹配位置。我正在使用现有图像拼接管道的一部分,该管道严重依赖于 cv2.PyRotationWarper 类。一个工作示例如下所示:

import cv2
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
from pathlib import Path
import numpy as np
from skimage import data


img = data.cells3d()[34]
img = (255.0 * img / 2**16).astype(np.uint8)[0]
img = cv2.resize(img, (300, 200))
point = [200, 100]
K = np.array(
    [[863.5509, 0.0, 446.5], [0.0, 863.5509, 336.0], [0.0, 0.0, 1.0]], dtype=np.float32
)

R = np.array(
    [
        [0.02657406, 0.99131364, -0.12880631],
        [-0.9981135, 0.01917798, -0.05832428],
        [-0.05534741, 0.13011324, 0.9899532],
    ],
    dtype=np.float32,
)

scale = 890.0
aspect = 1.0

warper = cv2.PyRotationWarper("spherical", scale * aspect)

# warp the image
_, warped_image = warper.warp(
    img,
    K,
    R,
    cv2.INTER_LINEAR,
    cv2.BORDER_REFLECT,
)

# warp the input point
warped_pt = warper.warpPoint(
    point,
    K,
    R,
)

w, h = img.shape[:2][::-1]

# check the maps to see where the transformed pixels came from
_, xmap, ymap = warper.buildMaps(
    (w, h),
    K,
    R,
)

# plot the example
fig, axes = plt.subplots(2, 2, figsize=(10, 8))

axes[0, 0].imshow(img, cmap='gray')
imx = axes[0, 1].imshow(xmap)
imy = axes[1, 0].imshow(ymap)
axes[1, 1].imshow(warped_image, cmap='gray')

axes[0, 0].add_patch(Circle(point, 3, color='red',))
axes[1, 1].add_patch(Circle(warped_pt, 3, color='red'))

axes[0, 0].set(title=f"original image; point: {point}")
axes[0, 1].set(title="xmap")
axes[1, 0].set(title="ymap")
axes[1, 1].set(title=f"warped image: point: [{warped_pt[0]:.2f}, {warped_pt[1]:.2f}]")
cbx = plt.colorbar(imx, ax=axes[0, 1], orientation="vertical")
cby = plt.colorbar(imy, ax=axes[1, 0], orientation="vertical")

plt.tight_layout()

但该点被投影到一个疯狂的位置 [-353.75, 1582.54] 而不是我期望的位置:大约 [100, 100]。调试图如下所示: debug_image

很明显,我在这里遗漏了一些东西,也许只是不理解 warpwarpPoint 函数应该如何工作。给出了什么?

最佳答案

我假设 warper.warp() 返回的第一个值与该问题直接相关。因此,我只是通过减去返回的数量来校正 warped_point 坐标:warped_pt_ Corrected=np.array(warped_pt)-np.array( Correction)。应用校正后,投影看起来不错。

import cv2
import matplotlib.pyplot as plt
from matplotlib.patches import Circle
from pathlib import Path
import numpy as np
from skimage import data


img = data.cells3d()[34]
img = (255.0 * img / 2**16).astype(np.uint8)[0]
img = cv2.resize(img, (300, 200))
point = [200, 100]
K = np.array(
    [[863.5509, 0.0, 446.5], [0.0, 863.5509, 336.0], [0.0, 0.0, 1.0]], dtype=np.float32
)

R = np.array(
    [
        [0.02657406, 0.99131364, -0.12880631],
        [-0.9981135, 0.01917798, -0.05832428],
        [-0.05534741, 0.13011324, 0.9899532],
    ],
    dtype=np.float32,
)

scale = 890.0
aspect = 1.0

warper = cv2.PyRotationWarper("spherical", scale * aspect)

# warp the image
correction, warped_image = warper.warp(
    img,
    K,
    R,
    cv2.INTER_LINEAR,
    cv2.BORDER_REFLECT,
)

# warp the input point
warped_pt = warper.warpPoint(
    point,
    K,
    R,
)

w, h = img.shape[:2][::-1]

# check the maps to see where the transformed pixels came from
_, xmap, ymap = warper.buildMaps(
    (w, h),
    K,
    R,
)

# plot the example
fig, axes = plt.subplots(2, 2, figsize=(10, 8))

axes[0, 0].imshow(img, cmap='gray')
imx = axes[0, 1].imshow(xmap)
imy = axes[1, 0].imshow(ymap)
axes[1, 1].imshow(warped_image, cmap='gray')


warped_pt_corrected=np.array(warped_pt)-np.array(correction)

axes[0, 0].add_patch(Circle(point, 3, color='red',))
axes[1, 1].add_patch(Circle(warped_pt_corrected, 3, color='red'))

axes[0, 0].set(title=f"original image; point: {point}")
axes[0, 1].set(title="xmap")
axes[1, 0].set(title="ymap")
axes[1, 1].set(title=f"warped image: point: [{warped_pt_corrected[0]:.2f}, {warped_pt_corrected[1]:.2f}]")
cbx = plt.colorbar(imx, ax=axes[0, 1], orientation="vertical")
cby = plt.colorbar(imy, ax=axes[1, 0], orientation="vertical")

plt.tight_layout()

The image is the output of the code

让我再用另一个例子来更好地看出更正是否合适: Additional example

关于python - 为什么 PyRotationWarper.warp 和 PyRotationWarper.warpPoint 似乎应用不同的变换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75908039/

相关文章:

python - 如何过滤掉数据框中值以某个单词开头的行

image-processing - 'cvFindContours' 未在此范围内声明,opencv 2.4.2,编译错误

c++ - aam-opencv 编译因 OpenCVConfig.cmake 失败

opencv - 读取像素值方法?

python - 将值传递到进度条(twitter bootstrap,Flask)

Python 3 使用 Matplotlib 添加颜色条

python - 在python中如何以一定的概率随机替换数组的特定元素?

python - 在 python 中的索引中右移 for 循环

opencv - 如何使用相机在 3D 空间中定位对象

python - GStreamer-关键 ** : gst_element_make_from_uri: assertion 'gst_uri_is_valid (uri)' failed