我有一些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]
。调试图如下所示:
很明显,我在这里遗漏了一些东西,也许只是不理解warp
和warpPoint
函数应该如何工作。怎么回事?
1条答案
按热度按时间vmpqdwk31#
我假设warper.warp()返回的第一个值与问题直接相关。因此,我只是通过减去返回的数量来校正warp_point坐标:warp_pt_corrected=np.array(warp_pt)-np.array(corrected)。在应用校正后,投影看起来不错。
让我再举另一个例子来更好地说明修正是适当的: