SFMedu有python版本,但是有一些問題,我們把他解決能運行,但是我們還是會用matlab版本:
https://github.com/aferral/Structure-from-motion-python
python2
sudo pip install opencv-python==3.3.0.10
sudo pip install opencv-contrib-python==3.3.0.10
sudo pip install plyfile
修改代碼:
graph.py
def triangulateGraph(graph,imagesize):
newGraph = graph
n = newGraph.str.shape[0]
X = np.zeros((n,4))
colIms = np.array([imagesize[1], imagesize[0]]).reshape((2, 1))
imsize = colIms.repeat(len(graph.frames), axis=1)
for i in range(n):
validCamera = np.where(graph.ObsIdx[i] != -1)[0]
P = np.zeros((3,4,validCamera.shape[0]))
x= np.zeros((validCamera.shape[0],2))
cnt=0
#Consigue los puntos en el plano de la camara y la matriz de proyeccion
for ind in validCamera:
temp = int(newGraph.ObsIdx[i][ind])
x[cnt,:] = newGraph.obsVal[temp,:]
P[:,:,cnt] = np.dot(newGraph.focal,newGraph.mot[:,:,ind])
cnt+=1
X[i,:] = vgg_X_from_xP_nonlin(x,P,imsize,X=None)
allscales = X[:,3].reshape((n, 1))
newGraph.str = X[:,0:3] / np.hstack([allscales,allscales,allscales])
return newGraph
mergeGraph.py
def mergeG(gA, gB):
# Como ejemplo sean frames A 1 2 y B 2 3
# los frarmes son las camaras o fotos
# Primero se calculan frames que hacen overlap
comFram = list(set(gA.frames).intersection(gB.frames))
# Luego las que son propias de A y las propias de B (en ej A1 B3)
propB = list(set(gB.frames).difference(gA.frames))
indpB = [gB.frames.index(a) for a in propB]
# Si no hay comunes retorna error
# Si las propias de B son ninguna tira error
if len(comFram) == 0:
raise Exception("Comunes vacio ")
if len(propB) == 0:
raise Exception("No hay propias de B")
# Crear grafo mezclca igual a grafo A
merged = deepcopy(gA)
# Para el primer overlap (pueden existir muchos)
firstOv = comFram[0]
# Transforma B.mot b.str al mismo sistema de cordenadas de A
commonA = gA.frames.index(firstOv)
commonB = gB.frames.index(firstOv)
# Consigue transformada rtB
transf = catRt(invertRt(gA.mot[:, :, commonA]), gB.mot[:, :, commonB])
gB.str = transformPtsByRt(np.transpose(gB.str), transf, False) # Aplicar a str B
# Mot ahora es la concadenacion de mot y el inverso RtB
for i in range(len(gB.frames)):
gB.mot[:, :, i] = catRt(gB.mot[:, :, i], invertRt(transf))
merged.frames = list(set(gA.frames).union(set(gB.frames)))
newMot = np.zeros((3, 4, len(merged.frames)))
newMot[:, :, np.array(range(len(gA.frames)))] = gA.mot
newMot[:, :, np.array(range(len(gA.frames), len(merged.frames)))] = gB.mot[:, :, indpB]
merged.mot = newMot
# Agrega frames a grafico
# Ahora caso common frames mas de una
for fr in comFram:
cA = gA.frames.index(fr)
cB = gB.frames.index(fr)
obsIndA = gA.ObsIdx[:, cA][gA.ObsIdx[:, cA] != -1]
obsIndA = gA.ObsIdx[:, cA]
valA = gA.obsVal[obsIndA.astype(np.int), :]
obsIndB = gB.ObsIdx[:, cB][gB.ObsIdx[:, cB] != -1]
obsIndB = gB.ObsIdx[:, cB]
valB = gB.obsVal[obsIndB.astype(np.int), :]
iA = findInterIndexA(valA, valB)[0]
comunes = valA[iA]
iB = np.array([getIndexOfRow(valB, row)[0][0] for row in comunes])
iA,iB = deleteRepeated(iA.tolist(), iB.tolist(),valA,valB)
iA = np.array(iA)
iB = np.array(iB)
for i in range(iA.shape[0]):
# idA = obsIndA[iA[i]]
# idB = obsIndB[iB[i]]
for j in range(len(indpB)):
bObbsIdx = gB.ObsIdx[iB[i], indpB[j]]
# Agrego un elemento a obsVal y a ObsIdx
bObbsIdx = int(bObbsIdx)
merged.obsVal = np.vstack([merged.obsVal, gB.obsVal[bObbsIdx, :]])
while merged.ObsIdx.shape[1] < (len(gA.frames) + j + 1):
merged.ObsIdx = np.hstack([merged.ObsIdx, minus1((merged.ObsIdx.shape[0], 1))])
merged.ObsIdx[iA[i], len(gA.frames) + j] = merged.obsVal.shape[0]-1
# Calcula set diference
diferentesB = setDif(valB, valA)
idB = np.array([getIndexOfRow(valB, row)[0][0] for row in diferentesB])
for i in range(idB.shape[0]):
bObbsIdx = gB.ObsIdx[idB[i], cB]
bObbsIdx = int(bObbsIdx)
merged.obsVal = np.vstack([merged.obsVal, gB.obsVal[bObbsIdx, :]])
merged.ObsIdx = np.vstack([merged.ObsIdx, minus1((1,merged.ObsIdx.shape[1]))])
merged.ObsIdx[merged.ObsIdx.shape[0]-1, cA] = merged.obsVal.shape[0]-1
merged.str = np.vstack([ merged.str , gB.str[:,idB[i]].reshape((1,3)) ])
for j in range(len(indpB)):
bObbsIdx = gB.ObsIdx[idB[i], indpB[j]]
bObbsIdx = int(bObbsIdx)
merged.obsVal = np.vstack([merged.obsVal, gB.obsVal[bObbsIdx, :]])
while merged.ObsIdx.shape[1] < (len(gA.frames) + j + 1):
merged.ObsIdx = np.hstack([merged.ObsIdx, minus1((merged.ObsIdx.shape[0], 1))])
merged.ObsIdx[-1, len(gA.frames) + j] = merged.obsVal.shape[0]-1
#Revisa si quedo alguna columna sin algun valor
#Selecciona en ObsIdx los frames comunes y dif en Gb
#Asegurate que para ningun punto se cumpla A and B
#Siendo A = En columnas comunes todas tienen el valor de -1
#Siendo B = En columnas dif la suma de los valores mayores que -1 es mayor que 0
newB = np.zeros((1,len(gB.frames)))
newB[:,np.array(indpB)] = 1
A= (np.sum( gB.ObsIdx[:,np.bitwise_not(newB.astype(np.bool)).astype(int)[0]], axis=1) < 0 )
B= (np.sum( gB.ObsIdx[:,newB[0].astype(np.int)], axis=1) > 0 )
assert(not np.any(np.bitwise_and(A,B)))
return merged
進入正式流程:
http://3dvision.princeton.edu/courses/SFMedu/slides.pptx
5點算法
動態估計焦距
成對相鄰匹配之外
三焦點張量
使它對於不同的圖像輸入穩定
使它適用於視頻輸入
使它工作更快
檢查所有理論並修復所有錯誤
關於F矩陣和E矩陣:
https://blog.csdn.net/try_again_later/article/details/88655563
自由度爲7
直接線性變換算法
代數誤差與幾何誤差
由(非線性)最小二乘求解器(例如Ceres)求解
4個匹配對,8個點
RANSAC估計基本矩陣
關於計算機視覺中的最優化問題:
http://cmp.felk.cvut.cz/old_pages/mini/