钾肥喵的窝

我在 CODING 部署的 Hexo 博客

0%

用四角坐标反推投影变换矩阵

缘起

在给Petpet生成器添加新功能的时候发现需要对图片进行投影变换, 但是SixLabors的投影变换不能直接使用四角坐标, 而是需要使用变换矩阵, 因此有了这篇文章.

齐次坐标

坐标变换的形式如下:

\[ \begin{pmatrix} x' \\ y' \\ z' \\ k \end{pmatrix} = \begin{bmatrix} a_{11} & a_{12} & a_{13} & a_{14} \\ a_{21} & a_{22} & a_{23} & a_{24} \\ a_{31} & a_{32} & a_{33} & a_{34} \\ a_{41} & a_{42} & a_{43} & a_{44} \end{bmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \end{pmatrix} \]

其中的\(k\)可视作缩放系数, 最终的坐标应当是\((\frac{x'}{k}, \frac{y'}{k}, \frac{z'}{k})\).

推导过程

我们用\(LT' = (x_{1}, y_{1}), RT'=(x_{2}, y_{2}), RB'=(x_{3}, y_{3}), LB'=(x_{4}, y_{4})\)分别表示 变换后的左上角、右上角、右下角、左下角坐标(顺时针顺序), 用\(w, h\)分别表示原图的宽与高, 以左上角为原点, 坐标向右向下增大.

首先有\(LT=(0, 0), RT=(w, 0), RB=(w, h), LB=(0, h)\).

因为变换前后都是二维坐标, 不妨令\(z\)轴全为0, 此时有变换矩阵:

\[ \begin{bmatrix} a_{11} & a_{12} & 0 & a_{14} \\ a_{21} & a_{22} & 0 & a_{24} \\ 0 & 0 & 1 & 0 \\ a_{41} & a_{42} & 0 & a_{44} \end{bmatrix} \]

\(LT\)\(LT'\)代入得: \(a_{14}=x_{1}, a_{24}=y_{1}, a_{44}=1\).

\[ \begin{bmatrix} a_{11} & a_{12} & 0 & x_{1} \\ a_{21} & a_{22} & 0 & y_{1} \\ 0 & 0 & 1 & 0 \\ a_{41} & a_{42} & 0 & 1 \end{bmatrix} \]

继续代入可得方程组:

\[ \left\{ \begin{aligned} x_{2} = \frac{a_{11}w+x_{1}}{a_{41}w+1} \\ \\ y_{2} = \frac{a_{21}w+y_{1}}{a_{41}w+1} \end{aligned}\right. \quad \left\{ \begin{aligned} x_{3} = \frac{a_{11}w+a_{12}h+x_{1}}{a_{41}w+a_{42}h+1} \\ \\ y_{3} = \frac{a_{21}w+a_{22}h+y_{1}}{a_{41}w+a_{42}h+1} \end{aligned}\right. \quad \left\{ \begin{aligned} x_{4} = \frac{a_{12}h+x_{1}}{a_{42}h+1} \\ \\ y_{4} = \frac{a_{22}h+y_{1}}{a_{42}h+1} \end{aligned}\right. \]

变形可得方程组:

\[ \left\{ \begin{align*} & w \cdot a_{11} - wx_{2} \cdot a_{41} = x_{2} - x_{1} \\ & w \cdot a_{21} - wy_{2} \cdot a_{41} = y_{2} - y_{1} \\ & w \cdot a_{11} + h \cdot a_{12} - wx_{3} \cdot a_{41} - hx_{3} \cdot a_{42} = x_{3}-x_{1} \\ & w \cdot a_{21} + h \cdot a_{22} - wy_{3} \cdot a_{41} - hy_{3} \cdot a_{42} = y_{3}-y_{1} \\ & h \cdot a_{12} - hx_{4} \cdot a_{42} = x_{4} - x_{1} \\ & h \cdot a_{22} - hy_{4} \cdot a_{42} = y_{4} - y_{1} \end{align*} \right. \]

求解非齐次线性方程组:

\[ \begin{bmatrix} w & 0 & 0 & 0 & -wx_{2} & 0 \\ 0 & 0 & w & 0 & -wy_{2} & 0 \\ w & h & 0 & 0 & -wx_{3} & -hx_{3} \\ 0 & 0 & w & h & -wy_{3} & -hy_{3} \\ 0 & h & 0 & 0 & 0 & -hy_{4} \\ 0 & 0 & 0 & h & 0 & -hy_{4} \end{bmatrix} \times \begin{bmatrix} a_{11}\\ a_{12}\\ a_{21}\\ a_{22}\\ a_{41}\\ a_{42} \end{bmatrix} = \begin{bmatrix} x_{2} - x_{1} \\ y_{2} - y_{1} \\ x_{3} - x_{1} \\ y_{3} - y_{1} \\ x_{4}-x_{1} \\ y_{4}-y_{1} \end{bmatrix} \]

扔给Mathematica求解:

1
2
3
4
5
6
7
8
9
10
Solve[
{
w*a11 - w*x2*a41 == x2 - x1,
w*a21 - w*y2*a41 == y2 - y1,
w*a11 + h*a12 - w*x3*a41 - h*x3*a42 == x3 - x1,
w*a21 + h*a22 - w*y3*a41 - h*y3*a42 == y3 - y1,
h*a12 - h*x4*a42 == x4 - x1,
h*a22 - h*y4*a42 == y4 - y1
}, {a11, a12, a21, a22, a41, a42}
]

解得(已手动合并同类项):

\[ \left\{ \begin{align*} a_{11}&=-\frac{x_{1}x_{3}(y_{2}-y_{4}) - x_{1}x_{4}(y_{2}-y_{3}) - x_{2}x_{3}(y_{1}-y_{4}) + x_{2}x_{4}(y_{1}-y_{3})} {w (-x_{2}y_{3}+x_{2}y_{4}+x_{3}y_{2}-x_{3}y_{4}-x_{4}y_{2}+x_{4}y_{3})}\\ a_{12}&=\frac{x_{1}x_{2}(y_{3}-y_{4}) - x_{1}x_{3}(y_{2}-y_{4}) + x_{2}x_{4}(y_{1}-y_{3}) - x_{3}x_{4}(y_{1}-y_{2})} {h (-x_{2}y_{3}+x_{2}y_{4}+x_{3}y_{2}-x_{3}y_{4}-x_{4}y_{2}+x_{4}y_{3})}\\ a_{21}&=\frac{-(x_{1}y_{2}-x_{2}y_{1})(y_{3}-y_{4})+(x_{3}y_{4}-x_{4}y_{3})(y_{1}-y_{2})} {w (-x_{2}y_{3}+x_{2}y_{4}+x_{3}y_{2}-x_{3}y_{4}-x_{4}y_{2}+x_{4}y_{3})}\\ a_{22}&=-\frac{(x_{1}y_{4}-x_{4}y_{1})(y_{2}-y_{3})-(x_{2}y_{3} - x_{3}y_{2})(y_{1}-y_{4})} {h (-x_{2}y_{3}+x_{2}y_{4}+x_{3}y_{2}-x_{3}y_{4}-x_{4}y_{2}+x_{4}y_{3})}\\ a_{41}&=\frac{-(x_{1}-x_{2})(y_{3}-y_{4})+(x_{3}-x_{4})(y_{1}-y_{2})} {w (-x_{2}y_{3}+x_{2}y_{4}+x_{3}y_{2}-x_{3}y_{4}-x_{4}y_{2}+x_{4}y_{3})}\\ a_{42}&=\frac{-(x_{1}-x_{4})(y_{2}-y_{3}) + (x_{2}-x_{3})(y_{1}-y_{4})} {h (-x_{2}y_{3}+x_{2}y_{4}+x_{3}y_{2}-x_{3}y_{4}-x_{4}y_{2}+x_{4}y_{3})} \end{align*} \right. \]