diff --git a/perspective/perspective.md b/perspective/perspective.md new file mode 100644 index 0000000..789c40b --- /dev/null +++ b/perspective/perspective.md @@ -0,0 +1,138 @@ +# 透视投影 + +# 总体思路: + 1.先透视变换 $P_{透视}$ + 2.再投影 $P_{投影}$ + 3.最终的变换矩阵 $T = P_{透视}P_{投影}$ + 4.定点序列 $V_{new}=V_{origin}T $ +# 1. 透视 + +## 1.1 一点透视 + +### 步骤: + + (1) 进行平移变换,将三维形体平移到适当位 置l、m、n; + + (2)进行透视变换; + + (3)进行投影变换,向xoy平面作正投影变换,将结果变换到xoy平面上。 + + 变换矩阵: +
+ +$P_{透视}=\begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&1&0\\L&M&N&1\end{bmatrix}$ +
+ +## 1.2 两点透视 + +### 步骤: + + (1)先将三维形体平移到适当位置,使视点有一定 高度,且使形体的主要表面不会积聚成线; + + (2)将形体绕y轴旋转一个φ⻆(φ<90 ̊),方向满足 右手定则; + + (3)进行透视变换; + + (4)最后向xoy面作正投影,即得二点透视图。 + + 变换矩阵: +
+ +$P_{透视}=\begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&1&0\\L&M&N&1\end{bmatrix}\begin{bmatrix} cos(φ)&0&sin(φ)&0\\0&1&0&0\\-sin(φ)&0&cos(φ)&0\\0&0&0&1\end{bmatrix}$ +
+ +## 1.3 三点透视 + +### 步骤: + + (1)首先将三维形体平移到适当位置;; + + (2)将形体进行透视变换; + + (3)然后使形体先绕y轴旋转φ⻆; + + (4)再绕x轴旋转θ⻆; + + (5)将变形且旋转后的形体向xoy面作正投影。 + + 变换矩阵: +
+ +$P_{透视}=\begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&1&0\\L&M&N&1\end{bmatrix}\begin{bmatrix} cosφ&0&sinφ&0\\0&1&0&0\\-sinφ&0&cosφ&0\\0&0&0&1\end{bmatrix}\begin{bmatrix} 1&0&0&0\\0&cosθ&sinθ&0\\0&-sinθ&cosθ&0\\0&0&0&1\end{bmatrix}$ +
+ +# 2 投影 + +
+ +
+ +  首先考虑这样一种最简单的情况,假设投影中心为坐标为 $(0, 0, -d)$ ,空间中任意一点$P(x,y,z)$,投影到$xOy$平面一点$P^’(x^’,y^’,0)$,由相似三角形易证: +
+ +$x^’= \frac{d}{d+z}*x$ + +$y^’= \frac{d}{d+z}*y$ +
+ +  易得,$P^’$的齐次坐标位为 + +
+ + $[\frac{d}{d+z}*x,\frac{d}{d+z}*y,0,1]$ +
+ +  即 + +
+ +$[x,y,0,\frac{1+z}d]$ +
+  因此,投投影矩阵为 + +
+ +$P_{投影}=\begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&0& \frac{1}{d} \\ 0&0&0&1 \\ \end{bmatrix}$ +
+  推广:空间任意一点作为投影中心,投影到xOy平面 + +
+ +$P_{投影}=\begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&1&0 \\ -x_0&-y_0&0&1 \\ \end{bmatrix}\begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&0& \frac{1}{d} \\ 0&0&0&1 \\ \end{bmatrix} \begin{bmatrix} 1&0&0&0\\0&1&0&0\\0&0&1&0 \\ x_0&y_0&0&1\\ \end{bmatrix}= \begin{bmatrix} 1&0&0&0\\0&1&0&0\\\frac{x}{d}& \frac{y}{d}&0& \frac{1}{d} \\ 0&0&0&1\\ \end{bmatrix}$ +
+ +# 3 实例 + 假设初始顶点序列表示一个顶点在原点,边长为2的正方体,视点在(4,4,-2),投影平面在$xOy$。 + 用蓝色图形表示原图形;红色图形表示透视移动后的图形;黑色图形表示投影结果;绿色平面是投影平面;粉色虚线表示进行透视所进行的变换对应关系;黄色虚线表示投影进行的变换关系。 +## 3.1 一点透视 + 假设移动距离L=6,M=5,N=1 +
+ + +

一点透视三维示意图

+ + +

一点透视投影结果

+
+ +## 3.2 二点透视 + 假设移动距离L=6,M=5,N=1,φ=40$^。$ +
+ + +

