正如標題所說,我想使用來自 kornia 的 HomographyWarper,以便它提供與 OpenCV warpPerspective 相同的輸出。
import cv2
import numpy as np
import torch
from kornia.geometry.transform import HomographyWarper
from kornia.geometry.conversions import normalize_pixel_coordinates
image_cv = cv2.imread("./COCO_train2014_000000000009.jpg")
image_cv = image_cv[0:256, 0:256]
image = torch.tensor(image_cv).permute(2, 0, 1)
image = image.to('cuda:0')
image_reshaped = image.type(torch.float32).view(1, *image.shape)
height, width, _ = image_cv.shape
homography_0_1 = torch.tensor([[ 7.8783e-01, 3.6705e-02, 2.5139e 02],
[ 1.6186e-02, 1.0893e 00, -2.7614e 01],
[-4.3304e-04, 7.6681e-04, 1.0000e 00]], device='cuda:0',
dtype=torch.float64)
homography_0_2 = torch.tensor([[ 7.8938e-01, 3.5727e-02, 1.5221e 02],
[ 1.8347e-02, 1.0921e 00, -2.8547e 01],
[-4.3172e-04, 7.7596e-04, 1.0000e 00]], device='cuda:0',
dtype=torch.float64)
transform_h1_h2 = torch.linalg.inv(homography_0_1).matmul(
homography_0_2).type(torch.float32).view(1, 3, 3)
homography_warper_1_2 = HomographyWarper(height, width, padding_mode='zeros', normalized_coordinates=True)
warped_image_torch = homography_warper_1_2(image_reshaped, transform_h1_h2)
warped_image_1_2_cv = cv2.warpPerspective(
image_cv,
transform_h1_h2.cpu().numpy().squeeze(),
dsize=(width, height),
borderMode=cv2.BORDER_REFLECT101,
)
cv2.namedWindow("original image")
cv2.imshow("original image", image_cv)
cv2.imshow("OpenCV warp", warped_image_1_2_cv)
cv2.imshow("Korni warp", warped_image_torch.squeeze().permute(1, 2, 0).cpu().numpy())
cv2.waitKey(0)
cv2.destroyAllWindows()
使用上面的代碼,我得到以下輸出:

使用normalized_coordinates=False,我得到以下輸出:

顯然,單應變換的應用方式不同。我很想知道其中的區別。
uj5u.com熱心網友回復:
您需要進行兩項更改:
- 使用相同的填充模式。
在您的示例中,cv2 使用cv2.BORDER_REFLECT101但 korniazeros
所以在呼叫 kornia 時更改zeros為。padding_mode='reflection'
- 您需要指定
normalized_homography=False.
所以修改后的版本:
from kornia.geometry.transform.imgwarp import homography_warp
warped_image_torch = homography_warp(image_reshaped, transform_h1_h2, dsize=(height, width), padding_mode="reflection", normalized_homography=False)
或者簡單地說:
from kornia.geometry.transform.imgwarp import warp_perspective
warped_image_torch = warp_perspective(image_reshaped, transform_h1_h2, dsize=(height, width), padding_mode="reflection")
結果(cv2/kornia):

HomographyWarper 內部呼叫homography_warp函式https://github.com/kornia/kornia/blob/f696d2fb7313474bbaf5e73d8b5a56077248b508/kornia/geometry/transform/homography_warper.py#L96但 HomographyWarper 不提供normalized_homography引數并且提供homography_warp。
完整示例:
import cv2
import numpy as np
import torch
from kornia.geometry.transform.imgwarp import warp_perspective, homography_warp
image_cv = cv2.imread("./000000000009.jpg")
image_cv = image_cv[0:256, 0:256]
image = torch.tensor(image_cv).permute(2, 0, 1)
image = image.to("cuda:0")
image_reshaped = image.type(torch.float32).view(1, *image.shape)
height, width, _ = image_cv.shape
homography_0_1 = torch.tensor(
[
[7.8783e-01, 3.6705e-02, 2.5139e02],
[1.6186e-02, 1.0893e00, -2.7614e01],
[-4.3304e-04, 7.6681e-04, 1.0000e00],
],
device="cuda:0",
dtype=torch.float64,
)
homography_0_2 = torch.tensor(
[
[7.8938e-01, 3.5727e-02, 1.5221e02],
[1.8347e-02, 1.0921e00, -2.8547e01],
[-4.3172e-04, 7.7596e-04, 1.0000e00],
],
device="cuda:0",
dtype=torch.float64,
)
transform_h1_h2 = (
torch.linalg.inv(homography_0_1)
.matmul(homography_0_2)
.type(torch.float32)
.view(1, 3, 3)
)
# warped_image_torch = homography_warp(image_reshaped, transform_h1_h2, dsize=(height, width), padding_mode="reflection", normalized_homography=False)
warped_image_torch = warp_perspective(image_reshaped, transform_h1_h2, dsize=(height, width), padding_mode="reflection")
warped_image_1_2_cv = cv2.warpPerspective(
image_cv,
transform_h1_h2.cpu().numpy().squeeze(),
dsize=(width, height),
borderMode=cv2.BORDER_REFLECT101,
)
warped_kornia = warped_image_torch.cpu().numpy().squeeze().transpose(1, 2, 0).astype(np.uint8)
cv2.imwrite("kornia_warp.png", np.hstack((warped_image_1_2_cv, warped_kornia)))
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/510780.html
