色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

張氏標定法的原理和實現

jt_rfid5 ? 來源:CSDN ? 作者:weixin_39717692 ? 2022-11-14 10:14 ? 次閱讀

張正友相機標定法是張正友教授1998年提出的單平面棋盤格的相機標定方法。傳統標定法的標定板是需要三維的,需要非常精確,這很難制作,而張正友教授提出的方法介于傳統標定法和自標定法之間,但克服了傳統標定法需要的高精度標定物的缺點,而僅需使用一個打印出來的棋盤格就可以。同時也相對于自標定而言,提高了精度,便于操作。因此張氏標定法被廣泛應用于計算機視覺方面。

傳統標定法的的標定板

a4cfcda4-6362-11ed-8abf-dac502259ad0.png

張正友標定法的標定板

今天,我們就來講解一下張氏標定法的原理和實現,學會之后,我們就可以自己去制作一個棋盤標定板,然后拍照,標定自己手機相機的參數啦!

一、相機標定介紹

二、算法原理

1.整體流程

2.模型假設

3.模型求解

(1)內外參數求解

(2)畸變系數求解

(3)精度優化

三、算法實現

1.main.py

2.homography.py

4.extrinsics.py

5.distortion.py

6.refine_all.py

7.結果

一、相機標定介紹

相機標定指建立相機圖像像素位置與場景點位置之間的關系,根據相機成像模型,由特征點在圖像中坐標與世界坐標的對應關系,求解相機模型的參數。相機需要標定的模型參數包括內部參數和外部參數。

針孔相機成像原理其實就是利用投影將真實的三維世界坐標轉換到二維的相機坐標上去,其模型示意圖如下圖所示:

a4df7dda-6362-11ed-8abf-dac502259ad0.png

從圖中我們可以看出,在世界坐標中的一條直線上的點在相機上只呈現出了一個點,其中發生了非常大的變化,同時也損失和很多重要的信息,這正是我們3D重建、目標檢測與識別領域的重點和難點。實際中,鏡頭并非理想的透視成像,帶有不同程度的畸變。理論上鏡頭的畸變包括徑向畸變和切向畸變,切向畸變影響較小,通常只考慮徑向畸變。

徑向畸變:徑向畸變主要由鏡頭徑向曲率產生(光線在遠離透鏡中心的地方比靠近中心的地方更加彎曲)。導致真實成像點向內或向外偏離理想成像點。其中畸變像點相對于理想像點沿徑向向外偏移,遠離中心的,稱為枕形畸變;徑向畸點相對于理想點沿徑向向中心靠攏,稱為桶狀畸變。

用數學公式來表示:

a548bb06-6362-11ed-8abf-dac502259ad0.png

其中,X為相機中的坐標;X為真實世界坐標;K為內參矩陣;RT為外參矩陣 K為內參矩陣,是相機內部參數組成的一個3*3的矩陣,其中,代表焦距;S為畸變參數為中心點坐標,a為縱橫比例參數,我們可以默認設為1,所以 RT為外參矩陣,R是描述照相機方向的旋轉矩陣,T是描述照相機中心位置的三維平移向量。

二、算法原理

1.整體流程

a5682806-6362-11ed-8abf-dac502259ad0.png

2.模型假設

a57c7b4e-6362-11ed-8abf-dac502259ad0.png

a58eab2a-6362-11ed-8abf-dac502259ad0.png

a5a299f0-6362-11ed-8abf-dac502259ad0.png

a5bd0664-6362-11ed-8abf-dac502259ad0.png

3.模型求解

(1)內外參數求解

我們令,則

其中,H為一個3*3的矩陣,并且有一個元素作為齊次坐標。因此,H有8個自由度。

現在有8個自由度需要求解,所以需要四個對應點。也就是四個點就可以求出圖像平面到世界平面的單應性矩陣H。

我想,張氏標定法選用的棋盤格作為標定板的原因除了角點方便檢測的另外一個原因可能就是這個吧。

通過4個點,我們就可以可以獲得單應性矩陣H。但是,H是內參陣和外參陣的合體。我們想要最終分別獲得內參和外參。所以需要想個辦法,先把內參求出來。然后外參也就隨之解出了。觀察一下這個式子:

我們可以知道以下約束條件:

①,R1R2 正交,也就是說 R1 R2=0。其實這個不難理解,因為 R1 R2 是分別繞x軸和y軸得到的,而x軸和y軸均垂直z軸。

②旋轉向量的模為1,也就是說R1=R2=1,這是因為旋轉不改變尺度。

根據這兩個約束條件,經過數學變換,我們可以得到:

觀察上面的兩個式子,我們可以看出,由于H1和H2是通過單應性求解出來的,所以我們要求解的參數就變成A矩陣中未知的5個參數。我們可以通過三個單應性矩陣來求解這5個參數,利用三個單應性矩陣在兩個約束下可以生成6個方程。其中,三個單應性矩陣可以通過三張對同一標定板不同角度和高度的照片獲得。

用數學公式來表達如下:

我們很容易發現B是一個對稱陣,所以B的有效元素就剩下6個,即

進一步化簡:

通過計算,我們可以得到

a5d514d4-6362-11ed-8abf-dac502259ad0.png

利用上面提到的兩個約束條件,我們可以得到下面的方程組:

a5e9de8c-6362-11ed-8abf-dac502259ad0.png

這個方程組的本質和前面那兩個用h和A組成的約束條件方程組是一樣的。

通過至少含一個棋盤格的三幅圖像,應用上述公式我們就可以估算出B了。得到B后,我們通過cholesky分解,就可以得到攝相機機的內參陣A的六個自由度,即:

a5fed012-6362-11ed-8abf-dac502259ad0.png

再根據a611067e-6362-11ed-8abf-dac502259ad0.png化簡可得外部參數,即:

a625a5ca-6362-11ed-8abf-dac502259ad0.png

(2)畸變系數求解

在文章的開始,我們就講到真實的鏡頭并非理想的透視成像,而是帶有不同程度的畸變。理論上鏡頭的畸變包括徑向畸變和切向畸變,切向畸變影響較小,通常只考慮徑向畸變,而且在徑向畸變的求解中,僅考慮了起主導的二元泰勒級數展開的前兩個系數。

具體推導,參考https://blog.csdn.net/onthewaysuccess/article/details/40736177

(3)精度優化

在張正友標定法中,使用了兩次極大似然估計策略,第一次是在不考慮畸變的情況下求解內參和外參,第二次是求解實際的畸變系數。

極大似然參數估計,參考https://blog.csdn.net/onthewaysuccess/article/details/40717213

三、算法實現

1.main.py

#!usr/bin/env/ python

# _*_ coding:utf-8 _*_

import cv2 as cv

import numpy as np

import os

from step.homography import get_homography

from step.intrinsics import get_intrinsics_param

from step.extrinsics import get_extrinsics_param

from step.distortion import get_distortion

from step.refine_all import refinall_all_param

def calibrate():

#求單應矩陣

H = get_homography(pic_points, real_points_x_y)

#求內參

intrinsics_param = get_intrinsics_param(H)

#求對應每幅圖外參

extrinsics_param = get_extrinsics_param(H, intrinsics_param)

#畸變矯正

k = get_distortion(intrinsics_param, extrinsics_param, pic_points, real_points_x_y)

#微調所有參數

[new_intrinsics_param, new_k, new_extrinsics_param] = refinall_all_param(intrinsics_param,

k, extrinsics_param, real_points, pic_points)

print("intrinsics_parm: ", new_intrinsics_param)

print("distortionk: ", new_k)

print("extrinsics_parm: ", new_extrinsics_param)

if __name__ == "__main__":

file_dir = r'..pic'

# 標定所用圖像

pic_name = os.listdir(file_dir)

# 由于棋盤為二維平面,設定世界坐標系在棋盤上,一個單位代表一個棋盤寬度,產生世界坐標系三維坐標

cross_corners = [9, 6] #棋盤方塊交界點排列

real_coor = np.zeros((cross_corners[0] * cross_corners[1], 3), np.float32)

real_coor[:, :2] = np.mgrid[0:9, 0:6].T.reshape(-1, 2)

real_points = []

real_points_x_y = []

pic_points = []

for pic in pic_name:

pic_path = os.path.join(file_dir, pic)

pic_data = cv.imread(pic_path)

# 尋找到棋盤角點

succ, pic_coor = cv.findChessboardCorners(pic_data, (cross_corners[0], cross_corners[1]), None)

if succ:

# 添加每幅圖的對應3D-2D坐標

pic_coor = pic_coor.reshape(-1, 2)

pic_points.append(pic_coor)

real_points.append(real_coor)

real_points_x_y.append(real_coor[:, :2])

calibrate()

2.homography.py

這是用于求解單應性矩陣的文件