一二点透视三维示意图

+ + +

二点透视投影结果

+
+ +## 3.3 三点透视 + 假设移动距离L=1,M=-3,N=4,φ=45$^。$,θ=30$^。$ +
+ + +

三点透视三维示意图

+ + +

三点透视投影结果

+
\ No newline at end of file diff --git a/projection.py b/perspective/perspective.py similarity index 54% rename from projection.py rename to perspective/perspective.py index e70f6dd..075c427 100644 --- a/projection.py +++ b/perspective/perspective.py @@ -19,19 +19,38 @@ def projection_trans(view_point,points): new_points=np.matmul(points,mtx) return new_points -def one_point_projection(L,M,N,view_point,point): - '''一点''' +def one_point_perspective(L,M,N,view_point,point): + '''一点透视:移动L,M,N''' + mtx_mv=np.array([[1,0,0,0], + [0,1,0,0], + [0,0,1,0], + [L,M,N,1]],dtype=np.float32) + new_point=np.matmul(point,mtx_mv) + + return new_point + +def two_point_perspective(L,M,N,a,view_point,point): + '''二点透视''' + #先移动L,M,N mtx_mv=np.array([[1,0,0,0], [0,1,0,0], [0,0,1,0], [L,M,N,1]],dtype=np.float32) point=np.matmul(point,mtx_mv) - # print(point) - new_point=projection_trans(view_point,point) - return new_point,point -def two_point_projection(L,M,N,a,view_point,point): - '''二点''' + #绕y轴旋转 a 度(a<90deg) + a=a/180*np.pi + mtx_roty=np.array([[np.cos(a),0,np.sin(a),0], + [0,1,0,0], + [-1*np.sin(a),0,np.cos(a),0], + [0,0,0,1]],dtype=np.float32) + new_point=np.matmul(point,mtx_roty) + + return new_point + + +def three_point_perspective(L,M,N,a,b,view_point,point): + '''三点透视''' #先移动L,M,N mtx_mv=np.array([[1,0,0,0], [0,1,0,0], @@ -47,71 +66,18 @@ def two_point_projection(L,M,N,a,view_point,point): [0,0,0,1]],dtype=np.float32) point=np.matmul(point,mtx_roty) - # print(point) - new_point=projection_trans(view_point,point) - return new_point,point - - -def three_point_projection(L,M,N,a,b,view_point,point): - '''三点''' - #先移动L,M,N - mtx_mv=np.array([[1,0,0,0], - [0,1,0,0], - [0,0,1,0], - [L,M,N,1]],dtype=np.float32) - point=np.matmul(point,mtx_mv) - print("aaa") - print(point) - #绕y轴旋转 a 度(a<90deg) - a=a/180*np.pi - mtx_roty=np.array([[np.cos(a),0,np.sin(a),0], - [0,1,0,0], - [-1*np.sin(a),0,np.cos(a),0], - [0,0,0,1]],dtype=np.float32) - point=np.matmul(point,mtx_roty) - print("bbb") - print(point) #绕x轴旋转 b 度(b<90deg) b=b/180*np.pi mtx_rotx=np.array([[1,0,0,0], [0,np.cos(b),np.sin(b),0], [0,-1*np.sin(b),np.cos(b),0], [0,0,0,1]],dtype=np.float32) - point=np.matmul(point,mtx_rotx) - print("ccc") - print(point) - # print(point) - new_point=projection_trans(view_point,point) - return new_point,point + new_point=np.matmul(point,mtx_rotx) + + return new_point -view_point = np.array([0,0,-1,1],dtype=np.float32) -points= np.array([[0,0,0,1], - [1,0,0,1], - [1,1,0,1], - [0,1,0,1], - [0,0,0,1], - [0,0,1,1], - [1,0,1,1], - [1,1,1,1], - [0,1,1,1], - [0,0,1,1], - [0,0,0,1], - [1,0,0,1], - [1,0,1,1], - [1,1,1,1], - [1,1,0,1], - [0,1,0,1], - [0,1,1,1]],dtype=np.float32) - - -#new_points=one_point_projection(0,0,0,view_point,points) -new_points,ori_points=three_point_projection(2,3,1,50,30,view_point,points) - -new_points=homo2cart(new_points) - - -def draw(view_point,ori_points,new_points): +def draw(view_point,ori_points,mv_points,new_points): plt.scatter(new_points[:,0],new_points[:,1],c="black") plt.plot(new_points[:,0],new_points[:,1],c="black") ax=Axes3D(plt.figure()) @@ -123,23 +89,63 @@ def draw(view_point,ori_points,new_points): ax.plot_surface(X,Y,Z=X*0,color='g',alpha=0.3) - ax.scatter(ori_points[:,0],ori_points[:,1],ori_points[:,2]) + #原来的点阵 + ax.scatter(ori_points[:,0],ori_points[:,1],ori_points[:,2],c="brown") + ax.plot(ori_points[:,0],ori_points[:,1],ori_points[:,2],c="brown") + #透视移动后 + ax.scatter(mv_points[:,0],mv_points[:,1],mv_points[:,2]) ax.scatter(view_point[0],view_point[1],view_point[2],c='r') - ax.plot(ori_points[:,0],ori_points[:,1],ori_points[:,2]) - ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1,1, 0.5, 1])) - + ax.plot(mv_points[:,0],mv_points[:,1],mv_points[:,2]) + ax.get_proj = lambda: np.dot(Axes3D.get_proj(ax), np.diag([1,1, 1, 1])) + #投影后 ax.scatter(new_points[:,0],new_points[:,1],c="black") ax.plot(new_points[:,0],new_points[:,1],c="black") + #原来与移动后点两两连接 + for i in range(len(mv_points)): + ax.plot([ori_points[i,0],mv_points[i,0]],[ori_points[i,1],mv_points[i,1]],[ori_points[i,2],mv_points[i,2]],c="pink",linestyle='--') + #两组点两两连接 + for i in range(len(mv_points)): + ax.plot([mv_points[i,0],view_point[0]],[mv_points[i,1],view_point[1]],[mv_points[i,2],view_point[2]],c='y',linestyle='dashdot') ax.set_zlabel('Z', fontdict={'size': 15, 'color': 'red'}) ax.set_ylabel('Y', fontdict={'size': 15, 'color': 'red'}) ax.set_xlabel('X', fontdict={'size': 15, 'color': 'red'}) - - plt.show() +#视点(0,0,-1,1) +view_point = np.array([4,4,-2,1],dtype=np.float32) +#以(0,0,0)为原点的正方体 +points= np.array([[0,0,0,1], + [2,0,0,1], + [2,2,0,1], + [0,2,0,1], + [0,0,0,1], + [0,0,2,1], + [2,0,2,1], + [2,2,2,1], + [0,2,2,1], + [0,0,2,1], + [0,0,0,1], + [2,0,0,1], + [2,0,2,1], + [2,2,2,1], + [2,2,0,1], + [0,2,0,1], + [0,2,2,1]],dtype=np.float32) + +#获得透视移动后的点和投影后的点 +#per_points=one_point_perspective(6,5,1,view_point,points) +#per_points=two_point_perspective(6,5,1,40,view_point,points) +#透视移动后的点 +per_points=three_point_perspective(1,-3,3,45,30,view_point,points) +#投影后的点 +pro_points=projection_trans(view_point,per_points) +#转为笛卡尔坐标系 +per_points=homo2cart(per_points) +pro_points=homo2cart(pro_points) -draw(view_point,ori_points,new_points) \ No newline at end of file +#画图 +draw(view_point,points,per_points,pro_points) \ No newline at end of file diff --git a/perspective/pic/Figure_1.png b/perspective/pic/Figure_1.png new file mode 100644 index 0000000..a4a4618 Binary files /dev/null and b/perspective/pic/Figure_1.png differ diff --git a/perspective/pic/Figure_2.png b/perspective/pic/Figure_2.png new file mode 100644 index 0000000..7f959e9 Binary files /dev/null and b/perspective/pic/Figure_2.png differ diff --git a/perspective/pic/Figure_3.png b/perspective/pic/Figure_3.png new file mode 100644 index 0000000..70c6a7c Binary files /dev/null and b/perspective/pic/Figure_3.png differ diff --git a/perspective/pic/Figure_4.png b/perspective/pic/Figure_4.png new file mode 100644 index 0000000..e136c46 Binary files /dev/null and b/perspective/pic/Figure_4.png differ diff --git a/perspective/pic/Figure_5.png b/perspective/pic/Figure_5.png new file mode 100644 index 0000000..b93f161 Binary files /dev/null and b/perspective/pic/Figure_5.png differ diff --git a/perspective/pic/Figure_6.png b/perspective/pic/Figure_6.png new file mode 100644 index 0000000..21cfd6a Binary files /dev/null and b/perspective/pic/Figure_6.png differ diff --git a/perspective/pic/Untitled.png b/perspective/pic/Untitled.png new file mode 100644 index 0000000..a2fb873 Binary files /dev/null and b/perspective/pic/Untitled.png differ