Python实现AR增强现实:从姿态估计到3D模型投影实战
本文详解如何利用Python实现增强现实(AR)基础功能。通过SIFT算法提取图像特征并计算单应性矩阵,完成参考平面到目标图像的映射。结合相机标定与RANSAC算法推导空间变换,最终使用PyOpenGL将3D立方体或茶壶模型实时投影叠加至真实场景,并解决常见依赖库冲突问题。
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平面,原点置于标记物的特定位置。
坐标系转换与3D模型投影验证
从单应性矩阵推导参考面坐标系至目标图像坐标系的转换关系
在实施坐标转换前,为验证单应性矩阵结果的准确性,需在目标图像上放置若干三维物体,本实验选用立方体作为验证对象。生成该立方体的代码示例如下:
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[1]+wid, c[2]-wid])
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[1]-wid, c[2]+wid])
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[1]-wid, c[2]+wid])
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[1]+wid, c[2]+wid])
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[1]+wid, c[2]+wid])
p.append([c[0]+wid, c[1]-wid, c[2]+wid])
p.append([c[0]+wid, c[1]-wid, c[2]-wid]
return array(p).T
计算出相机标定矩阵后,即可得出两个视图间的相对变换关系。
相关代码如下:
#计算照相机标定矩阵,使用图像的分辨率为747*1000
K = my_calibration((747, 1000))
#位于边长为0.2,Z=0平面上的三维点
box = cube_points([0, 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[:, 0], 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
AR全称为Augmented Reality,即增强现实技术。
该技术是一种将真实世界信息与虚拟世界信息“无缝”集成的新技术。它通过计算机科学技术,对现实世界中难以直接体验的实体信息(如视觉、声音、味道、触觉等)进行模拟仿真,再将虚拟信息叠加到真实世界中,通过人类感官感知,从而获得超越现实的体验。真实环境与虚拟物体在同一画面或空间中实时共存。
增强现实技术不仅展示真实世界信息,还同时显示虚拟信息,两者相互补充、叠加。在视觉化增强现实中,用户利用头盔显示器,将真实世界与计算机图形多重合成,即可看到被虚拟物体环绕的真实世界。
增强现实技术融合了多媒体、三维建模、实时视频显示及控制、多传感器融合、实时跟踪及注册、场景融合等多项新技术与新手段,提供了常规情况下人类无法直接感知的信息。
Python实现AR的完整流程与报错处理
如何利用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,0,width,height)
def set_modelview_from_camera(Rt):
#从照相机姿态中获取模拟视图矩阵
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
Rx = np.array([[1,0,0],[0,0,-1],[0,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,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)
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.5,0.0,0.0,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)
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的完整教程,希望能为读者提供参考,并欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









