1. 程式人生 > 程式設計 >利用python實現AR教程

利用python實現AR教程

先了解如何利用python語言實現以平面和標記物進行姿態估計

本實驗只是先實現一個簡單的小例子。簡單來說就是先識別出影象中的參考面,再拍攝一張目標影象,將參考面頂部的3D模型投影到目標影象上。

大致步驟如下:

識別參考平面

在這一步中,我們所需要做的事就是提取參考影象和目標影象的sift特徵,然後使用RANSAC演算法穩健地估計單應性矩陣。

程式碼如下:

#計算特徵
sift.process_image('D:輸入圖片/book_frontal.JPG','im0.sift')
l0,d0 = sift.read_features_from_file('im0.sift')

sift.process_image('D:輸入圖片/book_per.JPG','im1.sift')
l1,d1 = sift.read_features_from_file('im1.sift')

#匹配特徵,並計算單應性矩陣
matches = sift.match_twosided(d0,d1)
ndx = matches.nonzero()[0]
fp = homography.make_homog(l0[ndx,:2].T)
ndx2 = [int(matches[i]) for i in ndx]
tp = homography.make_homog(l1[ndx2,:2].T)

model = homography.RansacModel()
H,inliers = homography.H_from_ransac(fp,tp,model)

由上面程式碼可得到單應性矩陣,它能夠將一幅影象中標記物的點對映到另一幅影象中的對應點。還需要建立X-Y(Z=0)三維座標系,標記物在Z=0平面上,原點在標記物的某個位置上。

從單應性推匯出從參考面座標系到目標影象座標系的轉換

在進行座標轉換之前,為了檢驗單應性矩陣結果的正確性,需要將一些三維物體放置在目標影象上,本實驗使用了一個立方體。產生立方體的程式碼如下:

def cube_points(c,wid):

  p = []
  p.append([c[0]-wid,c[1]-wid,c[2]-wid])
  p.append([c[0]-wid,c[1]+wid,c[2]-wid])
  p.append([c[0]+wid,c[2]-wid])

  p.append([c[0]-wid,c[2]+wid])
  p.append([c[0]-wid,c[2]+wid])
  p.append([c[0]+wid,c[2]+wid])

  p.append([c[0]-wid,c[2]-wid]

 return array(p).T

先計算出照相機的標定矩陣,就可以得出兩個檢視間的相對變換

程式碼如下:

#計算照相機標定矩陣,使用影象的解析度為747*1000
K = my_calibration((747,1000))

#位於邊長為0.2,Z=0平面上的三維點
box = cube_points([0,0.1],0.1)

#投影第一幅影象上底部的正方形
cam1 = camera.Camera(hstack((K,dot(K,array([[0],[0],[-1]])))))
#底部正方形上的點
box_cam1 = cam1.project(homography.make_homog(box[:,:5]))

#使用H將點變換到第二幅影象上
box_trans = homography.normalize(dot(H,box_cam1))

#從cam1和H中計算第二個照相機矩陣
cam2 = camera.Camera(dot(H,cam1.P))
A = dot(linalg.inv(K),cam2.P[:,:3])
A = array([A[:,0],A[:,1],cross(A[:,1])]).T
cam2.P[:,:3] = dot(K,A)

#使用第二個照相機矩陣投影
box_cam2 = cam2.project(homography.make_homog(box))

在影象(畫素空間)中投影我們的3D模型並繪製它。

#底部正方形的二維投影
figure()
imshow(im0)
plot(box_cam1[0,:],box_cam1[1,linewidth=3)
title('2D projection of bottom square')
axis('off')

#使用H對二維投影進行變換
figure()
imshow(im1)
plot(box_trans[0,box_trans[1,linewidth=3)
title('2D projection transfered with H')
axis('off')

#三維立方體
figure()
imshow(im1)
plot(box_cam2[0,box_cam2[1,linewidth=3)
title('3D points projected in second image')
axis('off')

實驗結果如下

什麼是AR

AR全稱Augmented Reality,意為增強現實技術。

它是一種將真實世界資訊和虛擬世界資訊“無縫”整合的新技術,是把原本在現實世界的一定時間空間範圍內很難體驗到的實體資訊(視覺資訊,聲音,味道,觸覺等),通過電腦等科學技術,模擬模擬後再疊加,將虛擬的資訊應用到真實世界,被人類感官所感知,從而達到超越現實的感官體驗。真實的環境和虛擬的物體實時地疊加到了同一個畫面或空間同時存在。

增強現實技術,不僅展現了真實世界的資訊,而且將虛擬的資訊同時顯示出來,兩種資訊相互補充、疊加。在視覺化的增強現實中,使用者利用頭盔顯示器,把真實世界與電腦圖形多重合成在一起,便可以看到真實的世界圍繞著它。

增強現實技術包含了多媒體、三維建模、實時視訊顯示及控制、多感測器融合、實時跟蹤及註冊、場景融合等新技術與新手段。增強現實提供了在一般情況下,不同於人類可以感知的資訊。

如何利用python實現AR

步驟和實現姿態估計無太大差別。由上述內容計算出照相機的位置和姿態,使用這些資訊來放置計算機影象學模型。這裡我們放置了一個紅色的小茶壺。

在執行程式碼之前,我們需要先安裝PyGame和PyOpenGL,下載連結(https://www.lfd.uci.edu/~gohlke/pythonlibs/)。

核心程式碼如下:

def set_projection_from_camera(K): 
#從照相機標定矩陣中獲得檢視

 glMatrixMode(GL_PROJECTION) 
 glLoadIdentity()
 fx = K[0,0] 
 fy = K[1,1] 
 fovy = 2*math.atan(0.5*height/fy)*180/math.pi 
 aspect = (width*fy)/(height*fx)
 near = 0.1 
 far = 100.0
 gluPerspective(fovy,aspect,near,far) 
 glViewport(0,width,height)

def set_modelview_from_camera(Rt): 
#從照相機姿態中獲取模擬檢視矩陣

 glMatrixMode(GL_MODELVIEW) 
 glLoadIdentity()
 Rx = np.array([[1,[0,-1],1,0]])
 R = Rt[:,:3] 
 U,S,V = np.linalg.svd(R) 
 R = np.dot(U,V) 
 R[0,:] = -R[0,:]
 t = Rt[:,3]
 M = np.eye(4) 
 M[:3,:3] = np.dot(R,Rx) 
 M[:3,3] = t
 M = M.T
 m = M.flatten()
 glLoadMatrixf(m)

def draw_background(imname):
#使用四邊形繪製背景影象

 bg_image = pygame.image.load(imname).convert() 
 bg_data = pygame.image.tostring(bg_image,"RGBX",1)
 glMatrixMode(GL_MODELVIEW) 
 glLoadIdentity()

 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)
 glEnable(GL_TEXTURE_2D) 
 glBindTexture(GL_TEXTURE_2D,glGenTextures(1)) 
 glTexImage2D(GL_TEXTURE_2D,GL_RGBA,height,GL_UNSIGNED_BYTE,bg_data) 
 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST) 
 glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST)
 glBegin(GL_QUADS) 
 glTexCoord2f(0.0,0.0); glVertex3f(-1.0,-1.0,-1.0) 
 glTexCoord2f(1.0,0.0); glVertex3f( 1.0,1.0); glVertex3f( 1.0,1.0,-1.0) 
 glTexCoord2f(0.0,1.0); glVertex3f(-1.0,-1.0) 
 glEnd()
 glDeleteTextures(1)

def draw_teapot(size):
#在原點處繪製紅色茶壺

 glEnable(GL_LIGHTING) 
 glEnable(GL_LIGHT0) 
 glEnable(GL_DEPTH_TEST) 
 glClear(GL_DEPTH_BUFFER_BIT)
 glMaterialfv(GL_FRONT,GL_AMBIENT,0]) 
 glMaterialfv(GL_FRONT,GL_DIFFUSE,[0.5,0.0,0.0]) 
 glMaterialfv(GL_FRONT,GL_SPECULAR,[0.7,0.6,0.0]) 
 glMaterialf(GL_FRONT,GL_SHININESS,0.25*128.0) 
 glutSolidTeapot(size)

width,height = 1000,747
def setup():
 pygame.init() 
 pygame.display.set_mode((width,height),OPENGL | DOUBLEBUF) 
 pygame.display.set_caption("OpenGL AR demo")  

實驗結果如圖:

執行程式碼遇到的錯誤及解決方案

錯誤如下:An error ocurred while starting the kernelfreeglut ERROR: Function called without first calling ‘glutInit'.

原因:經大神指點得知這個錯誤是freeglut和glut共存的緣故,它們倆定義了相同的方法,這個是動態連結庫的重疊問題,我的在ana\Lib\site-packages\OpenGL\DLLS資料夾裡面。

你需要刪除freeglut.vc15.dll這個檔案。我這是已經刪除完的樣子。

以上這篇利用python實現AR教程就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援我們。