日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

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

發(fā)布時(shí)間:2023/11/27 生活经验 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Python计算机视觉——照相机模型与增强现实 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Python計(jì)算機(jī)視覺(jué)——照相機(jī)模型與增強(qiáng)現(xiàn)實(shí)

文章目錄

  • Python計(jì)算機(jī)視覺(jué)——照相機(jī)模型與增強(qiáng)現(xiàn)實(shí)
    • 1 針孔照相機(jī)模型
      • 1.1 照相機(jī)矩陣
      • 1.2 三維點(diǎn)的投影
      • 1.3 照相機(jī)矩陣的分解
      • 1.4 計(jì)算照相機(jī)中心
    • 2 照相機(jī)標(biāo)定
    • 3 以平面和標(biāo)記物進(jìn)行姿態(tài)估計(jì)
    • 4 增強(qiáng)現(xiàn)實(shí)
      • 4.1 PyGame和PyOpenGL
      • 4.2 在圖像中放置虛擬物體

1 針孔照相機(jī)模型

針孔照相機(jī)模型(有時(shí)稱為射影照相機(jī)模型)是計(jì)算機(jī)視覺(jué)中廣泛使用的照相機(jī)模 型。對(duì)于大多數(shù)應(yīng)用來(lái)說(shuō),針孔照相機(jī)模型簡(jiǎn)單,并且具有足夠的精確度。在針孔照相機(jī)模型中,在光線投影到圖像平面之前,從唯一一個(gè)點(diǎn)經(jīng)過(guò),也就是 照相機(jī)中心 C。如下圖所示,圖像點(diǎn) x 是由圖像平面與連接三維點(diǎn) X 和照相機(jī)中心 C 的直線相 交而成的。虛線表示該照相機(jī)的光學(xué)坐標(biāo)軸。

在針孔照相機(jī)中,三維點(diǎn) X 投影為圖像點(diǎn) x(兩個(gè)點(diǎn)都是用齊次坐標(biāo)表示的),如下 所示:
λx=PXλx=PX λx=PX
3×4 的矩陣 P 為照相機(jī)矩陣(或投影矩陣)。注意,在齊次坐標(biāo)系中,三維 點(diǎn) X 的坐標(biāo)由 4 個(gè)元素組成,X=[X, Y, Z, W]。這里的標(biāo)量 λ 是三維點(diǎn)的逆深度(深度的倒數(shù))。如果我們打算在齊次坐標(biāo)中將最后一個(gè)數(shù)值歸一化為 1,那么就會(huì)使用到它。

1.1 照相機(jī)矩陣

照相機(jī)矩陣可以分解為:
P=K[R∣t]P=K[R|t] P=K[Rt]
其中,R 是描述照相機(jī)方向的旋轉(zhuǎn)矩陣,t 是描述照相機(jī)中心位置的三維平移向量, 內(nèi)標(biāo)定矩陣 K描述照相機(jī)的投影性質(zhì)。標(biāo)定矩陣僅和照相機(jī)自身的情況相關(guān),通常情況下可以寫成:
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)圖像平面和照相機(jī)中心間的距離為焦距 f。當(dāng)像素?cái)?shù)組在傳感器上偏斜的時(shí)候,需要 用到傾斜參數(shù) s。在大多數(shù)情況下,s 可以設(shè)置成 0。也就是說(shuō):
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?
縱橫比例參數(shù) α 是在像素元素非正方形的情況下使用的。通常情況下,我們可以默 認(rèn)設(shè)置 α=1。經(jīng)過(guò)這些假設(shè),標(biāo)定矩陣變?yōu)?#xff1a;
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????
除焦距之外,標(biāo)定矩陣中剩余的唯一參數(shù)為光心(有時(shí)稱主點(diǎn))的坐標(biāo) c=[cx,cy]c=[c_{x} ,c_{y}]c=[cx?cy?],也就是光線坐標(biāo)軸和圖像平面的交點(diǎn)。因?yàn)楣庑耐ǔT趫D像的中心,并且圖像的坐 標(biāo)是從左上角開(kāi)始計(jì)算的,所以光心的坐標(biāo)常接近于圖像寬度和高度的一半。特別強(qiáng)調(diào)一點(diǎn),在這個(gè)例子中,唯一未知的變量是焦距 f。

1.2 三維點(diǎn)的投影

下面的例子展示如何將三維中的點(diǎn)投影到圖像視圖中.使用的數(shù)據(jù)集在這下載:Visual Geometry Group - University of Oxford。使用其中的 house.p3d三維模型做實(shí)驗(yàn),首先可以看看這模型長(zhǎng)啥樣,其實(shí)就是幾百個(gè)三維點(diǎn)組成的矩陣,所以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()