#!usr/bin/env/ python

# _*_ coding:utf-8 _*_

import numpy as np

from scipy import optimize as opt

#求輸入數據的歸一化矩陣

def normalizing_input_data(coor_data):

x_avg = np.mean(coor_data[:, 0])

y_avg = np.mean(coor_data[:, 1])

sx = np.sqrt(2) / np.std(coor_data[:, 0])

sy = np.sqrt(2) / np.std(coor_data[:, 1])

norm_matrix = np.matrix([[sx, 0, -sx * x_avg],

[0, sy, -sy * y_avg],

[0, 0, 1]])

return norm_matrix

#求取初始估計的單應矩陣

def get_initial_H(pic_coor, real_coor):

# 獲得歸一化矩陣

pic_norm_mat = normalizing_input_data(pic_coor)

real_norm_mat = normalizing_input_data(real_coor)

M = []

for i in range(len(pic_coor)):

#轉換為齊次坐標

single_pic_coor = np.array([pic_coor[i][0], pic_coor[i][1], 1])

single_real_coor = np.array([real_coor[i][0], real_coor[i][1], 1])

#坐標歸一化

pic_norm = np.dot(pic_norm_mat, single_pic_coor)

real_norm = np.dot(real_norm_mat, single_real_coor)

#構造M矩陣

M.append(np.array([-real_norm.item(0), -real_norm.item(1), -1,

0, 0, 0,

pic_norm.item(0) * real_norm.item(0), pic_norm.item(0) * real_norm.item(1), pic_norm.item(0)]))

M.append(np.array([0, 0, 0,

-real_norm.item(0), -real_norm.item(1), -1,

pic_norm.item(1) * real_norm.item(0), pic_norm.item(1) * real_norm.item(1), pic_norm.item(1)]))

#利用SVD求解M * h = 0中h的解

U, S, VT = np.linalg.svd((np.array(M, dtype='float')).reshape((-1, 9)))

# 最小的奇異值對應的奇異向量,S求出來按大小排列的,最后的最小

H = VT[-1].reshape((3, 3))

H = np.dot(np.dot(np.linalg.inv(pic_norm_mat), H), real_norm_mat)

H /= H[-1, -1]

return H

#返回估計坐標與真實坐標偏差

def value(H, pic_coor, real_coor):

Y = np.array([])

for i in range(len(real_coor)):

single_real_coor = np.array([real_coor[i, 0], real_coor[i, 1], 1])

U = np.dot(H.reshape(3, 3), single_real_coor)

U /= U[-1]

Y = np.append(Y, U[:2])

Y_NEW = (pic_coor.reshape(-1) - Y)

return Y_NEW

#返回對應jacobian矩陣

def jacobian(H, pic_coor, real_coor):

J = []

for i in range(len(real_coor)):

sx = H[0]*real_coor[i][0] + H[1]*real_coor[i][1] +H[2]

sy = H[3]*real_coor[i][0] + H[4]*real_coor[i][1] +H[5]

w = H[6]*real_coor[i][0] + H[7]*real_coor[i][1] +H[8]

w2 = w * w

J.append(np.array([real_coor[i][0]/w, real_coor[i][1]/w, 1/w,

0, 0, 0,

-sx*real_coor[i][0]/w2, -sx*real_coor[i][1]/w2, -sx/w2]))

J.append(np.array([0, 0, 0,

real_coor[i][0]/w, real_coor[i][1]/w, 1/w,

-sy*real_coor[i][0]/w2, -sy*real_coor[i][1]/w2, -sy/w2]))

return np.array(J)

#利用Levenberg Marquart算法微調H

def refine_H(pic_coor, real_coor, initial_H):

initial_H = np.array(initial_H)

final_H = opt.leastsq(value,

initial_H,

Dfun=jacobian,

args=(pic_coor, real_coor))[0]

final_H /= np.array(final_H[-1])

return final_H

#返回微調后的H

def get_homography(pic_coor, real_coor):

refined_homographies =[]

error = []

for i in range(len(pic_coor)):

initial_H = get_initial_H(pic_coor[i], real_coor[i])

final_H = refine_H(pic_coor[i], real_coor[i], initial_H)

refined_homographies.append(final_H)

return np.array(refined_homographies)

3.intrinsics.py

這是用于求解內參矩陣的文件

#!usr/bin/env/ python

# _*_ coding:utf-8 _*_

import numpy as np

#返回pq位置對應的v向量

def create_v(p, q, H):

H = H.reshape(3, 3)

return np.array([

H[0, p] * H[0, q],

H[0, p] * H[1, q] + H[1, p] * H[0, q],

H[1, p] * H[1, q],

H[2, p] * H[0, q] + H[0, p] * H[2, q],

H[2, p] * H[1, q] + H[1, p] * H[2, q],

H[2, p] * H[2, q]

])

#返回相機內參矩陣A

def get_intrinsics_param(H):

#構建V矩陣

V = np.array([])

for i in range(len(H)):

V = np.append(V, np.array([create_v(0, 1, H[i]), create_v(0, 0 , H[i])- create_v(1, 1 , H[i])]))

#求解V*b = 0中的b

U, S, VT = np.linalg.svd((np.array(V, dtype='float')).reshape((-1, 6)))

#最小的奇異值對應的奇異向量,S求出來按大小排列的,最后的最小

b = VT[-1]

#求取相機內參

w = b[0] * b[2] * b[5] - b[1] * b[1] * b[5] - b[0] * b[4] * b[4] + 2 * b[1] * b[3] * b[4] - b[2] * b[3] * b[3]

d = b[0] * b[2] - b[1] * b[1]

alpha = np.sqrt(w / (d * b[0]))

beta = np.sqrt(w / d**2 * b[0])

gamma = np.sqrt(w / (d**2 * b[0])) * b[1]

uc = (b[1] * b[4] - b[2] * b[3]) / d

vc = (b[1] * b[3] - b[0] * b[4]) / d

return np.array([

[alpha, gamma, uc],

[0, beta, vc],

[0, 0, 1]

])

4.extrinsics.py

這是用于求解外參矩陣的文件

#!usr/bin/env/ python

# _*_ coding:utf-8 _*_

import numpy as np

#返回每一幅圖的外參矩陣[R|t]

def get_extrinsics_param(H, intrinsics_param):

extrinsics_param = []

inv_intrinsics_param = np.linalg.inv(intrinsics_param)

for i in range(len(H)):

h0 = (H[i].reshape(3, 3))[:, 0]

h1 = (H[i].reshape(3, 3))[:, 1]

h2 = (H[i].reshape(3, 3))[:, 2]

scale_factor = 1 / np.linalg.norm(np.dot(inv_intrinsics_param, h0))

r0 = scale_factor * np.dot(inv_intrinsics_param, h0)

r1 = scale_factor * np.dot(inv_intrinsics_param, h1)

t = scale_factor * np.dot(inv_intrinsics_param, h2)

r2 = np.cross(r0, r1)

R = np.array([r0, r1, r2, t]).transpose()

extrinsics_param.append(R)

return extrinsics_param

5.distortion.py

這是用于求解畸變矯正系數的文件

#!usr/bin/env/ python

# _*_ coding:utf-8 _*_

import numpy as np

#返回畸變矯正系數k0,k1

def get_distortion(intrinsic_param, extrinsic_param, pic_coor, real_coor):

D = []

d = []

for i in range(len(pic_coor)):

for j in range(len(pic_coor[i])):

#轉換為齊次坐標

single_coor = np.array([(real_coor[i])[j, 0], (real_coor[i])[j, 1], 0, 1])

#利用現有內參及外參求出估計圖像坐標

u = np.dot(np.dot(intrinsic_param, extrinsic_param[i]), single_coor)

[u_estim, v_estim] = [u[0]/u[2], u[1]/u[2]]

coor_norm = np.dot(extrinsic_param[i], single_coor)

coor_norm /= coor_norm[-1]

#r = np.linalg.norm((real_coor[i])[j])

r = np.linalg.norm(coor_norm)

D.append(np.array([(u_estim - intrinsic_param[0, 2]) * r ** 2, (u_estim - intrinsic_param[0, 2]) * r ** 4]))

D.append(np.array([(v_estim - intrinsic_param[1, 2]) * r ** 2, (v_estim - intrinsic_param[1, 2]) * r ** 4]))

#求出估計坐標與真實坐標的殘差

d.append(pic_coor[i][j, 0] - u_estim)

d.append(pic_coor[i][j, 1] - v_estim)

'''

D.append(np.array([(pic_coor[i][j, 0] - intrinsic_param[0, 2]) * r ** 2, (pic_coor[i][j, 0] - intrinsic_param[0, 2]) * r ** 4]))

D.append(np.array([(pic_coor[i][j, 1] - intrinsic_param[1, 2]) * r ** 2, (pic_coor[i][j, 1] - intrinsic_param[1, 2]) * r ** 4]))

#求出估計坐標與真實坐標的殘差

d.append(u_estim - pic_coor[i][j, 0])

d.append(v_estim - pic_coor[i][j, 1])

'''

