Python计算机视觉——照相机模型与增强现实

文章目录

  • Python计算机视觉——照相机模型与增强现实
    • 1 针孔照相机模型
      • 1.1 照相机矩阵
      • 1.2 三维点的投影
      • 1.3 照相机矩阵的分解
      • 1.4 计算照相机中心
    • 2 照相机标定
    • 3 以平面和标记物进行姿态估计
    • 4 增强现实
      • 4.1 PyGame和PyOpenGL
      • 4.2 在图像中放置虚拟物体

1 针孔照相机模型

针孔照相机模型(有时称为射影照相机模型)是计算机视觉中广泛使用的照相机模 型。对于大多数应用来说,针孔照相机模型简单,并且具有足够的精确度。在针孔照相机模型中,在光线投影到图像平面之前,从唯一一个点经过,也就是 照相机中心 C。如下图所示,图像点 x 是由图像平面与连接三维点 X 和照相机中心 C 的直线相 交而成的。虚线表示该照相机的光学坐标轴。

在针孔照相机中,三维点 X 投影为图像点 x(两个点都是用齐次坐标表示的),如下 所示:
λx=PXλx=PX λx=PX
3×4 的矩阵 P 为照相机矩阵(或投影矩阵)。注意,在齐次坐标系中,三维 点 X 的坐标由 4 个元素组成,X=[X, Y, Z, W]。这里的标量 λ 是三维点的逆深度(深度的倒数)。如果我们打算在齐次坐标中将最后一个数值归一化为 1,那么就会使用到它。

1.1 照相机矩阵

照相机矩阵可以分解为:
P=K[R∣t]P=K[R|t] P=K[R∣t]
其中,R 是描述照相机方向的旋转矩阵,t 是描述照相机中心位置的三维平移向量, 内标定矩阵 K描述照相机的投影性质。标定矩阵仅和照相机自身的情况相关,通常情况下可以写成:
K=[αfscx0fcy001]\boldsymbol{K}=\left[\begin{array}{ccc} \alpha f & s & c_{x} \\ 0 & f & c_{y} \\ 0 & 0 & 1 \end{array}\right] K=⎣⎡​αf00​sf0​cx​cy​1​⎦⎤​
既然K的size为3×3,则R的size为3×n,增广矩阵[R|t]必然是3×(n+1)图像平面和照相机中心间的距离为焦距 f。当像素数组在传感器上偏斜的时候,需要 用到倾斜参数 s。在大多数情况下,s 可以设置成 0。也就是说:
K=[fx0cx0fycy001],其中fx=αfy\boldsymbol{K}=\left[\begin{array}{ccc} f_{x} & 0 & c_{x} \\ 0 & f_{y} & c_{y} \\ 0 & 0 & 1 \end{array}\right],其中f_{x}=αf_{y} K=⎣⎡​fx​00​0fy​0​cx​cy​1​⎦⎤​,其中fx​=αfy​
纵横比例参数 α 是在像素元素非正方形的情况下使用的。通常情况下,我们可以默 认设置 α=1。经过这些假设,标定矩阵变为:
K=[f0cx0fcy001]\boldsymbol{K}=\left[\begin{array}{lll} f & 0 & c_{x} \\ 0 & f & c_{y} \\ 0 & 0 & 1 \end{array}\right] K=⎣⎡​f00​0f0​cx​cy​1​⎦⎤​
除焦距之外,标定矩阵中剩余的唯一参数为光心(有时称主点)的坐标 c=[cx,cy]c=[c_{x} ,c_{y}]c=[cx​,cy​],也就是光线坐标轴和图像平面的交点。因为光心通常在图像的中心,并且图像的坐 标是从左上角开始计算的,所以光心的坐标常接近于图像宽度和高度的一半。特别强调一点,在这个例子中,唯一未知的变量是焦距 f。

1.2 三维点的投影

下面的例子展示如何将三维中的点投影到图像视图中.使用的数据集在这下载:Visual Geometry Group - University of Oxford。使用其中的 house.p3d三维模型做实验,首先可以看看这模型长啥样,其实就是几百个三维点组成的矩阵,所以shape为[672,3],具体代码和shape如下:

