前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >A simple augmented reality application

A simple augmented reality application

作者头像
caoqi95
发布2019-10-18 01:59:36
8760
发布2019-10-18 01:59:36
举报
文章被收录于专栏:caoqi95的记录日志

主要理解代码 + 记录解决报错问题,具体内容有空补上。

相机矩阵转换成 OpenGL 格式

在 OpenGL 中主要使用 4x4 矩阵来表示转换,这个和 3x4 的相机矩阵不同。然而,OpenGL 中的 GL_PROJECTIONGL_MODELVIEW 是将相机矩阵分开来表示。其中 GL_PROJECTION 表示相机的内参数 K 矩阵;GL_MODELVIEW 表示物体和相机之间的转换关系,可以粗略地表示为 Rt 矩阵。

代码如下所示, K 表示校准后的相机内参数矩阵。

代码语言:javascript
复制
from OpenGL.GL import *
from OpenGL.GLU import *
import pygame, pygame.image
from pygame.locals import *
from OpenGL.GLUT import *
import numpy as np
from scipy import linalg
import sys


def set_projection_from_camera(K):
    
    """
    Set view from a camera calibration matrix.
    """
    
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    
    fx = K[0, 0]
    fy = K[1, 1]
    # 计算以度为单位的垂直视野
    fovy = 2*np.arctan(0.5*height/fy)*180/np.pi
    # 纵横比
    aspect = (width*fy)/(height*fx)
    
    # define the near and far clipping planes
    near = 0.1
    far = 100.0
    
    # set perspective
    gluPerspective(fovy, aspect, near, far)
    glViewport(0, 0, width, height)

P = K[R|t],所以 Rt = PK-1 得到。Rt 为下面代码的输入:

代码语言:javascript
复制
def set_modelview_from_camera(Rt):
    
    """
    Set the model view matrix from camera pose.
    """
    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    
    # rotate teapot 90 deg around x-axis so that z-axis is up
    Rx = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])
    
    # set rotation to best approximation
    R = Rt[:, :3]
    U, S, V = linalg.svd(R)
    R = np.dot(U, V)
    R[0, :] = -R[0, :] # change sign of x-axis
    
    # set translation
    t = Rt[:, 3]
    
    # set 4*4 model view matrix
    M = np.eye(4)
    M[:3, :3] = np.dot(R, Rx)
    M[:3, 3] = t
    
    # transpose and flatten to grt column order
    M = M.T
    m = M.flatten()
    
    # replace model view with new matrix
    glLoadMatrixf(m)
将虚拟物体投放到图片上
代码语言:javascript
复制
def draw_background(imname):
    
    """
    Draw background image using a quadrilateral.
    """
    
    # load backgound image (should be .bmp) to OpenGL texture
    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)
    
    # bind the texture
    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)
    
    # create quad to fill the whole window
    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()
    
    # clear the texture
    glDeleteTextures(1)

def draw_teapot(size):
    
    """
    Draw a red teapot at the origin.
    """
    glEnable(GL_LIGHTING) 
    glEnable(GL_LIGHT0) 
    glEnable(GL_DEPTH_TEST) 
    glClear(GL_DEPTH_BUFFER_BIT)
    
    # draw red teapot
    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)

主代码:

代码语言:javascript
复制
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import pygame, pygame.image
from pygame.locals import *
import pickle

width, height = 1000, 747

def setup():
    
    """
    Setup window and pygame environment.
    """
    
    pygame.init()
    pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)
    pygame.display.set_caption('OpenGL AR demo')
    
# load camera data
with open('ar_camera.pkl', 'rb') 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.05)

pygame.display.flip()
while True:
  for event in pygame.event.get():
    if event.type == pygame.QUIT:
       sys.exit()
       pygame.quit()
pygame.display.flip()

结果:

相关报错解决
  • 报错一:
代码语言:javascript
复制
OpenGL.error.NullFunctionError: 
Attempt to call an undefined function glutSolidTeapot, check for bool(glutSolidTeapot) before calling

解决方法:

  1. 卸载用 pip 安装的 PyOpenGL
  2. https://www.lfd.uci.edu/~gohlke/pythonlibs/ 下载对应 Python 版本的 .whl 文件;
  3. 重新安装:pip install xxxx.whl
  • 报错二
代码语言:javascript
复制
freeglut  ERROR:  Function <glutSolidTeapot> called without first calling 'glutInit'.

这个错误是freeglut和glut共存的缘故,它们俩定义了相同的方法,这个是动态链接库的重叠问题,找到你使用的python路径下\OpenGL\DLLS中的glut64.vcX.dll文件,将其余文件删除就可以了。

参考

[1]. Programming Computer Vision with Python

[2]. python照相机模型与增强现实

[3]. 【计算机视觉】照相机模型与增强现实

[4]. PyOpenGL Installation Notes for Windows

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.10.16 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 相机矩阵转换成 OpenGL 格式
  • 将虚拟物体投放到图片上
  • 相关报错解决
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档