D = np.array(D)

temp = np.dot(np.linalg.inv(np.dot(D.T, D)), D.T)

k = np.dot(temp, d)

'''

#也可利用SVD求解D * k = d中的k

U, S, Vh=np.linalg.svd(D, full_matrices=False)

temp_S = np.array([[S[0], 0],

[0, S[1]]])

temp_res = np.dot(Vh.transpose(), np.linalg.inv(temp_S))

temp_res_res = np.dot(temp_res, U.transpose())

k = np.dot(temp_res_res, d)

'''

return k

6.refine_all.py

這是用于微調參數的文件

#!usr/bin/env/ python

# _*_ coding:utf-8 _*_

import numpy as np

import math

from scipy import optimize as opt

#微調所有參數

def refinall_all_param(A, k, W, real_coor, pic_coor):

#整合參數

P_init = compose_paramter_vector(A, k, W)

#復制一份真實坐標

X_double = np.zeros((2 * len(real_coor) * len(real_coor[0]), 3))

Y = np.zeros((2 * len(real_coor) * len(real_coor[0])))

M = len(real_coor)

N = len(real_coor[0])

for i in range(M):

for j in range(N):

X_double[(i * N + j) * 2] = (real_coor[i])[j]

X_double[(i * N + j) * 2 + 1] = (real_coor[i])[j]

Y[(i * N + j) * 2] = (pic_coor[i])[j, 0]

Y[(i * N + j) * 2 + 1] = (pic_coor[i])[j, 1]

#微調所有參數

P = opt.leastsq(value,

P_init,

args=(W, real_coor, pic_coor),

Dfun=jacobian)[0]

#raial_error表示利用標定后的參數計算得到的圖像坐標與真實圖像坐標點的平均像素距離

error = value(P, W, real_coor, pic_coor)

