416 字
2 分钟
透视转换, 从一个四边形, 映射到另一个四边形

概述#

透视变换用于将在坐标系中的一个四边形映射到另一个四边形. 相较于仿射变换, 透视变换前平行的线, 并不保证再变换后仍然平行. 但直线在变换之后仍然是直线.

一般的, 是通过两四边形的点, 获取一个表示透视变换的矩阵, 对点做乘法, 最后对结果做处理, 即可得到变换之后的点.

M×P=RM \times P = R

不过这里的点, 需要作为三行一列的矩阵传入, 第三行传入 1:

[?????????]×[xy1]=[xyw]\left[ \begin{matrix} ? & ? & ? \\ ? & ? & ? \\ ? & ? & ? \\ \end{matrix} \right] \times \left[ \begin{matrix} x \\ y \\ 1 \\ \end{matrix} \right] = \left[ \begin{matrix} x^{\prime} \\ y^{\prime} \\ w^{\prime} \\ \end{matrix} \right]

最后变换的结果就是 (x÷w,y÷w)(x^{\prime} \div w^{\prime}, y^{\prime} \div w^{\prime}).

实操#

使用 OpenCV, 即可轻松实现. Cv2.GetPerspectiveTransform 传入两个表示四边形点的可迭代对象, 返回一个三行三列的透视变换矩阵:

Mat GetPerspectiveTransform(IEnumerable<Point2f> src, IEnumerable<Point2f> dst);

那么, 假设我们有两个长度为 4 的 Point2f 数组, 每一个数组存储四边形的四个点坐标, 那么通过以下操作, 即可得到透视变换矩阵:

Point2f[] srcQard;   // 源四边形
Point2f[] destQard;  // 目标四边形

Mat perspectiveTransform = Cv2.GetPerspectiveTransform(srcQard, destQard);

接下来, 假设我们有要进行变换的点的 x y 坐标, 然后构造一个存储该点的矩阵:

double x;  // X
double y;  // Y

Mat matrixPoint = new Mat<double>(3, 1);
matrixPoint.Set<double>(0, 0, x);
matrixPoint.Set<double>(1, 0, y);
matrixPoint.Set<double>(2, 0, 1);

进行乘法运算, 并取得变换结果:

Mat result = perspectiveTransform * matrixPoint;

double resultX = result.Get<double>(0, 0) / result.Get<double>(2, 0);
double resultY = result.Get<double>(1, 0) / result.Get<double>(2, 0);
透视转换, 从一个四边形, 映射到另一个四边形
https://slimenull.com/posts/202410030308/
作者
SlimeNull
发布于
2024-10-03
许可协议
CC BY-NC-SA 4.0