同時(shí),可圍 繞一個(gè)隨機(jī)的三維向量,進(jìn)行增量旋轉(zhuǎn)的投影:

1.3 照相機(jī)矩陣的分解

一開(kāi)始我們知道
P=K[R∣t]P=K[R|t] P=K[Rt]
我們可以使用RQ因子分解,在已知P矩陣的同時(shí),恢復(fù)內(nèi)參數(shù) K以及照相機(jī)的 位置 t 和姿勢(shì) 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 因子分解的結(jié)果并不是唯一的。在該因子分解中,分解的結(jié)果存在符號(hào)二義性。 由于我們需要限制旋轉(zhuǎn)矩陣 R 為正定的(否則,旋轉(zhuǎn)坐標(biāo)軸即可),所以如果需要,我們可以在求解到的結(jié)果中加入變換 T來(lái)改變符號(hào)。

1.4 計(jì)算照相機(jī)中心

給定照相機(jī)投影矩陣 P,我們可以計(jì)算出空間上照相機(jī)的所在位置。照相機(jī)的中心 C,是一個(gè)三維點(diǎn),滿足約束 PC=0。對(duì)于投影矩陣為 P=K[R|t] 的照相機(jī),有:
K[R∣t]C=KRC+Kt=0K[R|t]C=KRC+Kt=0 K[Rt]C=KRC+Kt=0
所以
C=?RTtC=-R^Tt C=?RTt
C與K無(wú)關(guān),只和R、t有關(guān)。

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 照相機(jī)標(biāo)定

標(biāo)定照相機(jī)是指計(jì)算出該照相機(jī)的內(nèi)參數(shù)。也就是算出矩陣K。標(biāo)定相機(jī)的標(biāo)準(zhǔn)方法是,拍攝多幅平面棋盤模式的圖像,然后進(jìn)行處理計(jì)算。

  1. 測(cè)量你選定矩形標(biāo)定物體的邊長(zhǎng) d X和 dY
  2. 將照相機(jī)和標(biāo)定物體放置在平面上,使得照相機(jī)的背面和標(biāo)定物體平行,同時(shí)物 體位于照相機(jī)圖像視圖的中心,你可能需要調(diào)整照相機(jī)或者物體來(lái)獲得良好的對(duì)齊效果;
  3. 測(cè)量標(biāo)定物體到照相機(jī)的距離 d Z
  4. 拍攝一副圖像來(lái)檢驗(yàn)該設(shè)置是否正確,即標(biāo)定物體的邊要和圖像的行和列對(duì)齊;
  5. 使用像素?cái)?shù)來(lái)測(cè)量標(biāo)定物體圖像的寬度和高度 dx 和 dy。

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

焦距是在特定圖像分辨率下計(jì)算出來(lái)的,焦距和光心是使用像素來(lái)度量的,其尺度和圖像分辨率相關(guān),代碼如下:

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 以平面和標(biāo)記物進(jìn)行姿態(tài)估計(jì)

如果圖像中包含平面狀的 標(biāo)記物體,并且已經(jīng)對(duì)照相機(jī)進(jìn)行了標(biāo)定,那么我們可以計(jì)算出照相機(jī)的姿態(tài)(旋轉(zhuǎn)和平移)。這里的標(biāo)記物體可以為對(duì)任何平坦的物體。舉例如下:

1)提取兩幅圖像的 SIFT 特征,然后使用 RANSAC 算法穩(wěn)健地 估計(jì)單應(yīng)性矩陣

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)

現(xiàn)在我們得到了單應(yīng)性矩陣。該單應(yīng)性矩陣將一幅圖像中標(biāo)記物上的點(diǎn)映射到另一幅圖像中的對(duì)應(yīng)點(diǎn)。

2)定義相應(yīng)的三維坐標(biāo)系,使標(biāo)記物在 X-Y平面上(Z=0),原點(diǎn)在標(biāo)記物的某位置上:為了檢驗(yàn)單應(yīng)性矩陣結(jié)果的正確性,我們需要將一些簡(jiǎn)單的三維物體放置在標(biāo)記物 上,這里我們使用一個(gè)立方體。你可以使用下面的函數(shù)來(lái)產(chǎn)生立方體上的點(diǎn):

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)有了單應(yīng)性矩陣和照相機(jī)的標(biāo)定矩陣,我們現(xiàn)在可以得出兩個(gè)視圖間的相對(duì)變換