raial_error = [np.sqrt(error[2 * i]**2 + error[2 * i + 1]**2) for i in range(len(error) // 2)]

print("total max error: ", np.max(raial_error))

#返回拆解后參數,分別為內參矩陣,畸變矯正系數,每幅圖對應外參矩陣

return decompose_paramter_vector(P)

#把所有參數整合到一個數組內

def compose_paramter_vector(A, k, W):

alpha = np.array([A[0, 0], A[1, 1], A[0, 1], A[0, 2], A[1, 2], k[0], k[1]])

P = alpha

for i in range(len(W)):

R, t = (W[i])[:, :3], (W[i])[:, 3]

#旋轉矩陣轉換為一維向量形式

zrou = to_rodrigues_vector(R)

w = np.append(zrou, t)

P = np.append(P, w)

return P

#分解參數集合,得到對應的內參,外參,畸變矯正系數

def decompose_paramter_vector(P):

[alpha, beta, gamma, uc, vc, k0, k1] = P[0:7]

A = np.array([[alpha, gamma, uc],

[0, beta, vc],

[0, 0, 1]])

k = np.array([k0, k1])

W = []

M = (len(P) - 7) // 6

for i in range(M):

m = 7 + 6 * i

zrou = P[m:m+3]

t = (P[m+3:m+6]).reshape(3, -1)

#將旋轉矩陣一維向量形式還原為矩陣形式

R = to_rotation_matrix(zrou)

#依次拼接每幅圖的外參

w = np.concatenate((R, t), axis=1)

W.append(w)

W = np.array(W)

return A, k, W

#返回從真實世界坐標映射的圖像坐標

def get_single_project_coor(A, W, k, coor):

single_coor = np.array([coor[0], coor[1], coor[2], 1])

#'''

coor_norm = np.dot(W, single_coor)

coor_norm /= coor_norm[-1]

#r = np.linalg.norm(coor)

r = np.linalg.norm(coor_norm)

uv = np.dot(np.dot(A, W), single_coor)

uv /= uv[-1]

#畸變

u0 = uv[0]

v0 = uv[1]

uc = A[0, 2]

vc = A[1, 2]

#u = (uc * r**2 * k[0] + uc * r**4 * k[1] - u0) / (r**2 * k[0] + r**4 * k[1] - 1)

#v = (vc * r**2 * k[0] + vc * r**4 * k[1] - v0) / (r**2 * k[0] + r**4 * k[1] - 1)

u = u0 + (u0 - uc) * r**2 * k[0] + (u0 - uc) * r**4 * k[1]

v = v0 + (v0 - vc) * r**2 * k[0] + (v0 - vc) * r**4 * k[1]

'''

uv = np.dot(W, single_coor)

uv /= uv[-1]

# 透鏡矯正

x0 = uv[0]

y0 = uv[1]

r = np.linalg.norm(np.array([x0, y0]))

k0 = 0

k1 = 0

x = x0 * (1 + r ** 2 * k0 + r ** 4 * k1)

y = y0 * (1 + r ** 2 * k0 + r ** 4 * k1)

#u = A[0, 0] * x + A[0, 2]

#v = A[1, 1] * y + A[1, 2]

[u, v, _] = np.dot(A, np.array([x, y, 1]))

'''

return np.array([u, v])

#返回所有點的真實世界坐標映射到的圖像坐標與真實圖像坐標的殘差

def value(P, org_W, X, Y_real):

M = (len(P) - 7) // 6

N = len(X[0])

A = np.array([

[P[0], P[2], P[3]],

[0, P[1], P[4]],

[0, 0, 1]

])

Y = np.array([])

for i in range(M):

m = 7 + 6 * i

#取出當前圖像對應的外參

w = P[m:m + 6]

# 不用旋轉矩陣的變換是因為會有精度損失

'''

R = to_rotation_matrix(w[:3])

t = w[3:].reshape(3, 1)

W = np.concatenate((R, t), axis=1)

'''

W = org_W[i]

#計算每幅圖的坐標殘差

for j in range(N):

Y = np.append(Y, get_single_project_coor(A, W, np.array([P[5], P[6]]), (X[i])[j]))

error_Y = np.array(Y_real).reshape(-1) - Y

return error_Y

#計算對應jacobian矩陣

def jacobian(P, WW, X, Y_real):

M = (len(P) - 7) // 6

N = len(X[0])

K = len(P)

A = np.array([

[P[0], P[2], P[3]],

[0, P[1], P[4]],

[0, 0, 1]

])

res = np.array([])

for i in range(M):

m = 7 + 6 * i

w = P[m:m + 6]

R = to_rotation_matrix(w[:3])

t = w[3:].reshape(3, 1)

W = np.concatenate((R, t), axis=1)

for j in range(N):

res = np.append(res, get_single_project_coor(A, W, np.array([P[5], P[6]]), (X[i])[j]))

#求得x, y方向對P[k]的偏導

J = np.zeros((K, 2 * M * N))

for k in range(K):

J[k] = np.gradient(res, P[k])

return J.T

#將旋轉矩陣分解為一個向量并返回,Rodrigues旋轉向量與矩陣的變換,最后計算坐標時并未用到,因為會有精度損失

def to_rodrigues_vector(R):

p = 0.5 * np.array([[R[2, 1] - R[1, 2]],

[R[0, 2] - R[2, 0]],

[R[1, 0] - R[0, 1]]])

c = 0.5 * (np.trace(R) - 1)

if np.linalg.norm(p) == 0:

if c == 1:

zrou = np.array([0, 0, 0])

elif c == -1:

R_plus = R + np.eye(3, dtype='float')

norm_array = np.array([np.linalg.norm(R_plus[:, 0]),

np.linalg.norm(R_plus[:, 1]),

np.linalg.norm(R_plus[:, 2])])

v = R_plus[:, np.where(norm_array == max(norm_array))]

u = v / np.linalg.norm(v)

if u[0] < 0 or (u[0] == 0 and u[1] < 0) or (u[0] == u[1] and u[0] == 0 and u[2] < 0):

u = -u

zrou = math.pi * u

else:

zrou = []

else:

u = p / np.linalg.norm(p)

theata = math.atan2(np.linalg.norm(p), c)

zrou = theata * u

return zrou

#把旋轉矩陣的一維向量形式還原為旋轉矩陣并返回

def to_rotation_matrix(zrou):

theta = np.linalg.norm(zrou)

zrou_prime = zrou / theta

W = np.array([[0, -zrou_prime[2], zrou_prime[1]],

[zrou_prime[2], 0, -zrou_prime[0]],

[-zrou_prime[1], zrou_prime[0], 0]])

R = np.eye(3, dtype='float') + W * math.sin(theta) + np.dot(W, W) * (1 - math.cos(theta))

return R

7.結果

拍攝的不同角度,不同高度的圖像

a639fb38-6362-11ed-8abf-dac502259ad0.png

運行結果:

a65ce8c8-6362-11ed-8abf-dac502259ad0.png

拍照的手機是華為p9,后置攝像頭是1200萬像素。

內部參數矩陣是為:

[ 9.95397796e+02, -5.74043156e+00, 5.30659959e+02, 0.00000000e+00, 1.04963119e+03, 6.55565437e+02, 0.00000000e+00, 0.00000000e+00, 1.00000000e+00]

因為代碼是以一個方格為一個單位,沒有考慮單位長度,所以要求真實的參數應該乘一個單位長度,博主采用的方格的尺寸是2.98cm的,自己拿excel畫的,get了一個新技能~~

審核編輯:郭婷

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 手機
    +關注

    關注

    35

    文章

    6896

    瀏覽量

    158004
  • 計算機
    +關注

    關注

    19

    文章

    7534

    瀏覽量

    88451

原文標題:三、算法實現

文章出處:【微信號:今日光電,微信公眾號:今日光電】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    請問做反射式血氧飽和度測量時如何進行標定呢?

    請問做反射式血氧飽和度測量時如何進行標定呢? 目前已完成透射式血氧飽和度測量儀的設計和實現,采用的Fluke的生命體征模擬儀Prosim8進行標定的,儀器有一個模擬手指,可以將指套式探頭夾在模擬
    發表于 01-08 06:42

    橋信號發生器的工作原理和結構

    橋信號發生器是一種基于文橋電路的信號發生器,它能夠產生穩定且頻率可調的正弦波信號。以下是對文橋信號發生器的工作原理和結構的詳細闡述。
    的頭像 發表于 09-25 16:28 ?864次閱讀
    文<b class='flag-5'>氏</b>橋信號發生器的工作原理和結構

    傳感器靜態標定的主要步驟是什么

    傳感器靜態標定的主要步驟通常包括以下幾個方面: 一、準備階段 確定標定范圍 :首先,需要明確傳感器的全量程(即測量范圍),這是標定工作的基礎。 準備標準設備 :利用標準儀器或設備產生已知的非電量(如
    的頭像 發表于 09-19 17:02 ?1583次閱讀

    基于CW32的儀表精度測量實現(三):標定與校準

    標定的概念 標定是一種校準過程,它通過與已知的標準或參考值進行比較來確保測量設備、儀器或系統的準確性和可靠性。這個過程涉及調整設備,以消除系統誤差和提高測量結果與真實值的一致性,從而確保數據的精確度
    的頭像 發表于 09-02 10:07 ?386次閱讀
    基于CW32的儀表精度測量<b class='flag-5'>實現</b>(三):<b class='flag-5'>標定</b>與校準

    基于DCC和標定的相機鏡頭畸變校正

    電子發燒友網站提供《基于DCC和標定的相機鏡頭畸變校正.pdf》資料免費下載
    發表于 08-29 10:37 ?0次下載
    基于DCC和<b class='flag-5'>張</b><b class='flag-5'>氏</b><b class='flag-5'>標定</b>的相機鏡頭畸變校正

    橋振蕩器的原理和應用

    橋振蕩器(Wien Bridge Oscillator),又稱文電橋振蕩電路或RC橋式正弦波振蕩器,是一種基于RC串并聯網絡實現的振蕩電路,由德國物理學家Max Wien在1891年發明。這種振蕩器在電子通信、信號處理、科
    的頭像 發表于 07-30 18:06 ?3179次閱讀

    平行電流線對羅線圈的影響

    在電力系統和電子測量領域,羅線圈(Rogowski Coil)是一種常用的非接觸式電流測量裝置,它通過感應被測電流產生的磁場來測量電流的大小。然而,當羅線圈附近存在平行電流線時,這些平行電流線
    的頭像 發表于 07-16 11:30 ?1132次閱讀
    平行電流線對羅<b class='flag-5'>氏</b>線圈的影響

    線圈用什么材質做的

    線圈(Rogowski Coil)是一種用于測量電流的電磁感應設備,其工作原理基于法拉第電磁感應定律。羅線圈具有許多優點,如高頻響應好、測量范圍廣、不受被測電流頻率的影響等,因此在電力系統
    的頭像 發表于 07-12 15:31 ?684次閱讀

    線圈電流傳感器的工作原理、結構特點及應用

    傳感器的工作原理 電磁感應原理 羅線圈電流傳感器的工作原理基于電磁感應原理。當導體中的電流發生變化時,會在其周圍產生變化的磁場。這個變化的磁場會在線圈中產生感應電動勢,從而實現對電流的測量。 羅線圈的結構 羅
    的頭像 發表于 07-12 15:29 ?2.4w次閱讀

    線圈輸出的電壓信號是直流電壓嗎

    線圈輸出的信號類型取決于被測電流的性質。當被測電流為直流時,羅線圈輸出的信號為直流電壓;當被測電流為交流時,羅線圈輸出的信號為交流電壓。羅線圈(Rogowski coil)是
    的頭像 發表于 07-12 15:25 ?865次閱讀

    線圈輸出是什么信號

    線圈(Rogowski Coil)是一種用于測量電流的電磁感應器件,廣泛應用于電力系統、電氣設備和電子測量等領域。羅線圈的輸出信號是電壓信號,其大小與通過線圈的電流變化率成正比。 一、羅線圈
    的頭像 發表于 07-12 15:06 ?1017次閱讀

    線圈可以測直流嗎

    線圈(Rogowski coil),又稱為羅戈夫斯基線圈或羅電流傳感器,是一種用于測量電流的電磁感應裝置。它具有結構簡單、響應速度快、測量范圍廣等優點,在電力系統、工業自動化、科研等領域得到
    的頭像 發表于 07-12 15:03 ?1421次閱讀

    采用羅線圈來測試脈沖磁場的方法

    采用羅線圈這一有效的工具。本文將介紹采用羅線圈測試脈沖磁場的方法及其在實際應用中的重要性。 羅線圈的原理和結構: 羅線圈是一種用于測量磁場的傳感器,通常由繞制成圈狀的導線組成。
    的頭像 發表于 07-05 15:05 ?532次閱讀
    采用羅<b class='flag-5'>氏</b>線圈來測試脈沖磁場的方法

    電流探頭柔性線圈的保養與維護

    線圈是一種重要的電氣元件,廣泛應用于各種電子設備和系統中。它由導線纏繞成的圓柱形結構組成,通常用于產生磁場或者用于電感器件。為了確保羅線圈的正常運行和延長其使用壽命,進行定期的保養和維護
    的頭像 發表于 05-28 09:54 ?365次閱讀
    羅<b class='flag-5'>氏</b>電流探頭柔性線圈的保養與維護

    TSMaster如何同時記錄標定變量和DBC信號至BLF文件

    和大家分享一下關于TSMaster軟件中同時記錄標定變量和DBC信號至BLF文件的實現方法。本文關鍵字:標定變量、DBC信號、BLF文件目錄Catalog1.加載
    的頭像 發表于 03-25 08:20 ?826次閱讀
    TSMaster如何同時記錄<b class='flag-5'>標定</b>變量和DBC信號至BLF文件
    主站蜘蛛池模板: 成人精品视频在线观看 | 中文字幕一区二区三区在线播放 | 午夜不卡av免费 | 全是肉的高h短篇列车 | 国产精品久久vr专区 | 熟妇内谢69XXXXXA片 | 99手机在线视频 | 99久久99久久免费精品蜜桃 | 动态抽插图视频 | 亚洲精品久久久无码一区二区 | 色欲精品久久人妻AV中文字幕 | 天天插天天射天天干 | 成人免费一区二区无码视频 | 久久不射视频 | 国产成人女人视频在线观看 | 中文字幕绝色少妇性 | 九九久久国产精品大片 | 91伊人久久大香线蕉 | 亚洲第一天堂无码专区 | 色多多旧版污污破解版 | 99热最新网站 | 欧美亚洲另类丝袜自拍动漫 | 国产97视频在线观看 | 天美传媒在线观看完整高清 | 日本高清在线一区二区三区 | 76人遣返航班上71人呈阳性 | 漂亮的保姆6在线观看中文 漂亮的保姆5电影免费观看完整版中文 | 曰产无码久久久久久精品 | a视频免费在线 | 久久精品动漫网一区二区 | 超级乱淫片午夜电影网99 | 高清无码中文字幕在线观看视频 | 久久精品国产欧美 | 国色天香社区视频免费高清3 | 久久热这里只有 精品 | 欧美丰满少妇久久无码精品 | 日韩高清一区二区三区不卡 | 色久久综合视频本道88 | 久久久久久电影 | 最近更新2019中文字幕国语 | 各种肉黄浪荡故事集 |