In [1]:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
import time
import numpy.linalg as linalg
import cv2
import random
from mpl_toolkits.mplot3d import Axes3D
from multiprocessing import Queue, Process
%matplotlib notebook
orb = cv2.ORB_create()
N = 200
s = 8
random.seed(0xDEADBEEF)

In [2]:
#function for computing the fundamental matrix
def computeF(xl, xr):
    A = []
    for i in range(len(xl)):
        x = xl[i]
        x_prime = xr[i]
        #Put a row into the matrix, with formula fropm class.
        A.append([x[0]*x_prime[0], x[1]*x_prime[0], x_prime[0],
                  x[0]*x_prime[1], x[1]*x_prime[1], x_prime[1], x[0], x[1], 1])
    #Get actual fundamental matrix.
    A = np.array(A)
    _, _, V = linalg.svd(A)
    F = V[-1,:].reshape((3,3))
    U, s, V = linalg.svd(F)
    sigma = np.diag(s)
    sigma[2,2] = 0
    return np.matmul(U, np.matmul(sigma, V))
    
def ransacF(points, kp1, kp2):
    n = 0 
    currF = None
    maxInliers = 0
    # run ransac
    for n in range(N):
        sample = random.sample(points, s)
        leftPoints = [kp1[point.trainIdx].pt for point in sample]
        rightPoints = [kp2[point.queryIdx].pt for point in sample]
        # compute our F matrix
        FToTest = computeF(leftPoints, rightPoints)
        numIn = 0
        for match in points:
            p = kp1[match.trainIdx].pt
            q = kp2[match.queryIdx].pt
            if (abs(np.matmul([p[0], p[1], 1], np.matmul(FToTest, [q[0], q[1], 1])))) < .01:
                numIn += 1
        if currF is None:
            currF = FToTest
        if numIn > maxInliers:
            maxInliers = numIn
            currF = FToTest
    return currF

In [3]:
npz = np.load("calibrationM/matrices.npz")
K = npz['cameraMatrix']
K_prime = np.transpose(K)
W = np.matrix([[0, -1, 0], [1, 0, 0], [0, 0, 1]])
negW = np.transpose(W)
Winv = linalg.inv(W)

Z = np.matrix([[0, 1, 0], [-1, 0, 0], [0, 0, 0]])
trans = np.transpose
svd = linalg.svd
matmul = np.matmul
location = np.reshape((np.array([[0, 0, 0, 1]])), (4, 1))
# Compute null space of matrix A, algorithm from scipy mailing lists
def null(A, eps=1e-15):
    u, s, vh = linalg.svd(A)
    null_mask = (s <= eps)
    null_space = np.compress(null_mask, vh, axis=0)
    return trans(null_space)

def updateLoc(F, points):
    global location
    # Need to find K for the camera
    E = matmul(K, matmul(F, K_prime))
    # https://en.wikipedia.org/wiki/Essential_matrix
    U, sigma, Vt = svd(E)
    t_mat = matmul(U, matmul(Z, trans(U)))
    RPos = matmul(U, matmul(Winv, Vt))
    opt = 0
    t = null(t_mat)
    t = t/linalg.norm(t, ord=1)
    motion = np.hstack([RPos, t])
    motion = np.vstack([motion, np.array([0, 0, 0, 1])])
    location = np.matmul(motion, location)
    return None

In [ ]:
def queueFrames():
    cap = cv2.VideoCapture(0)
    i = 0
    while cap.isOpened():
        i += 1
        ret, frame = cap.read()
        if ret == False:
            queueFrames.q.put(None)
            return
        if i % 10 != 0:
            continue
        if i > 300:
            cap.release()
            queueFrames.q.put(None)
            return
        grayImg = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        queueFrames.q.put(grayImg)

In [ ]:
last = None
lastDes = None
locations = []
q = Queue()
queueFrames.q = q
now = time.time()
#start reading image frames in background
Process(target=queueFrames).start()
while True:
    grayImg = q.get(timeout=100)
    if grayImg is None:
        break
    kp, des = orb.detectAndCompute(grayImg, None)
    
    if last == None:
        last = kp
        lastDes = des
        continue
    
    # BFMatcher with default params
    bf = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True)
    matches = bf.match(lastDes, des)
    # Apply ratio test
    
    F = ransacF(matches, kp, last)
    updateLoc(F, matches)
    locations.append(location)
    del last
    del lastDes
    last = kp
    lastDes = des
    
after = time.time()
print("time elapsed: {0}".format(after - now))
fig = plt.figure()
ax = fig.gca(projection='3d')
ax.plot([np.reshape(location, (4,1))[0,0] for location in locations],
       [np.reshape(location, (4,1))[1,0] for location in locations],
       [np.reshape(location, (4,1))[2,0] for location in locations], label="locations")
plt.show()

In [ ]:


In [ ]: