我有一些 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
函数应该如何工作。给出了什么?
最佳答案
我假设 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()
关于python - 为什么 PyRotationWarper.warp 和 PyRotationWarper.warpPoint 似乎应用不同的变换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75908039/