-
Notifications
You must be signed in to change notification settings - Fork 0
/
perspective_lab.py
188 lines (151 loc) · 8.3 KB
/
perspective_lab.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
# version code 80e56511a793+
# Please fill out this stencil and submit using the provided submission script.
from vec import Vec
from mat import Mat
from matutil import rowdict2mat, mat2rowdict
import image_mat_util
from solver import solve
## 1: (Task 5.12.1) Move To Board
def move2board(y):
'''
Input:
- y: a Vec with domain {'y1','y2','y3'}, the coordinate representation in whiteboard coordinates of a point q
Output:
- A {'y1','y2','y3'}-Vec, the coordinate representation
in whiteboard coordinates of the point p such that the line through the
origin and q intersects the whiteboard plane at p.
'''
return Vec({'y1','y2','y3'}, {'y1': y['y1'] / y['y3'], 'y2': y['y2'] / y['y3'], 'y3': 1})
## 2: () Make domain of vector
# D should be assigned the Cartesian product of R and C
D = {('y1', 'x1'), ('y1', 'x2'), ('y1', 'x3'), ('y2', 'x1'), ('y2', 'x2'), ('y2', 'x3'), ('y3', 'x1'), ('y3', 'x2'), ('y3', 'x3')}
## 3: (Task 5.12.2) Make Equations
def make_equations(x1, x2, w1, w2):
'''
Input:
- x1, x2: pixel coordinates of a point q in the image plane
- w1, w2: w1=y1/y3 and w2=y2/y3 where y1,y2,y3 are the whiteboard coordinates of q.
Output:
- List [u,v] of D-vectors that define linear equations u*h = 0 and v*h = 0
For example, suppose we have an image of the whiteboard in which
the top-left whiteboard corner appears at pixel coordinates 9, 18
the bottom-left whiteboard corner appears at pixel coordinates 8,25
the top-right whiteboard corner appears at pixel coordinates 20,20
the bottom-right whiteboard corner appears at pixel coordinates 18,23
Let q be the point in the image plane with pixel coordinates x=8,y=25, i.e. camera coordinates (8,25,1).
Let y1,y2,y3 be the whiteboard coordinates of the same point. The line that goes through the
origin and p intersects the whiteboard at a point p. That point p is the bottom-left corner of
the whiteboard, so its whiteboard coordinates are 0,1,1. Therefore (y1/y3,y2/y3,y3/y3) = (0,1,1).
We define w1=y1/y3 and w2=y2/y3, so w1 = 0 and w2 = 1. Given this input-output pair, let's find
two linear equations u*h=0 and v*h=0 constraining the unknown vector h whose entries are the entries
of the matrix H.
>>> for v in make_equations(8,25,1,0): print(v)
<BLANKLINE>
('y1', 'x1') ('y1', 'x2') ('y1', 'x3') ('y2', 'x1') ('y2', 'x2') ('y2', 'x3') ('y3', 'x1') ('y3', 'x2') ('y3', 'x3')
---------------------------------------------------------------------------------------------------------------------
-8 -25 -1 0 0 0 8 25 1
<BLANKLINE>
('y1', 'x1') ('y1', 'x2') ('y1', 'x3') ('y2', 'x1') ('y2', 'x2') ('y2', 'x3') ('y3', 'x1') ('y3', 'x2') ('y3', 'x3')
---------------------------------------------------------------------------------------------------------------------
0 0 0 -8 -25 -1 0 0 0
Note that the negations of these vectors form an equally valid solution.
Similarly, consider the point q in the image plane with pixel coordinates 18, 23. Let y1,y2,y3 be the whiteboard
coordinates of p. The corresponding point p in the whiteboard plane is the bottom-right corner, and the whiteboard
coordinates of p are 1,1,1, so (y1/y3,y2/y3,y3/y3)=(1,1,1). We define w1=y1/y3 and w2=y2/y3, so w1=1 and w2=1.
We obtain the vectors u and v defining equations u*h=0 and v*h=0 as follows:
>>> for v in make_equations(18,23,1,1): print(v)
<BLANKLINE>
('y1', 'x1') ('y1', 'x2') ('y1', 'x3') ('y2', 'x1') ('y2', 'x2') ('y2', 'x3') ('y3', 'x1') ('y3', 'x2') ('y3', 'x3')
---------------------------------------------------------------------------------------------------------------------
-18 -23 -1 0 0 0 18 23 1
<BLANKLINE>
('y1', 'x1') ('y1', 'x2') ('y1', 'x3') ('y2', 'x1') ('y2', 'x2') ('y2', 'x3') ('y3', 'x1') ('y3', 'x2') ('y3', 'x3')
---------------------------------------------------------------------------------------------------------------------
0 0 0 -18 -23 -1 18 23 1
Again, the negations of these vectors form an equally valid solution.
'''
u = Vec(D, {('y1', 'x1'): -x1, ('y1', 'x2'): -x2, ('y1', 'x3'): -1, ('y3', 'x1'): w1 * x1, ('y3', 'x2'): w1 * x2, ('y3', 'x3'): w1})
v = Vec(D, {('y2', 'x1'): -x1, ('y2', 'x2'): -x2, ('y2', 'x3'): -1, ('y3', 'x1'): w2 * x1, ('y3', 'x2'): w2 * x2, ('y3', 'x3'): w2})
return [u, v]
## 4: () Scaling row
# This is the vector defining the scaling equation
w = Vec(D, {('y1', 'x1'): 1})
## 5: () Right-hand side
# Now construct the Vec b that serves as the right-hand side for the matrix-vector equation L*hvec=b
# This is the {0, ..., 8}-Vec whose entries are all zero except for a 1 in position 8
b = Vec({0, 1, 2, 3, 4, 5, 6, 7, 8}, {8: 1})
## 6: () Rows of constraint matrix
def make_nine_equations(corners):
'''
input: a list of four tuples:
[(i0,j0),(i1,j1),(i2,j2),(i3,j3)]
where i0,j0 are the pixel coordinates of the top-left corner,
i1,j1 are the pixel coordinates of the bottom-left corner,
i2,j2 are the pixel coordinates of the top-right corner,
i3,j3 are the pixel coordinates of the bottom-right corner,
output: the list of Vecs u0, u1, ..., u8 that are to be the rows of the matrix.
Vecs u0,u1 come from applying make_equations to the top-left corner,
Vecs u2,u3 come from applying make_equations to the bottom-left corner,
Vecs u4,u5 come from applying make_equations to the top-right corner,
Vecs u6,u7 come from applying make_equations to the bottom-right corner,
Vec u8 is the vector w.
'''
(i0,j0), (i1,j1), (i2,j2), (i3,j3) = corners
return make_equations(i0, j0, 0, 0) + make_equations(i1, j1, 0, 1) \
+ make_equations(i2, j2, 1, 0) + make_equations(i3, j3, 1, 1) + [w]
## 7: (Task 5.12.4) Build linear system
# Apply make_nine_equations to the list of tuples specifying the pixel coordinates of the
# whiteboard corners in the image. Assign the resulting list of nine vectors to veclist:
veclist = make_nine_equations([(358, 36), (329, 597), (592, 157), (580, 483)])
# Build a Mat whose rows are the Vecs in veclist
# print(rowdict2mat(make_equations(358, 36, 0, 0)))
L = rowdict2mat(veclist)
# print(L)
## 8: () Solve linear system
# Now solve the matrix-vector equation to get a Vec hvec, and turn it into a matrix H.
hvec = solve(L, b)
H = Mat(({'y1', 'y2', 'y3'}, {'x1', 'x2', 'x3'}), hvec.f)
(X_pts, colors) = image_mat_util.file2mat('board.png', ('x1', 'x2', 'x3'))
Y_pts = H * X_pts
## 9: (Task 5.12.7) Y Board Comprehension
def mat_move2board(Y):
'''
Input:
- Y: a Mat each column of which is a {'y1', 'y2', 'y3'}-Vec
giving the whiteboard coordinates of a point q.
Output:
- a Mat each column of which is the corresponding point in the
whiteboard plane (the point of intersection with the whiteboard plane
of the line through the origin and q).
Example:
>>> Y_in = Mat(({'y1', 'y2', 'y3'}, {0,1,2,3}),
... {('y1',0):2, ('y2',0):4, ('y3',0):8,
... ('y1',1):10, ('y2',1):5, ('y3',1):5,
... ('y1',2):4, ('y2',2):25, ('y3',2):2,
... ('y1',3):5, ('y2',3):10, ('y3',3):4})
>>> print(Y_in)
<BLANKLINE>
0 1 2 3
------------
y1 | 2 10 4 5
y2 | 4 5 25 10
y3 | 8 5 2 4
<BLANKLINE>
>>> print(mat_move2board(Y_in))
<BLANKLINE>
0 1 2 3
------------------
y1 | 0.25 2 2 1.25
y2 | 0.5 1 12.5 2.5
y3 | 1 1 1 1
<BLANKLINE>
'''
rows = mat2rowdict(Y)
y1 = rows['y1']
y2 = rows['y2']
y3 = rows['y3']
return rowdict2mat({'y1': Vec(y1.D, dict((k, y1[k] / y3[k]) for k in y1.D)),
'y2': Vec(y2.D, dict((k, y2[k] / y3[k]) for k in y2.D)),
'y3': Vec(y3.D, dict((k, y3[k] / y3[k]) for k in y3.D))})
Y_board = mat_move2board(Y_pts)
image_mat_util.mat2display(Y_board, colors, ('y1', 'y2', 'y3'), scale=100, xmin=None, ymin=None)