如何从两对点获得二维变换矩阵?

问题描述 投票:0回答:1

OpenCV 提供:

  • getRotationMatrix2D
    获取由
    center
    angle
    scale
  • 定义的 2x3 变换矩阵(旋转、缩放、平移)
  • getAffineTransform
    获得由三对点定义的 2x3 变换矩阵(旋转、缩放、平移、剪切)。

我想从两对点获得一个具有旋转、缩放和平移(即无剪切)的变换矩阵。

这是我当前的实现,它有效,但对我来说太复杂了:

from typing import Tuple, List

import cv2
import numpy as np
import numpy.typing


def _third_triangle_point(p1: Tuple[float, float], p2: Tuple[float, float]) -> Tuple[float, float]:
    """Calculate the third point of an isosceles right-angled triangle."""
    p1_arr = np.array(p1, dtype=np.float32)
    p2_arr = np.array(p2, dtype=np.float32)
    diff = p2_arr - p1_arr
    perpendicular = np.array((diff[1], -diff[0]), dtype=np.float32)
    result = p1_arr + perpendicular
    return result[0], result[1]


def _stack_points(points: List[Tuple[float, float]]) -> np.typing.NDArray[np.float32]:
    return np.vstack([np.array(p, dtype=np.float32) for p in points])


def get_transformation_between_two_point_pairs(
        src: Tuple[Tuple[float, float], Tuple[float, float]],
        dst: Tuple[Tuple[float, float], Tuple[float, float]]
) -> np.typing.NDArray[np.float32]:
    # cv2.getAffineTransform takes three point pairs.
    # It supports rotation, translation, scaling, and shearing.
    # We don't need the shearing,
    # so we invent a third point with a stable relation to the given two.
    return cv2.getAffineTransform(  # type: ignore
        _stack_points([src[0], src[1], _third_triangle_point(src[0], src[1])]),
        _stack_points([dst[0], dst[1], _third_triangle_point(dst[0], dst[1])])
    )


print(get_transformation_between_two_point_pairs(((10, 10), (17, 23)), ((30, 30), (70, 30))))
[[ 1.28440367  2.3853211  -6.69724771]
 [-2.3853211   1.28440367 41.00917431]]

有没有更简单的方法可以达到相同的结果?

python opencv computer-vision linear-algebra affinetransform
1个回答
0
投票

解决办法很简单,只需使用

estimateAffinePartial2D
:

from typing import Tuple

import cv2
import numpy as np
import numpy.typing


def get_transformation_between_two_point_pairs(
        src: Tuple[Tuple[float, float], Tuple[float, float]],
        dst: Tuple[Tuple[float, float], Tuple[float, float]]
) -> np.typing.NDArray[np.float32]:
    return cv2.estimateAffinePartial2D(np.array([src[0], src[1]]), np.array([dst[0], dst[1]]))[0]  # type: ignore


print(get_transformation_between_two_point_pairs(((10, 10), (17, 23)), ((30, 30), (70, 30))))
[[ 1.28440367  2.3853211  -6.69724771]
 [-2.3853211   1.28440367 41.00917431]]
© www.soinside.com 2019 - 2024. All rights reserved.