import camera
import numpy as np
import matplotlib.pyplot as plt# shape = [3, 672]
points = np.loadtxt('./3d/house.p3d').T
# shape = [4, 672]
points = np.vstack((points,np.ones(points.shape[1])))
# shape = [3, 4]
P = np.hstack((np.eye(3),np.array([[0],[0],[-10]])))
cam = camera.Camera(P)
# shape = [3, 672]
x = cam.project(points)plt.figure()
plt.plot(x[0],x[1],'k.')
plt.show()

同时,可围 绕一个随机的三维向量,进行增量旋转的投影:

1.3 照相机矩阵的分解

一开始我们知道
P=K[R∣t]P=K[R|t] P=K[R∣t]
我们可以使用RQ因子分解,在已知P矩阵的同时,恢复内参数 K以及照相机的 位置 t 和姿势 R。代码如下:

def factor(self):"""    Factorize the camera matrix into K,R,t as P = K[R|t]. """  # factor first 3*3 partK,R = linalg.rq(self.P[:,:3])# make diagonal of K positiveT = diag(sign(diag(K)))if linalg.det(T) < 0:T[1,1] *= -1self.K = dot(K,T)self.R = dot(T,R) # T is its own inverseself.t = dot(linalg.inv(self.K),self.P[:,3])return self.K, self.R, self.t

RQ 因子分解的结果并不是唯一的。在该因子分解中,分解的结果存在符号二义性。 由于我们需要限制旋转矩阵 R 为正定的(否则,旋转坐标轴即可),所以如果需要,我们可以在求解到的结果中加入变换 T来改变符号。

1.4 计算照相机中心

给定照相机投影矩阵 P,我们可以计算出空间上照相机的所在位置。照相机的中心 C,是一个三维点,满足约束 PC=0。对于投影矩阵为 P=K[R|t] 的照相机,有:
K[R∣t]C=KRC+Kt=0K[R|t]C=KRC+Kt=0 K[R∣t]C=KRC+Kt=0
所以
C=−RTtC=-R^Tt C=−RTt
C与K无关,只和R、t有关。

def center(self):"""    Compute and return the camera center. """if self.c is not None:return self.celse:# compute c by factoringself.factor()self.c = -dot(self.R.T,self.t)return self.c

2 照相机标定

标定照相机是指计算出该照相机的内参数。也就是算出矩阵K。标定相机的标准方法是,拍摄多幅平面棋盘模式的图像,然后进行处理计算。

  1. 测量你选定矩形标定物体的边长 d X和 dY
  2. 将照相机和标定物体放置在平面上,使得照相机的背面和标定物体平行,同时物 体位于照相机图像视图的中心,你可能需要调整照相机或者物体来获得良好的对齐效果;
  3. 测量标定物体到照相机的距离 d Z
  4. 拍摄一副图像来检验该设置是否正确,即标定物体的边要和图像的行和列对齐;
  5. 使用像素数来测量标定物体图像的宽度和高度 dx 和 dy。

其中焦距的公式为:
fx=dxdXdZ,fy=dydYdZf_{x}=\frac{\mathrm{d} x}{\mathrm{~d} X} \mathrm{~d} Z, \quad f_{y}=\frac{\mathrm{d} y}{\mathrm{~d} Y} \mathrm{~d} Z fx​= dXdx​ dZ,fy​= dYdy​ dZ

焦距是在特定图像分辨率下计算出来的,焦距和光心是使用像素来度量的,其尺度和图像分辨率相关,代码如下:

def my_calibration(sz):row, col = szfx = 2555 * col / 2592fy = 2586 * row / 1936K = diag([fx, fy, 1])K[0, 2] = 0.5 * colK[1, 2] = 0.5 * rowreturn K

3 以平面和标记物进行姿态估计

如果图像中包含平面状的 标记物体,并且已经对照相机进行了标定,那么我们可以计算出照相机的姿态(旋转和平移)。这里的标记物体可以为对任何平坦的物体。举例如下:

