Upload
others
View
0
Download
0
Embed Size (px)
Citation preview
コンピュータビジョンカメラモデル
カメラの幾何学的モデル(1/3)• Pinhole camera model (or central projection)
X
Y
Z
x
y
f
O
x =
xy
�
X =
2
4XYZ
3
5
x = fX
Zy = f
Y
Z
2
4xy1
3
5 /
2
4f 0 00 f 00 0 1
3
5
2
4XYZ
3
5
image plane
image coordinates
camera coordinates
焦点距離と画角の関係
-
: focal length(焦点距離)注:画像面と投影中心間の距離
f
http://www.sony.jp/cyber-shot/products/DSC-RX1/spec.html
X
Y
Z
x
y
f
O
x =
xy
�
X =
2
4XYZ
3
5
カメラの幾何学的モデル(2/3)• Offset of projection center
Matrix of internal parameters
2
4xy1
3
5 /
2
4f 0 x0
0 f y00 0 1
3
5
2
4XYZ
3
5x = fX
Z+ x0 y = f
Y
Z+ y0
K =
2
4f 0 x0
0 f y00 0 1
3
5
X
Y
Z
x
y
f
O
x =
xy
�
X =
2
4XYZ
3
5
カメラの幾何学的モデル(3/3)• 最も一般化したもの
– Non-square pixels à aspect ratio– Non-perpendicular image plane
• Matrix of internal parameters– 5 parameters = 5DoFs– Upper triangular
2
4xy1
3
5 /
2
4f sf x0
0 ↵f y00 0 1
3
5
2
4XYZ
3
5: skew: aspect ratio
s
↵
K =
2
4f sf x0
0 ↵f y00 0 1
3
5
2
4xy1
3
5 / K
2
4XYZ
3
5
カメラの姿勢• 空間に固定された世界(world)座標系とカメラに固定されたカメラ座標系の間の座標変換
X
Y
ZO
YC
XC
ZCOC
X = [X,Y, Z]>XC = [XC , YC , ZC ]
>
XC = RX+ t
R t:3×3回転行列 :並進ベクトル
2
664
XC
YC
ZC
1
3
775 =
R t0> 1
�2
664
XYZ1
3
775
Camera matrix• 世界座標→カメラ座標 × カメラ座標→画像座標
XC = RX+ t2
4xy1
3
5 / K
2
4XC
YC
ZC
3
5
2
4xy1
3
5 / K[R | t]
2
664
XYZ1
3
775
2
4xy1
3
5 / P
2
664
XYZ1
3
775
P = K[R | t] : camera matrix (3x4)
internal external parameters
X
Y
ZO
YC
XC
ZCOC
Rotation matrix• 回転行列の表現方法は複数ある
– 回転軸角度,Euler角,quarternion• 回転軸角度表現
– 向きが回転軸方向,長さが回転角度の3成分ベクトルで表現– ベクトルから3×3回転行列を計算(Rodrigues formula)– R, jac = cv2.Rodrigues(v) (逆変換も可能)
R = I+ sin ✓[v]⇥ + (1� cos ✓)(vv> � I)
[v]⇥ =
2
40 �v3 v2v3 0 �v1�v2 v1 0
3
5
カメラモデルの確認• 空間の立方体を画像面に投影し描画する関数 draw_cube()
import numpy, cv2
pt = numpy.array([[0,0,0], [0,0,-1], [0,1,0], [1,0,0],¥[0,1,-1],[1,0,-1], [1,1,0], [1,1,-1]],float)
ll = [[0,1],[0,2],[0,3],[1,4],[1,5],[2,4],¥[2,6],[3,5],[3,6],[4,7],[5,7],[6,7]]
def draw_cube(image, K, base, length, Rmat, tvec):#print base.shape, cubept[0:1,:].T.shape, tvec.shapefor l in ll:
ipt1 = K.dot(length*Rmat.dot(pt[l[0]:l[0]+1,:].T+base)¥+ tvec)
ipt2 = K.dot(length*Rmat.dot(pt[l[1]:l[1]+1,:].T+base)¥+ tvec)
cv2.line(image, (ipt1[0]/ipt1[2], ipt1[1]/ipt1[2]),¥(ipt2[0]/ipt2[2], ipt2[1]/ipt2[2]), (0,0,255), 3)
...
cam_model.py
カメラモデルの確認if __name__ == "__main__":
focal, z0 = 1000.0, 500.0 # z0 must be greater than 100cube_orig = numpy.array([[-0.5,-0.5,0.5]], float).T
ang = 0.0while 1:
rot1, jac1 = cv2.Rodrigues(numpy.array([[0, ang, 0]], float))rot2, jac2 = cv2.Rodrigues(numpy.array([[0.4, 0, 0]], float))ang = ang + numpy.pi/100rot = rot2.dot(rot1)trans = numpy.array([[0,0,z0]], float).T
K = numpy.array([[focal, 0.0, 320.0],¥[0.0, focal, 240.0],¥[0.0, 0.0, 1.0]], float)
image = numpy.zeros((480,640,3), dtype=numpy.uint8)draw_cube(image, K, cube_orig, 100, rot, trans)
cv2.imshow('Image', image)...
cam_model.py
レンズ• 空間の1点から発した光線の集合を画像面(イメージセンサ)上の1点に集める働き
Gaussの結像公式
理想レンズ 中心投影
現実のレンズの例
レンズ歪みX 00 = (1 + k1r
2 + k2r4 + k3r
6)X 0 + 2p1X0Y 0 + p2(r
2 + 2X 02)
Y 00 = (1 + k1r2 + k2r
4 + k3r6)Y 0 + p1(r
2 + 2Y 02) + 2p2X0Y 0
X 0 = X/Z
Y 0 = Y/Z
2
4xy1
3
5 /
2
4f sf x0
0 ↵f y00 0 1
3
5
2
4X 00
Y 00
1
3
5
X
Y
Z
x
y
f
O
x =
xy
�
X =
2
4XYZ
3
5
平面像と2次元射影変換• 平面とその像の関係は2次元射影変換で与えられる
X
Y
Zx
y
XC
YC
ZC
2
4xy1
3
5 / K[R | t]
2
664
XYZ1
3
775
2
4xy1
3
5 / K[r1 r2 t]
2
4XY1
3
5
H = K[r1 r2 t]
3×3 matrix2D projective trans.(Planar homography)
general 3D points planar points
Z = 0
[x, y]
[X,Y, 0]
カメラの回転と2次元射影変換• カメラがその場回転して得られる像どうし(あるいは無限遠方の像)は2次元射影変換で変換される
X1
Y1
Z1
Z2
X2
Y2
2
4X2
Y2
Z2
3
5 = R12
2
4X1
Y1
Z1
3
5+ t12
2
4x2
y21
3
5 / K2
2
4X2
Y2
Z2
3
5
2
4x1
y11
3
5 / K1
2
4X1
Y1
Z1
3
5
その場回転
2
4x2
y21
3
5 / K2R12K�11
2
4x1
y11
3
5
回転前回転後画像の点
[x1, y1]
[x2, y2]
Camera calibration(カメラの校正)...while 1:
stat, image = cap.read(0)
ret, centers = cv2.findCirclesGrid(image, (patw, path))cv2.drawChessboardCorners(image, (patw, path), centers, ret)
cv2.imshow('Camera', image)key = cv2.waitKey(10)
if key == 0x1b: # ESCbreak
elif key == 0x20 and ret == True:print 'Saved!'objp_list.append(objp.astype(numpy.float32))imgp_list.append(centers)
if len(objp_list) >= 3:...cv2.calibrateCamera(objp_list, imgp_list, (image.shape[1],
mage.shape[0]), K, dist)...
calib.py
”Zhang’s calibration method”
2
4xi
yi1
3
5 / P
2
664
Xi
Yi
Zi
1
3
775 , (i = 1, . . . , n)
PnP: Perspective-N-Point• 3次元座標が既知の点群(>=3)の像からカメラの姿勢を計算
– カメラの内部パラメータ(K)既知
while 1:stat, image = cap.read(0)
retval, centers = cv2.findCirclesGrid(image, (patw, path))
if retval == True:ret, rvec, tvec = cv2.solvePnP(objp, centers, K, dist)Rmat, jac = cv2.Rodrigues(rvec)cam_model.draw_cube(image, K,¥
numpy.array([[0.0,0.0,0.0]], float).T,¥3.0, Rmat, tvec)
pnp.py
P = K[R | t]
DLTによる2次元射影変換の計算
• 平面上の点 Xi とその像 xi のペアが n 点与えられたとき,平面と画像間の射影変換を求める– n >= 4
X
Y
Zx
y
XC
YC
ZC
[Xi, Yi, 0]
[xi, yi]
2
4xi
yi1
3
5 / H
2
4Xi
Yi
1
3
5 (i = 1, . . . , n)
※ DLT=Direct Linear Transformation
DLTによる2次元射影変換の計算2
4xi
yi1
3
5 / H
2
4Xi
Yi
1
3
5xi =
h00Xi + h01Yi + h02
h20Xi + h21Yi + h22
yi =h10Xi + h11Yi + h12
h20Xi + h21Yi + h22
H =
2
4h00 h01 h02
h10 h11 h12
h20 h21 h22
3
5
,
h00Xi + h01Yi + h02 � (h20Xi + h21Yi + h22)xi = 0
h10Xi + h11Yi + h12 � (h20Xi + h21Yi + h22)yi = 0
)
Xi Yi 1 0 0 0 �xiXi �xiYi �xi
0 0 0 Xi Yi 1 �yiXi �yiYi �yi
�
2
6666666666664
h00
h01
h02
h10
h11
h12
h20
h21
h22
3
7777777777775
= 0or
(Hの成分に関する線形方程式)
DLTによる2次元射影変換の計算
Ah = 0
A = UWV> V = [v0, · · · ,v8]
解(n=4の場合は厳密解・n>4の場合は最小二乗解)は特異値分解の最小特異値に対応するベクトル: h = v8
2
6666666664
X1 Y1 1 0 0 0 �x1X1 �x1Y1 �x1
0 0 0 X1 Y1 1 �y1X1 �y1Y1 �y1X2 Y2 1 0 0 0 �x2X2 �x2Y2 �x2
0 0 0 X2 Y2 1 �y2X2 �y2Y2 �y2...
Xn Yn 1 0 0 0 �xnXn �xnYn �xn
0 0 0 Xn Yn 1 �ynXn �ynYn �yn
3
7777777775
2
6666666666664
h00
h01
h02
h10
h11
h12
h20
h21
h22
3
7777777777775
= 02n
9
(Hの成分に関する線形方程式)
DLTによる2次元射影変換の計算
def calcHomography(objp, imgp):numPts = objp.shape[0]A = numpy.zeros((numPts*2, 9), float)imgp = imgp.reshape(numPts,2)for i in range(numPts):
A[i*2+0,0:2] = objp[i,0:2]A[i*2+0,2] = 1.0A[i*2+0,6:9] = -imgp[i,0]*A[i*2+0,0:3]A[i*2+1,3:5] = objp[i,0:2]A[i*2+1,5] = 1.0A[i*2+1,6:9] = -imgp[i,1]*A[i*2+1,3:6]
U, w, Vt = numpy.linalg.svd(A)return Vt[8,:].reshape(3,3)
homography.py
対応点から2次元射影変換を求める部分:
A = UWV>
h = v8
V = [v0, · · · ,v8]
2
6666666664
X1 Y1 1 0 0 0 �x1X1 �x1Y1 �x1
0 0 0 X1 Y1 1 �y1X1 �y1Y1 �y1X2 Y2 1 0 0 0 �x2X2 �x2Y2 �x2
0 0 0 X2 Y2 1 �y2X2 �y2Y2 �y2...
Xn Yn 1 0 0 0 �xnXn �xnYn �xn
0 0 0 Xn Yn 1 �ynXn �ynYn �yn
3
7777777775
2
6666666666664
h00
h01
h02
h10
h11
h12
h20
h21
h22
3
7777777777775
= 0
DLTによる2次元射影変換の計算
retval, centers = cv2.findCirclesGrid(image, (patw, path))
if retval == True:H = calcHomography(objp, centers) # H = K[r0,r1,t]Q = Q*numpy.sign(numpy.linalg.det(Q))Q = numpy.linalg.inv(K).dot(H) # Q=K^{-1}HR = Q / (numpy.linalg.norm(Q[:,0])) # Normalizet = R[:,2].reshape(3,1).copy() # Deep copyR[:,2] = numpy.cross(R[:,0],R[:,1]) # r2=r0xr1cam_model.draw_cube(image, K,¥
numpy.array([[0.0,0.0,0.0]], float).T,¥3.0, R, t)
homography.py
求めた2次元射影変換を分解してカメラ姿勢を求める:
H / K[r0 r1 t] Q ⌘ K�1
H / [r0 r1 t]
Q/|q0| = [r0 r1 t]
)) R = [r0 r1 (r0 ⇥ r1)]
K-1をかける
列ベクトルの長さを1に 3列目は1,2列目と直交
特異値分解(singular value decomposition)
• 任意の 行列 は次のように分解可能m⇥ n A
A = UWV>U>U = I V>V = I
W =
2
6664
w1
w2
. . .wn
3
7775
直交 直交行列対角
m⇥ nn⇥ n
m⇥ nn⇥ n
※ 特異値を降順にすれば分解は一意
A† = VW�1U>※ 一般化逆行列:
特異値(singular value)
=
A†A = [(A>A)�1A>]A
= VW�1U>UWV> = I
※ 非ゼロ特異値の個数 = 行列のrank
線形最小二乗1) 線形方程式
– で が full rank → 解あり:– で が full rank → 厳密解なし・最小二乗解は
– の場合一般には解は不定( の列空間内に がなければ解なし)
2) 線形方程式– 無意味な解 は考えない・ なる解を考える– が full rankでない → のゼロ特異値に対応するベクトルが解
– が full rank → の最小特異値に対応するベクトルが最小二乗解
m = n A
m > n A
m < n b
Ax = b
x = (A>A)�1A>b
A
Ax = 0x = 0 kxk2 = 1
A
A
A
A
(A : m⇥ n)
x = argminx
kAx� bk2
x = argminx
kAxk2
A† = (A>A)�1A>※ 一般化逆行列:
= (A>A)�1A>b
線形最小二乗
x = (A>A)�1A>b
A>Ax = �xdJ
dx= 2A>Ax� 2�x = 0
dJ
dx= 2A>(Ax� b) = 0
J(x) = kAx� bk2 ! min.
J(x) = kAxk2 ! min. subject to kxk2 = 1
J(x) = kAxk2 + �(k1� xk2) ! min.
)停留点:
Lagrange multiplier:
停留点: )
最小値はこの固有値問題の解: x = ek (A>Aek = �kek)
kAxk2 = e>k A>Aek = �kkekk2 = �k
最小固有値に対応するベクトルが解:
1)
2)
注)ATAの固有値=Aの特異値の二乗
レポート1• カメラをその場回転させて撮影した2枚の画像は,説明した通り2次元射影変換で関係付けられる(=片方を2次元射影変換するともう一方とぴったり重なる)– これはパノラマ画像の生成原理でもある– cv2.warpPerspective()
• この原理を使って,同様の画像複数枚を使って「超広角レンズで撮影したような画像」を合成せよ– 4点以上の画像間対応が必要
• 対応を手動で求める à 最大A評価• 自動で求める à AA
– 重複部分はblendingすること• blending手法の美しさ à 点数に反映
• pythonのコードと実行結果例• コードの内容と結果の見せ方→点数に
[x1, y1]
[x2, y2]