# 計(jì)算照相機(jī)標(biāo)定矩陣
K = my_calibration((300, 400))# 位于邊長(zhǎng)為0.2 z=0平面的三維點(diǎn)
box = cube_points([0, 0, 0.1], 0.1)# 投影第一幅圖像上底部的正方形
cam1 = camera.Camera(hstack((K, dot(K, array([[0], [0], [-1]])))))
# 底部正方形上的點(diǎn)
box_cam1 = cam1.project(homography.make_homog(box[:, :5]))# 使用H將點(diǎn)變換到第二幅圖像中
box_trans = homography.normalize(dot(H,box_cam1))# 從cam1和H中計(jì)算第二個(gè)照相機(jī)矩陣
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)# 使用第二個(gè)照相機(jī)矩陣投影
box_cam2 = cam2.project(homography.make_homog(box))# 測(cè)試:將點(diǎn)投影在 z=0 上,應(yīng)該能夠得到相同的點(diǎn)
point = array([1,1,0,1]).T
print(homography.normalize(dot(dot(H,cam1.P),point)))
print(cam2.project(point))

因?yàn)閳?chǎng)景坐標(biāo)的尺度是任意的,所以我們使用下面的矩陣來(lái)創(chuàng)建第一個(gè)照相機(jī):
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????
有了估計(jì)出的單應(yīng)性矩陣,我們可以將其變換到第二幅圖像上,繪制出變換后的圖像P2P_{2}P2?
P2=HP1P_{2}=H P_{1} P2?=HP1?
作為合理性驗(yàn)證,可以使用新矩陣投影標(biāo)記平面的一個(gè)點(diǎn),然后檢查投影后的點(diǎn)是否與使用第一個(gè)照相機(jī)和單應(yīng)性矩陣變換后的點(diǎn)相同。

4)實(shí)現(xiàn)結(jié)果(完整代碼):

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# 計(jì)算照相機(jī)標(biāo)定矩陣
K = my_calibration((300, 400))# 位于邊長(zhǎng)為0.2 z=0平面的三維點(diǎn)
box = cube_points([0, 0, 0.1], 0.1)# 投影第一幅圖像上底部的正方形
cam1 = camera.Camera(np.hstack((K, np.dot(K, np.array([[0], [0], [-1]])))))
# 底部正方形上的點(diǎn)
box_cam1 = cam1.project(homography.make_homog(box[:, :5]))# 使用H將點(diǎn)變換到第二幅圖像中
box_trans = homography.normalize(np.dot(H,box_cam1))# 從cam1和H中計(jì)算第二個(gè)照相機(jī)矩陣
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)# 使用第二個(gè)照相機(jī)矩陣投影
box_cam2 = cam2.project(homography.make_homog(box))# 測(cè)試:將點(diǎn)投影在 z=0 上,應(yīng)該能夠得到相同的點(diǎn)
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()

以上就是計(jì)算給定平面場(chǎng)景物體的照相機(jī)矩陣。我們結(jié)合特征匹配和單 應(yīng)性矩陣,以及照相機(jī)標(biāo)定技術(shù),實(shí)現(xiàn)了在一幅圖像上放置一個(gè)立方體。 有了照相機(jī)的姿態(tài)估計(jì)技術(shù),我們現(xiàn)在就具備了創(chuàng)建簡(jiǎn)單增強(qiáng)現(xiàn)實(shí)應(yīng)用的基本技能了。

4 增強(qiáng)現(xiàn)實(shí)

增強(qiáng)現(xiàn)實(shí)(Augmented Reality,AR)是將物體和相應(yīng)信息放置在圖像數(shù)據(jù)上的一 系列操作的總稱。最經(jīng)典的例子是放置一個(gè)三維計(jì)算機(jī)圖形學(xué)模型,使其看起來(lái)屬于該場(chǎng)景;如果在視頻中,該模型會(huì)隨著照相機(jī)的運(yùn)動(dòng)很自然地移動(dòng)。

4.1 PyGame和PyOpenGL

PyGame 是非常流行的游戲開(kāi)發(fā)工具包,它可以非常簡(jiǎn)單地處理顯示窗口、輸入設(shè) 備、事件,以及其他內(nèi)容。PyGame 是開(kāi)源的。

PyOpenGL 是 OpenGL 圖形編程的 Python 綁定接口。OpenGL 可以安裝在幾乎所 有的系統(tǒng)上,并且具有很好的圖形性能。OpenGL 具有跨平臺(tái)性,能夠在不同的操作系統(tǒng)之間工作。

安裝上述的教程很多,這里便不一一贅述,當(dāng)你可運(yùn)行下列代碼不報(bào)錯(cuò)即安裝成功:

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

還是不放心安裝成功沒(méi),那就運(yùn)行下列代碼,能轉(zhuǎn)起來(lái),則安裝成功:

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 在圖像中放置虛擬物體