1)提取两幅图像的 SIFT 特征,然后使用 RANSAC 算法稳健地 估计单应性矩阵

import homography
import camera
import sift# compute features
sift.process_image('C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg', 'python1.sift')
l0, d0 = sift.read_features_from_file('python1.sift')sift.process_image('C:/Users/jmuaia007/Pictures/Saved Pictures/python2.jpg', 'python2.sift')
l1, d1 = sift.read_features_from_file('python2.sift')# match features and estimate homography
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)

现在我们得到了单应性矩阵。该单应性矩阵将一幅图像中标记物上的点映射到另一幅图像中的对应点。

2)定义相应的三维坐标系,使标记物在 X-Y平面上(Z=0),原点在标记物的某位置上:为了检验单应性矩阵结果的正确性,我们需要将一些简单的三维物体放置在标记物 上,这里我们使用一个立方体。你可以使用下面的函数来产生立方体上的点:

def cube_points(c, wid):""" Creates a list of points for plottinga cube with plot. (the first 5 points arethe bottom square, some sides repeated). """p = []# bottomp.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])  # same as first to close plot# topp.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])  # same as first to close plot# vertical sidesp.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

3)有了单应性矩阵和照相机的标定矩阵,我们现在可以得出两个视图间的相对变换

# 计算照相机标定矩阵
K = my_calibration((300, 400))# 位于边长为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))# 测试:将点投影在 z=0 上,应该能够得到相同的点
point = array([1,1,0,1]).T
print(homography.normalize(dot(dot(H,cam1.P),point)))
print(cam2.project(point))

因为场景坐标的尺度是任意的,所以我们使用下面的矩阵来创建第一个照相机:
P1=K[10000100001−1]\boldsymbol{P}_{1}=\boldsymbol{K}\left[\begin{array}{cccc} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & -1 \end{array}\right] P1​=K⎣⎡​100​010​001​00−1​⎦⎤​
有了估计出的单应性矩阵,我们可以将其变换到第二幅图像上,绘制出变换后的图像P2P_{2}P2​:
P2=HP1P_{2}=H P_{1} P2​=HP1​
作为合理性验证,可以使用新矩阵投影标记平面的一个点,然后检查投影后的点是否与使用第一个照相机和单应性矩阵变换后的点相同。

4)实现结果(完整代码):

import homography
import camera
import sift
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image # compute features
sift.process_image('C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg', 'python1.sift')
l0, d0 = sift.read_features_from_file('python1.sift')sift.process_image('C:/Users/jmuaia007/Pictures/Saved Pictures/python2.jpg', 'python2.sift')
l1, d1 = sift.read_features_from_file('python2.sift')# match features and estimate homography
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)def cube_points(c, wid):""" Creates a list of points for plottinga cube with plot. (the first 5 points arethe bottom square, some sides repeated). """p = []# bottomp.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])  # same as first to close plot# topp.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])  # same as first to close plot# vertical sidesp.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 np.array(p).T
def my_calibration(sz):row, col = szfx = 2555 * col / 2592fy = 2586 * row / 1936K = np.diag([fx, fy, 1])K[0, 2] = 0.5 * colK[1, 2] = 0.5 * rowreturn K# 计算照相机标定矩阵
K = my_calibration((300, 400))# 位于边长为0.2 z=0平面的三维点
box = cube_points([0, 0, 0.1], 0.1)# 投影第一幅图像上底部的正方形
cam1 = camera.Camera(np.hstack((K, np.dot(K, np.array([[0], [0], [-1]])))))
# 底部正方形上的点
box_cam1 = cam1.project(homography.make_homog(box[:, :5]))# 使用H将点变换到第二幅图像中
box_trans = homography.normalize(np.dot(H,box_cam1))# 从cam1和H中计算第二个照相机矩阵
cam2 = camera.Camera(np.dot(H, cam1.P))
A = np.dot(np.linalg.inv(K), cam2.P[:, :3])
A = np.array([A[:, 0], A[:, 1], np.cross(A[:, 0], A[:, 1])]).T
cam2.P[:, :3] = np.dot(K, A)# 使用第二个照相机矩阵投影
box_cam2 = cam2.project(homography.make_homog(box))# 测试:将点投影在 z=0 上,应该能够得到相同的点
point = np.array([1,1,0,1]).T
print(homography.normalize(np.dot(np.dot(H,cam1.P),point)))
print(cam2.project(point))# plotting
im0 = np.array(Image.open('C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg'))
im1 = np.array(Image.open('C:/Users/jmuaia007/Pictures/Saved Pictures/python2.jpg'))plt.figure()
plt.imshow(im0)
plt.plot(box_cam1[0, :], box_cam1[1, :], linewidth=3)
plt.title('2D projection of bottom square')
plt.axis('off')plt.figure()
plt.imshow(im1)
plt.plot(box_trans[0, :], box_trans[1, :], linewidth=3)
plt.title('2D projection transfered with H')
plt.axis('off')plt.figure()
plt.imshow(im1)
plt.plot(box_cam2[0, :], box_cam2[1, :], linewidth=3)
plt.title('3D points projected in second image')
plt.axis('off')plt.show()

