OpenCV提供:

  • getRotationMatrix2D以得到由centeranglescale定义的2x3变换矩阵(旋转、zoom 、移位
  • getAffineTransform以获得由三对点定义的2x3变换矩阵(旋转、zoom 、平移、透明).

我想从两对点得到一个具有旋转、zoom 和移位(即没有剪切)的变换矩阵.

以下是我目前的实现,它很有效,但对我来说太复杂了:

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]]

有没有更简单的方法来达到同样的结果?

推荐答案

解决方案很简单,只需使用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]]

Python相关问答推荐

如何在具有重复数据的pandas中对groupby进行总和,同时保留其他列

为什么tkinter框架没有被隐藏?

带条件计算最小值

如何记录脚本输出

将图像拖到另一个图像

C#使用程序从Python中执行Exec文件

Telethon加入私有频道

如何将一个动态分配的C数组转换为Numpy数组,并在C扩展模块中返回给Python

在Python中动态计算范围

pandas:排序多级列

在代码执行后关闭ChromeDriver窗口

用SymPy在Python中求解指数函数

查看pandas字符列是否在字符串列中

从嵌套极轴列的列表中删除元素

如何获得满足掩码条件的第一行的索引?

极点替换值大于组内另一个极点数据帧的最大值

替换包含Python DataFrame中的值的<;

递归链表反转与打印语句挂起

我可以同时更改多个图像吗?

关于数字S种子序列内部工作原理的困惑