我們需要做的第一件事是將圖像(打算放置虛擬物體的圖像)作為背景添加進(jìn)來(lái)。下面的函數(shù)可以載入一幅圖像,然后將其轉(zhuǎn)換成一個(gè) OpenGL 紋理,并將該紋理放 置在四邊形上:該函數(shù)首先使用 PyGame 中的一些函數(shù)來(lái)載入一幅圖像,將其序列化為能夠在 PyOpenGL 中使用的原始字符串表示。然后,重置模擬視圖,清除顏色和深度緩存。 接下來(lái),綁定這個(gè)紋理,使其能夠在四邊形和指定插值中使用它。四邊形是在每一 維分別為 -1 和 1 的點(diǎn)上定義的。注意,紋理圖像的坐標(biāo)是從 0 到 1。最后,清除該紋理,避免其干擾之后準(zhǔn)備繪制的圖像。

def draw_background(imname):# 載入背景圖像bg_image = pygame.image.load(imname).convert()bg_data = pygame.image.tostring(bg_image, "RGBX", 1)  # 將圖像轉(zhuǎn)為字符串描述glMatrixMode(GL_MODELVIEW)  # 將當(dāng)前矩陣指定為投影矩陣glLoadIdentity()  # 把矩陣設(shè)為單位矩陣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):  # 繪制立方體的一各點(diǎn)列表""" 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])  # 和第一個(gè)相同# 頂部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])  # 和第一個(gè)相同# 豎直邊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)# 定義近和遠(yuǎn)的剪裁平面near = 0.1far = 100.0# 設(shè)定透視gluPerspective(fovy, aspect, near, far)glViewport(0, 0, width, height)def set_modelview_from_camera(Rt):  # 獲取矩陣glMatrixMode(GL_MODELVIEW)glLoadIdentity()# 圍繞x軸將茶壺旋轉(zhuǎn)90度,使z軸向上Rx = np.array([[1, 0, 0], [0, 0, -1], [0, 1, 0]])# 獲得旋轉(zhuǎn)的最佳逼近R = Rt[:, :3]U, S, V = np.linalg.svd(R)R = np.dot(U, V)R[0, :] = -R[0, :]  # 改變x軸的符號(hào)# 獲得平移量t = Rt[:, 3]# 獲得4*4的的模擬視圖矩陣M = np.eye(4)M[:3, :3] = np.dot(R, Rx)M[:3, 3] = t# 轉(zhuǎn)置并壓平以獲取列序數(shù)值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)  # 將圖像轉(zhuǎn)為字符串描述glMatrixMode(GL_MODELVIEW)  # 將當(dāng)前矩陣指定為投影矩陣glLoadIdentity()  # 把矩陣設(shè)為單位矩陣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():  # 設(shè)置窗口和pygame環(huán)境pygame.init()pygame.display.set_mode((width, height), OPENGL | DOUBLEBUF)pygame.display.set_caption("OpenGL AR demo")# 計(jì)算特征
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')# 匹配特征,計(jì)算單應(yīng)性矩陣
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)# 計(jì)算照相機(jī)標(biāo)定矩陣
K = my_calibration((1280,960))
# 位于邊長(zhǎng)為0.2,z=0平面上的三維點(diǎn)
box = cube_points([0, 0, 0.1], 0.1)# 投影第一幅圖下個(gè)上底部的正方形
cam1 = camera.Camera(hstack((K, dot(K, array([[0], [0], [-1]])))))
# 底部正方形上的點(diǎn)
box_cam1 = cam1.project(homography.make_homog(box[:, :5]))# 使用H將點(diǎn)變換到第二幅圖像中
box_trans = homography.normalize(dot(H, box_cam1))# 從cam1和H中計(jì)算第二個(gè)照相機(jī)矩陣
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)
# 使用第二個(gè)照相機(jī)矩陣投影
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()

其中幾個(gè)參數(shù)需要變動(dòng):

  1. draw_background(‘C:/Users/jmuaia007/Pictures/Saved Pictures/python1.jpg’)里面填的哪張圖,那么width, height = 1280,960就設(shè)置成響應(yīng)的分辨率
  2. 根據(jù)1的那張圖的width, height,使用fx=dxdXdZ,fy=dydYdZf_{x}=\frac{\mathrmozvdkddzhkzd x}{\mathrm{~d} X} \mathrm{~d} Z, \quad f_{y}=\frac{\mathrmozvdkddzhkzd y}{\mathrm{~d} Y} \mathrm{~d} Zfx?=?dXdx??dZ,fy?=?dYdy??dZ算出fx和f_{x}和fx?fyf_{y}fy?,替換這兩個(gè)值

最終效果如下所示:

總結(jié)

以上是生活随笔為你收集整理的Python计算机视觉——照相机模型与增强现实的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。