以上就是计算给定平面场景物体的照相机矩阵。我们结合特征匹配和单 应性矩阵,以及照相机标定技术,实现了在一幅图像上放置一个立方体。 有了照相机的姿态估计技术,我们现在就具备了创建简单增强现实应用的基本技能了。

4 增强现实

增强现实(Augmented Reality,AR)是将物体和相应信息放置在图像数据上的一 系列操作的总称。最经典的例子是放置一个三维计算机图形学模型,使其看起来属于该场景;如果在视频中,该模型会随着照相机的运动很自然地移动。

4.1 PyGame和PyOpenGL

PyGame 是非常流行的游戏开发工具包,它可以非常简单地处理显示窗口、输入设 备、事件,以及其他内容。PyGame 是开源的。

PyOpenGL 是 OpenGL 图形编程的 Python 绑定接口。OpenGL 可以安装在几乎所 有的系统上,并且具有很好的图形性能。OpenGL 具有跨平台性,能够在不同的操作系统之间工作。

安装上述的教程很多,这里便不一一赘述,当你可运行下列代码不报错即安装成功:

from OpenGL.GL import *
from OpenGL.GLU import *
import pygame, pygame.image
from pygame.locals import *

还是不放心安装成功没,那就运行下列代码,能转起来,则安装成功:

from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *def Draw():glClear(GL_COLOR_BUFFER_BIT)glRotatef(0.5, 0, 1, 0)glutWireTeapot(0.5)glFlush()glutInit()
glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA)
glutInitWindowSize(400, 400)
glutCreateWindow("test")
glutDisplayFunc(Draw)
glutIdleFunc(Draw)
glutMainLoop()

4.2 在图像中放置虚拟物体

我们需要做的第一件事是将图像(打算放置虚拟物体的图像)作为背景添加进来。下面的函数可以载入一幅图像,然后将其转换成一个 OpenGL 纹理,并将该纹理放 置在四边形上:该函数首先使用 PyGame 中的一些函数来载入一幅图像,将其序列化为能够在 PyOpenGL 中使用的原始字符串表示。然后,重置模拟视图,清除颜色和深度缓存。 接下来,绑定这个纹理,使其能够在四边形和指定插值中使用它。四边形是在每一 维分别为 -1 和 1 的点上定义的。注意,纹理图像的坐标是从 0 到 1。最后,清除该纹理,避免其干扰之后准备绘制的图像。

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)  # 清除纹理

整体代码如下:

# -*- coding: utf-8 -*-
import math
import pickle
import sys
from pylab import *
from OpenGL.GL import *
from OpenGL.GLU import *
from OpenGL.GLUT import *
import pygame, pygame.image
from pygame.locals import *
import homography, camera
import siftdef cube_points(c, wid):  # 绘制立方体的一各点列表""" Creates a list of points for plottinga cube with plot. (the first 5 points arethe bottom square, some sides repeated). """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).Tdef my_calibration(sz):row, col = szfx = 4529 * col / 2592fy = 2387 * row / 1936K = diag([fx, fy, 1])K[0, 2] = 0.5 * colK[1, 2] = 0.5 * rowreturn Kdef 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.piaspect = (width * fy) / (height * fx)# 定义近和远的剪裁平面near = 0.1far = 100.0# 设定透视gluPerspective(fovy, aspect, near, far)glViewport(0, 0, width, height)def set_modelview_from_camera(Rt):  # 获取矩阵glMatrixMode(GL_MODELVIEW)glLoadIdentity()# 围绕x轴将茶壶旋转90度,使z轴向上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, :]  # 改变x轴的符号# 获得平移量t = Rt[:, 3]# 获得4*4的的模拟视图矩阵M = np.eye(4)M[:3, :3] = np.dot(R, Rx)M[:3, 3] = t# 转置并压平以获取列序数值M = M.Tm = 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)def drawFunc(size):  # 白色茶壶glRotatef(0.5, 5, 5, 0)  # (角度,x,y,z)glutWireTeapot(size)# 刷新显示glFlush()width, height = 1280,960def setup():  # 设置窗口和pygame环境pygame.init()pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)pygame.display.set_caption("OpenGL AR demo")# 计算特征
sift.process_image('C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg', 'python1.sift')
l0, d0 = sift.read_features_from_file('python1.sift')sift.process_image('C:/Users/jmuaia007/Pictures/Saved Pictures/python2.jpg', 'python2.sift')
l1, d1 = sift.read_features_from_file('python2.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((1280,960))
# 位于边长为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))Rt = dot(linalg.inv(K), cam2.P)
setup()
draw_background('C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg')
set_projection_from_camera(K)
set_modelview_from_camera(Rt)draw_teapot(0.05)  # 显示红色茶壶
# drawFunc(0.05)  # 显示白色空心茶壶
pygame.display.flip()
while True:for event in pygame.event.get():if event.type == pygame.QUIT:sys.exit()

其中几个参数需要变动:

  1. draw_background(‘C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg’)里面填的哪张图,那么width, height = 1280,960就设置成响应的分辨率
  2. 根据1的那张图的width, height,使用fx=dxdXdZ,fy=dydYdZf_{x}=\frac{\mathrm{d} x}{\mathrm{~d} X} \mathrm{~d} Z, \quad f_{y}=\frac{\mathrm{d} y}{\mathrm{~d} Y} \mathrm{~d} Zfx​= dXdx​ dZ,fy​= dYdy​ dZ算出fx和f_{x}和fx​和fyf_{y}fy​,替换这两个值

最终效果如下所示:

Python计算机视觉——照相机模型与增强现实相关推荐

  1. Python计算机视觉编程第四章——照相机模型与增强现实

    Python计算机视觉编程 照相机模型与增强现实 (一)针孔照相机模型 1.1 照相机矩阵 1.2 三维点的投影 1.3 照相机矩阵的分解 1.4 计算照相机中心 (二)照相机标定 (三)以平面和标记 ...

  2. 四、【python计算机视觉编程】照相机模型与增强现实

    照相机模型与增强现实 (一)针孔照相机模型 (1)照相机矩阵 (2)三维点的投影 (3)照相机矩阵的分解 (4)计算照相机中心 (二)照相机标定 (三)以平面和标记物进行姿态估计 (四)增强现实 (A ...

  3. Python计算机视觉——第四章 照相机模型与增强现实

    文章目录 引言 4.1 针孔照相机模型 4.1.1 投影矩阵 4.1.2 三维点的投影 4.1.3 照相机矩阵的分解 4.1.4 计算照相机中心 4.2 照相机标定 4.2.1 相机参数标定实验 4. ...

  4. Python计算机视觉编程第四章 照相机模型与增强现实

    照相机模型与增强现实 1 针孔照相机模型 1.1 照相机矩阵 1.2 三维点的投影 1.3 照相机矩阵的分解 1.4 照相机中心 2 照相机标定 3 以平面和标记物进行姿态估计 4 增强现实 4.1 ...

  5. Python计算机视觉编程学习笔记 四 照相机模型与增强现实

    照相机模型与增强现实 (一)针孔照相机模型 1.1 照相机模型 1.2 三维点的投影 1.3照相机矩阵的分解 1.4 计算照相机中心 (二)照相机标定 (三)以平面和标记物进行姿态估计 (四)增强现实 ...

  6. 照相机模型与增强现实(相机标定)

    计算机视觉:照相机模型与增强现实 针孔照相机模型 照相机标定 光学标定 自标定(SFM) 实验结果 本篇文章主要讲述如何通过通过照相机模型在映射中加入部分照相机产生图像过程的投影特性从而 处理三维图像 ...

  7. python计算机视觉 第四章照相机模型与增强现实

    文章目录 引言 4.1针孔照相机模型 4.1.1照相机矩阵 4.1.2三维点的投影 4.1.3照相机矩阵分解 4.1.4计算照相机中心 4.2照相机标定 4.2.1一个简单地标定方法 4.3以平面和标 ...

  8. python计算机视觉学习———照相机模型与增强现实

    文章目录 4.1针孔照相机模型 4.1.1 照相机矩阵 4.1.2三维点的投影 4.1.3照相机矩阵的分解 4.2 照相机标定 4.3 以平面和标记物进行姿态估计 4.4 增强现实 4.4.1 PyG ...

  9. OpenGL照相机模型与增强现实

    本文将尝试对照相机进行建模并有效地使用这些模型. (该实验参书籍:Python计算机视觉编程 第四章) (代码为书上源码) 1.1 照相机标定 标定照相机是指计算出该照相机的内参数.其标准方法是,拍摄 ...

最新文章

  1. LED亮度与电流之间的关系?
  2. Uncaught ReferenceError: angular is not defined
  3. PHP 安装 扩展时 抛出 /usr/local/Cellar/php@7.1/7.1.25/pecl 异常解决
  4. gcc - lm的含义
  5. mac版smali2java_Android反编译apk并重新打包签名(Mac环境)
  6. Registry注册机制
  7. mysql 一个文章多个分类_jdbc mysql 插入一篇文章并与多个标签,一个分类建立关联关系。...
  8. Welcome to NHibernate
  9. nginx php mysql zend_性能测试基本功 - 手动配置nginx+php-cgi+zend+mysql
  10. SIFT算法原理介绍
  11. 星际开图挂_别开|《星际争霸2》牛X强力高端职业玩家手把手教你识别开图挂_234游戏网...
  12. java计算机毕业设计学生成绩管理系统源程序+mysql+系统+lw文档+远程调试
  13. VC 蓝牙设备 编程
  14. Qt 5.12.10 用Design ui 设计界面,连续输入中文时,变成英文输入
  15. 计算机内存采用什么存储模式,计算机内存模型
  16. Springboot 实现将文件压缩,然后下载
  17. RSA的非对称加密,公钥加密私钥解密,本地测试
  18. notes 常见问题
  19. C51模拟PS2键盘(一)
  20. 北京电大c语言实验作业二,大学大一c语言程序设计实验室上机题全部代码答案(实验报告).doc...

热门文章

  1. JAVA用递归方法判断某个字串是否是回文
  2. 主机/服务器某端口被占用及解决办法
  3. merge into使用方法
  4. 把ListT转换为DataTable
  5. 玩转Spring Cloud之配置中心(config server config client)
  6. 2022-2028年中国智能眼镜行业深度调研及投资前景预测报告
  7. MySQL 学习笔记(15)— 连接查询(内连接、左外连接、右外连接、全外连接、交叉连接、自然连接等)
  8. teamcity plugin中读取js和css文件的方法
  9. POJ 2430 状压DP
  10. 慢慢学Linux驱动开发,第十章,GNU C的扩展