计算机视觉编程——增强现实基础
文章目錄
- 增強(qiáng)現(xiàn)實(shí)
- 1 PyGame和PyOpenGL
- 2 從照相機(jī)矩陣到OpenGL格式
- 3 在圖像中放置虛擬物體
- 4 綜合集成
增強(qiáng)現(xiàn)實(shí)
增強(qiáng)現(xiàn)實(shí)是將物體和相應(yīng)信息放置在圖像數(shù)據(jù)上的一系列操作的總稱。
1 PyGame和PyOpenGL
PyGame是非常流行的游戲開(kāi)發(fā)工具包,可以簡(jiǎn)單地處理顯示窗口、輸入設(shè)備、事件,以及其他內(nèi)容。
PyOpenGL是OpenGL圖形編程的Python綁定接口,可以安裝在幾乎所有的系統(tǒng)上并且具有很好的圖形性能。
我們使用OpenGL將一個(gè)三維模型放置在一個(gè)場(chǎng)景中。為了使用PyGame和PyOpenGL工具包來(lái)完成,需要在腳本的開(kāi)始部分載入下邊的命令:
from OpenGL.GL import * from OpenGL.GLU import * import pygame, pygame.image from pygame.locals import *在這里主要使用OpenGL中的兩個(gè)部分:GL部分包含所有以"gl"開(kāi)頭的函數(shù);GLU部分是OpenGL的實(shí)用函數(shù)庫(kù),里邊包含一些高層的函數(shù),我們主要使用它完成設(shè)置照相機(jī)投影。
pygame部分用來(lái)設(shè)置窗口和事件控制;其中pygame.image用來(lái)載入圖像和創(chuàng)建OpenGL的紋理,pygame.locals用來(lái)設(shè)置OpenGL的顯示區(qū)域。
2 從照相機(jī)矩陣到OpenGL格式
OpenGL使用44的矩陣表示變換,與34的照相機(jī)矩陣略有差別。但是,照相機(jī)與場(chǎng)景的變換分成了兩個(gè)矩陣,GL_PROJECTION矩陣和GL_MODLEVIEW矩陣。前者處理圖像成像的性質(zhì),等價(jià)于內(nèi)標(biāo)定矩陣K;后者處理物體和照相機(jī)之間的三維變換關(guān)系,對(duì)應(yīng)于照相機(jī)矩陣中的R和t部分。
下面的函數(shù)將照相機(jī)參數(shù)轉(zhuǎn)換為OpenGL中的投影矩陣:
def set_projection_from_camera(K):glMatrixMode(GL_PROJECTION)glLoadIdentity()fx = K[0, 0]fy = K[1, 1]fovy = 2 * arctan(0.5 * height / fy) * 180 / piaspect = (width * fy) / (height * fx)near = 0.1far = 100.0gluPerspective(fovy, aspect, near, far)glViewport(0, 0, width, height)在上述代碼中,函數(shù)glMatrixMode()將工作矩陣設(shè)置為GL_PROJECTION,接下來(lái)的命令會(huì)修改這個(gè)矩陣。然后glLoadIdentity()函數(shù)將該矩陣設(shè)置為單位矩陣,根據(jù)圖像高度、照相機(jī)的焦距以及縱橫比,計(jì)算出視圖中的垂直場(chǎng)。OpenGL的投影同樣具有近距離和遠(yuǎn)距離的裁剪平面來(lái)限制場(chǎng)景拍攝的深度范圍。
使用GLU的使用函數(shù)gluPerspective()設(shè)置投影矩陣,將整個(gè)圖像定義為視圖部分。
使用下面的函數(shù)實(shí)現(xiàn)如何獲得移除標(biāo)定矩陣后的3*4針孔照相機(jī)矩陣,并創(chuàng)建一個(gè)模擬視圖:
def set_modelview_from_camera(Rt):glMatrixModel(GL_MODELVIEW)glLoadIdentity()Rx = array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])R = Rt[:, :3]U, S, V = linalg.svd(R)R = dot(U, V)R[0, :] = -R[0, :]t = Rt[:, 3]M = eye(4)M[:3, :3] = dot(R, Rx)M[:3, 3] = tM = M.Tm = M.flatten()glLoadMatrixf(m)上面的函數(shù)中,首先切換到GL_MODELVIEW矩陣,然后將該矩陣重置。創(chuàng)建一個(gè)90度的旋轉(zhuǎn)矩陣,由于估計(jì)照相機(jī)矩陣時(shí),可能會(huì)有錯(cuò)誤或者噪聲干擾,所以要確保照相機(jī)矩陣的旋轉(zhuǎn)部分確實(shí)是一個(gè)旋轉(zhuǎn)矩陣。將模擬視圖矩陣M設(shè)置成為旋轉(zhuǎn)矩陣的乘積,glLoadMatrixf()函數(shù)通過(guò)輸入?yún)?shù)為按列排列的16個(gè)數(shù)值數(shù)組,來(lái)設(shè)置模擬視圖。將M矩陣轉(zhuǎn)置,然后壓平并輸入glLoadMatrixf()函數(shù)。
3 在圖像中放置虛擬物體
我們首先需要將圖像作為背景添加進(jìn)來(lái),可以通過(guò)創(chuàng)建一個(gè)四邊形的方式來(lái)完成,該四邊形為整個(gè)視圖。下邊的函數(shù)可以載入一幅圖像,然后將其轉(zhuǎn)換成一個(gè)OpenGL紋理,并將該紋理放置在四邊形上:
def draw_background(imname):bg_image = pygame.image.load(imname).convert()bg_data = pygame.image.tostring(bg_image, "RGBX", 1)glMatrixMode(GL_MODEVIEW)glLoadIdentity()glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)glEnable(GL_TEXTURE_2D)glBindTexture(GL_TEXTURE_2D, glGenTextures(1))glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, 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, -1.0)glTexCoord2f(1.0, 1.0);glVertex3f(1.0, 1.0, -1.0)glTexCoord2f(0.0, 1.0);glVertex3f(-1.0, 1.0, -1.0)glEnd()glDeleteTextures(1)該函數(shù)首先使用PyGame中的一些函數(shù)來(lái)載入一幅圖像,將其序列化為能夠在PyOpenGL中使用的原始字符串表示。然后重置模擬視圖,清除顏色和深度緩存。接下來(lái)綁定這個(gè)紋理,使其能夠在四邊形和指定插值中使用。
使用下邊的命令產(chǎn)生一個(gè)相對(duì)大小為size的茶壺模型:
from OpenGL.GLUT import *glutSolidTeapot(size)使用下邊的函數(shù)設(shè)置其顏色和其他特性:
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, 0, 0, 0])glMaterialfv(GL_FRONT, GL_DIFFUSE, [0.0, 0.5, 0.5, 0.0])glMaterialfv(GL_FRONT, GL_SPECULAR, [0.7, 0.6, 0.6, 0.0])glMaterialf(GL_FRONT, GL_SHININESS, 0.25 * 128.0)glutSolidTeapot(size)4 綜合集成
使用下邊的腳本命令完成最后的操作:
width, height = 1000, 747def setup():"""設(shè)置窗口和pygame環(huán)境"""pygame.init()pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)pygame.display.set_caption("OpenGL AR demo")sift.process_image('book_frontal.jpg', 'im0.sift') l0, d0 = sift.read_features_from_file('im0.sift')sift.process_image('book_perspective.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)K = my_calibration((747,1000)) cam1 = camera.Camera(hstack((K, dot(K, array([[0], [0], [-1]]))))) box = cube_points([0, 0, 0.1], 0.1) box_cam1 = cam1.project(homography.make_homog(box[:, :5])) box_trans = homography.normalize(dot(H, box_cam1)) cam2 = camera.Camera(dot(H, cam1.P)) A = dot(linalg.inv(K), cam2.P[:, :3]) A = array([A[:, 0], A[:, 1], cross(A[:, 0], A[:, 1])]).T cam2.P[:, :3] = dot(K, A) box_cam2 = cam2.project(my_homography.make_homog(box))Rt = dot(linalg.inv(K), cam2.P)with open('ar_camera.pkl', 'r') as f:K = pickle.load(f)Rt = pickle.load(f)setup() draw_background('book_perspective.bmp') set_projection_from_camera(K) set_modelview_from_camera(Rt) draw_teapot(0.02)while True:for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit() pygame.display.flip()setup()函數(shù)會(huì)初始化PyGame,將窗口設(shè)置為圖像大小,繪制圖像區(qū)域?yàn)閮杀兜腛penGL窗口緩存大小,載入背景使其與窗口相符,然后設(shè)定照相機(jī)和模擬視圖矩陣,最后在正確的位置繪制出茶壺。顯示的結(jié)果如下圖所示:
總結(jié)
以上是生活随笔為你收集整理的计算机视觉编程——增强现实基础的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 计算机视觉编程——照相机模型
- 下一篇: 计算机视觉编程——多视图几何