Created
November 10, 2017 11:28
-
-
Save se7oluti0n/ca4ac8924729dd6b46d07e7ecab55d10 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import numpy as np" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def readPoints(filename):\n", | |
" points = []\n", | |
" with open(filename, 'r') as f:\n", | |
" for line in f.readlines():\n", | |
" points.append([float(n) for n in line.split()])\n", | |
" return np.asarray(points)\n", | |
" " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"points3d = readPoints('input/pts3d.txt')\n", | |
"points3d_norm = readPoints('input/pts3d-norm.txt')\n", | |
"points2d = readPoints('input/pts2d-pic_a.txt')\n", | |
"points2d_norm = readPoints('input/pts2d-norm-pic_a.txt')\n", | |
"points2d_b = readPoints('input/pts2d-pic_b.txt')" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def svdSolver(pts2d, pts3d):\n", | |
" n_points = pts2d.shape[0]\n", | |
" \n", | |
" a_matrix = np.zeros((n_points * 2, 12))\n", | |
" \n", | |
" u, v = pts2d[:, 0], pts2d[:, 1]\n", | |
" x, y, z = pts3d[:, 0], pts3d[:, 1], pts3d[:, 2]\n", | |
" \n", | |
" ones = np.ones(n_points)\n", | |
" zeros = np.zeros(n_points)\n", | |
" \n", | |
" a_matrix[::2, :] = np.column_stack((x, y, z, ones, zeros, zeros, zeros, zeros, -u*x, -u*y, -u*z, -u))\n", | |
" a_matrix[1::2, :] = np.column_stack((zeros, zeros, zeros, zeros, x, y, z, ones, -v*x, -v*y, -v*z, -v))\n", | |
" \n", | |
" _,_,V = np.linalg.svd(a_matrix, full_matrices=True)\n", | |
" M = V.T[:, -1]\n", | |
" M = M.reshape((3, 4))\n", | |
" \n", | |
" pts3d_homo = np.row_stack((pts3d.T, ones))\n", | |
" pts2d_homo = M.dot(pts3d_homo)\n", | |
" pts2d_proj = pts2d_homo / pts2d_homo[2, :]\n", | |
" \n", | |
" res = np.sqrt(np.sum((pts2d - pts2d_proj.T[:, :2]) ** 2))\n", | |
" return M, res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"M, res = svdSolver(points2d_norm, points3d_norm)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"M" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def computeResidual(pts2d, pts3d, M):\n", | |
" ones = np.ones(len(pts2d))\n", | |
" pts3d_homo = np.row_stack((pts3d.T, ones))\n", | |
" pts2d_homo = M.dot(pts3d_homo)\n", | |
" pts2d_proj = pts2d_homo / pts2d_homo[2, :]\n", | |
" \n", | |
" res = np.sqrt(np.sum((pts2d - pts2d_proj.T[:, :2]) ** 2))\n", | |
" return res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def leastSquareSolver(pts2d, pts3d):\n", | |
" num_points = pts2d.shape[0]\n", | |
" a_matrix = np.zeros((num_points * 2, 11))\n", | |
" u, v = pts2d[:, 0], pts2d[:, 1]\n", | |
" x, y, z = pts3d[:, 0], pts3d[:, 1], pts3d[:, 2]\n", | |
" \n", | |
" ones = np.ones(num_points)\n", | |
" zeros = np.zeros(num_points)\n", | |
" a_matrix[::2, :] = np.column_stack((x, y, z, ones, zeros, zeros, zeros, zeros, -u*x, -u*y, -u*z))\n", | |
" a_matrix[1::2, :] = np.column_stack((zeros, zeros, zeros, zeros, x, y, z, ones, -v*x, -v*y, -v*z))\n", | |
" \n", | |
" b = np.zeros(2 * num_points)\n", | |
" b[::2] = u\n", | |
" b[1::2] = v\n", | |
"\n", | |
" M,res,_,_ = np.linalg.lstsq(a_matrix, b)\n", | |
" M = np.append(M, 1)\n", | |
" M = M.reshape((3,4))\n", | |
" return M, res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"M, res = leastSquareSolver(points2d_norm, points3d_norm)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"M" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def randomSolver(pts2d, pts3d, samples=8, iterations=10, solver=leastSquareSolver):\n", | |
" \n", | |
" indices = np.arange(len(pts2d))\n", | |
" best_res = np.inf\n", | |
" bestM = None\n", | |
" for i in range(iterations):\n", | |
" np.random.shuffle(indices)\n", | |
" train_indices = indices[:samples]\n", | |
" val_indices = indices[samples: samples + 4]\n", | |
" \n", | |
" M, _ = solver(pts2d[train_indices], pts3d[train_indices])\n", | |
" res = computeResidual(pts2d[val_indices], pts3d[val_indices], M)\n", | |
" if res < best_res:\n", | |
" bestM = M\n", | |
" best_res = res\n", | |
" return bestM, best_res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"M, res = randomSolver(points2d, points3d, 16, 50)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Mnormlized, res = randomSolver(points2d_norm, points3d_norm, 16, 50)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Q = Mnormlized[:,:3]\n", | |
"m4 = Mnormlized[:, 3]" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"-np.linalg.inv(Q).dot(m4)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Fundamental Matrix" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def leastSquareFSolver(ptsLeft, ptsRight):\n", | |
" num_points = ptsLeft.shape[0]\n", | |
" a_matrix = np.zeros((num_points, 8))\n", | |
" u, v = ptsLeft[:, 0], ptsLeft[:, 1]\n", | |
" ur, vr = ptsRight[:, 0], ptsRight[:, 1]\n", | |
" \n", | |
" ones = np.ones(num_points)\n", | |
" a_matrix = np.column_stack((ur*u, ur*v, ur, vr*u, vr*v, vr, u, v))\n", | |
" \n", | |
" b = -ones\n", | |
"\n", | |
" F,res,_,_ = np.linalg.lstsq(a_matrix, b)\n", | |
" F = np.append(F, 1)\n", | |
" F = F.reshape((3,3))\n", | |
" return F, res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"F, res = leastSquareFSolver(points2d_b, points2d)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"res" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"F" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def calculateFdash(F):\n", | |
" U,D,V = np.linalg.svd(F, full_matrices=True)\n", | |
" D[np.argmin(D)] = 0\n", | |
" return np.dot(U, np.dot(np.diag(D), V))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Fdash = calculateFdash(F)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"Fdash" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"import cv2\n", | |
"import matplotlib.pyplot as plt\n", | |
"%matplotlib inline" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def calculateEpipolarLine(imgA, pointsA, pointsB, F):\n", | |
" rows, cols, _ = imgA.shape\n", | |
" pUL = np.asarray([0,0,1])\n", | |
" pBL = np.asarray([rows-1, 0,1])\n", | |
" \n", | |
" pUR = np.asarray([0, cols-1, 1])\n", | |
" pBR = np.asarray([rows-1, cols-1, 1])\n", | |
" \n", | |
" lL = np.cross(pUL, pBL)\n", | |
" lR = np.cross(pUR, pBR)\n", | |
" \n", | |
" lines = []\n", | |
" for pA, pB in zip(pointsA, pointsB):\n", | |
" la = F.dot(np.append(pB, 1).T)\n", | |
" p1 = np.cross(la, lL)\n", | |
" p2 = np.cross(la, lR)\n", | |
" \n", | |
" p1 = (p1[:2] / p1[2]).astype(np.int)\n", | |
" p2 = (p2[:2] / p2[2]).astype(np.int)\n", | |
" lines.append((p1, p2))\n", | |
" return lines " | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"def drawEpipolarLines(fn, point, others, Fdash):\n", | |
" img = cv2.imread(fn)\n", | |
" lines = calculateEpipolarLine(img, point, others, Fdash)\n", | |
"\n", | |
" for p1, p2 in lines:\n", | |
" cv2.line(img, (int(p1[0]), int(p1[1])), (int(p2[0]), int(p2[1])), color=(0, 0, 0))\n", | |
" img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)\n", | |
" plt.imshow(img)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"drawEpipolarLines('input/pic_a.jpg', points2d, points2d_b, Fdash)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [ | |
"drawEpipolarLines('input/pic_b.jpg', points2d_b, points2d, Fdash.T)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": {}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Python 2", | |
"language": "python", | |
"name": "python2" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 2 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython2", | |
"version": "2.7.14" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 2 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment