四元素理解

旋轉變換_四元數

2017年03月29日 11:59:38 csxiaoshui 閱讀數:5686

1.簡介

四元數是另一種描述三維旋轉的方式,四元數使用4個分量來描述旋轉,四元數的描述方式如下:

?

q=s+xi+yj+zk,(s,x,y,z∈?)i2=j2=k2=ijk=?1

?

四元數的由來和復數很很大的關系,因此首先討論一下關于復數的內容。

1.1 復數

復數可以定義如下:

z=a+bia,b∈?i2=?1


復數常用的基本運算如下:

?

Complex
復數中一個比較重要的概念是共軛復數,將復數的虛部取相反數,得到它的共軛復數:

z=a+biz?=a?bi


復數的模,定義為:
complex2

?

復數還可以使用復平面來表示,復平面分為實軸和虛軸(類似于二維直角坐標系中的x軸和y軸),如下圖所示:

Complex3
當我們使用i去乘以一個復數時,當我們把得到的結果繪制在復平面上時,發現得到的位置正好是繞原點旋轉90度的效果。
complex4
于是可以猜測,復數的乘法和旋轉之間應該有某些關系。
我們可以通過定義一個復數

q=cosθ+isinθ


使用它作為一個旋轉的因子,當與復數相乘時,得到:
complex5
寫成矩陣的形式是:

[a′b′]=[cosθsinθ?sinθcosθ]?[ab]


這個公式正好是二維的旋轉公式,當把新的到的(a′+b′i)繪制在復平面上時,得到的正好是原來的點(a+bi)旋轉θ角之后的位置。

?

2. 四元數

既然使用復數的乘法可以描述二維的旋轉,那么拓展一個維度是否能表示三維旋轉呢,這個也正是四元數發明者William Hamilton最初的想法,也就是說使用

z=a+ib+jci2=j2=?1


但是很遺憾 “三維的復數”(這僅僅是我按概念杜撰的一個詞,并不存在)的乘法并不是閉合的。也就是說有可能兩個值相乘得到的結果并不是三維的復數。
William Hamilton經歷了無數個日日夜夜,他絞盡腦汁也沒想明白這個問題。終于有一天(1843年的一天),他意識到自己所需要的運算在三維空間中是不可能實現的,但在四維空間中是可以的,他是如此的興奮,以至于把四元數的公式刻在了愛爾蘭的一座橋上。

?

quaternions

四元數可以寫成下面的方式:

q=[s,v]s∈Rv∈?3


或者寫成

q=[s,xi+yj+zk]s,x,y,z∈?

?

2.1 四元數的運算

  • 兩四元數相加:
    A(a+bi+cj+dk) + B(e + fi + gj + hk) = C【 (a+e) + (b+f)i + (c+g)j + (d+h)k 】,實現代碼:
      // Quat的成員_v[4]代表四元數的(x,y,z,w)inline Quat operator + (const Quat& rhs) const{return Quat(_v[0] + rhs._v[0],_v[1] + rhs._v[1],_v[2] + rhs._v[2],_v[3] + rhs._v[3]);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 兩個四元數相減
    (sa,va) - (sb,vb) = (sa-sb,va-vb)
        inline Quat operator - (const Quat& rhs) const{return Quat(_v[0] - rhs._v[0],_v[1] - rhs._v[1],_v[2] - rhs._v[2],_v[3] - rhs._v[3]);}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 兩個四元數相乘
兩個四元數相乘的規則和多項式乘法一樣,
(a + i b + j c + k d)*(e + i f + j g + k h)
當有i,j,k參與時,規則如下:
i*i = j*j = k*k = -1
i*j = k,
j*i = -k
j*k = i,
k*j = -i
k*i = j,
i*k = -j
使用多項式乘法展開,可以得到:
a*e - b*f - c*g - d*h
+ i (b*e + a*f + c*h- d*g)
+ j (a*g - b*h+ c*e + d*f)
+ k (a*h + b*g - c*f + d*e)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

實現代碼:

        inline const Quat operator*(const Quat& rhs) const{return Quat( rhs._v[3]*_v[0] + rhs._v[0]*_v[3] + rhs._v[1]*_v[2] - rhs._v[2]*_v[1],rhs._v[3]*_v[1] - rhs._v[0]*_v[2] + rhs._v[1]*_v[3] + rhs._v[2]*_v[0],rhs._v[3]*_v[2] + rhs._v[0]*_v[1] - rhs._v[1]*_v[0] + rhs._v[2]*_v[3],rhs._v[3]*_v[3] - rhs._v[0]*_v[0] - rhs._v[1]*_v[1] - rhs._v[2]*_v[2] );}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 兩四元數相除
    四元數一般來說不定義除法,因為四元數的乘法運算并不滿足交換律。一般有四元數的類定義除法是,其實定義的是q1?q2?1

,其中
q?1=conj(q)/|q2|,為什么定義這么奇怪的表達式呢,其實是為了讓q?q?1=1

  • ,這個結論很容易推導出來。conj(q)稱為q的共軛表達式,
    con(q) = w - xi - yj -zk,只需要四元數向量部分取負即可
    實現如下:
        inline const Quat operator/(const Quat& denom) const{return ( (*this) * denom.inverse() );}/// Conjugateinline Quat conj () const{return Quat( -_v[0], -_v[1], -_v[2], _v[3] );}/// Multiplicative inverse method: q^(-1) = q^*/(q.q^*)inline const Quat inverse () const{return conj() / length2();}value_type length2() const{return _v[0]*_v[0] + _v[1]*_v[1] + _v[2]*_v[2] + _v[3]*_v[3];}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

2.2 四元數的旋轉

四元數在三維圖形學領域的一個重要應用是用它來描述三維旋轉,四元數從某種意義上來說是四維空間的旋轉,難以想象,了解它的結論和使用場景更加重要。歐拉定理告訴我們任意三維旋轉都可以使用一個旋轉向量和旋轉角度來描述。因此四元數往往是使用旋轉軸和旋轉角來構造的,構造它的方法如下:


2.2.1 繞向量u旋轉角度θ

構造四元數

可以用下面的四元數來表示:

u??=(ux,uy,uz)=uxi+uyj+uzk

?

q=eθ2(uxi+uyj+uzk)=cosθ2+(uxi+uyj+uzk)sinθ2


實現代碼如下:

?

   void makeRotate(value_type angle, value_type x, value_type y, value_type z){const value_type epsilon = 1e-7;value_type length = sqrt(x*x + y*y + z*z);if (length < epsilon){*this = Quat();return;}value_type  inversenorm = 1.0 / length;value_type  coshalfangle = cos(0.5*angle);value_type  sinhalfangle = sin(0.5*angle);_v[0] = x * sinhalfangle * inversenorm;_v[1] = y * sinhalfangle * inversenorm;_v[2] = z * sinhalfangle * inversenorm;_v[3] = coshalfangle;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2.2.2 從一個向量旋轉到另一個向量構造四元數

按照最原始的想法,從一個向量旋轉到另一個向量,那么旋轉軸可以通過兩個向量的叉乘得到,旋轉角度可以通過兩個向量間的夾角得到。(向量間的夾角的余弦可以通過兩向量點乘去除以它們的模,再通過反余弦函數計算),得到旋轉軸和旋轉角度之后就轉換成2.2.1中的情形了。
也就是說最初的代碼如下:

void makeRotate(Vec3<value_type>& u,  Vec3<value_type>& v){u.normalize();v.normalize();double costheta = u*v;double angle = acos(costheta);Vec3<value_type> w = u^v;w.normalize();makeRotate(angle, w.x(), w.y(), w.z());}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

有一種特殊情況需要考慮:兩向量共線(包括方向相同和方向相反,也就是夾角是0度和180度的情形)

void makeRotate(const Vec3<value_type>& from, const Vec3<value_type>& to){const value_type epsilon = 1e-7;value_type length1 = from.length();value_type length2 = to.length();value_type cosangle = from*to / (length1*length2);if (fabs(cosangle - 1) < epsilon){makeRotate(0.0, 0.0, 0.0, 1.0);}else if (fabs(cosangle + 1.0) < epsilon){Vec3<value_type> tmp;if ((fabs(from.x())) < fabs(from.y())){if (fabs(from.x()) < fabs(from.z())){tmp.set(1.0, 0.0, 0.0);}else{tmp.set(0.0, 0.0, 1.0);}}else if (fabs(from.y()) < fabs(from.z())){tmp.set(0.0, 1.0, 0.0);}else{tmp.set(0.0, 0.0, 1.0);}Vec3<value_type> fromd(from.x(), from.y(), from.z());Vec3<value_type> axis(fromd^tmp);axis.normalize();_v[0] = axis[0];_v[1] = axis[1];_v[2] = axis[2];_v[3] = 0.0;}else{Vec3<value_type> axis(from^to);value_type angle = acos(cosangle);makeRotate(angle, axis.x(), axis.y(), axis.z());}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

上述的代碼改進了之前代碼,但是在計算過程中使用了反三角函數(相對比較耗時),可以通過三角函數公式,簡化,不需要調用反三角函數:

sinθ2cosθ2=1?cosθ2 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄√=1+cosθ2 ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄√


代碼可以修改為:

?

//省略部分相同的代碼else{Vec3<value_type> axis(from^to);//替換成下面幾行//value_type angle = acos(cosangle);//makeRotate(angle, axis.x(), axis.y(), axis.z());axis.normalize();value_type half_cos = sqrt(0.5*(1+cosangle));value_type half_sin = sqrt(0.5*(1-cosangle));_v[0] = axis[0] * half_sin;_v[1] = axis[1] * half_sin;_v[2] = axis[2] * half_sin;_v[3] = half_cos;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

這樣修改之后,去掉了算法中復雜的三角函數運算,事實上還可以進一步改進計算過程,考慮到代碼中多次的歸一化(normalize)的操作,需要進行多次開方運算,為了簡化,可以考慮:

||u×v||=|u|.|v|.|sinθ|

?

?

sinθ=2sinθ2cosθ2

?

同時有:

sqrt(a)sqrt(b)=sqrt(ab)

?

于是代碼可以修改為:

            else{value_type normFromAndTo = sqrt(from.length2()*to.length2());value_type cos_theta = from * to / normFromAndTo;value_type half_cos = sqrt(0.5 * (1+cos_theta));value_type half_sin = sqrt(0.5 * (1-cos_theta));Vec3<value_type> axis = from^to / (normFromAndTo*2*half_sin * half_cos);_v[0] = axis[0]*half_sin;_v[1] = axis[1]*half_sin;_v[2] = axis[2]*half_sin;_v[3] = half_cos;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

注意到_v[0]到_v[3]中乘以half_sin,之前axis計算的分母中就有half_sin,也就是說這一項可以被化簡掉,于是代碼簡化成:

        else{value_type normFromAndTo = sqrt(from.length2()*to.length2());value_type cos_theta = from * to / normFromAndTo;value_type half_cos = sqrt(0.5 * (1+cos_theta));Vec3<value_type> axis = from^to / (normFromAndTo*2 * half_cos);_v[0] = axis[0];_v[1] = axis[1];_v[2] = axis[2];_v[3] = half_cos;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

2.2.3 從四元數獲取旋轉矩陣和旋轉角

這個過程是上面的反過程,根據之前描述的公式反算就可以,得到的公式是:

 //設四元數是 xi+yj+zk+w,那么旋轉角度和旋轉軸(a,b,c)是:
angle = 2 * acos(w)
a = x / sqrt(1-w*w)
b = y / sqrt(1-w*w)
c = z / sqrt(1-w*w)
  • 1
  • 2
  • 3
  • 4
  • 5

推導過程如下:
有之前的公式可以知道: w=cos(θ/2)

可以得到 角度 θ=2?acos(w)

?

x=a?sin(θ/2)y=b?sin(θ/2)z=c?sin(θ/2)


先分析x這個等式,帶入求出的θ角,得到:

a=x/sin(acos(w))

,參考下圖:
sin(acosw)
得到 sin(acosw) = sqrt(1-w*w),同理可以推出其他的結論。
但是還需要考慮其他兩個特殊情況:也就是共線的情形(角度θ是0度或者180度)

?

  • 0度的情況:
    當時0度的時候,得到w=1,會導致計算公式中分母是0,除以0出現無窮大,因此需要單獨討論

  • 180度的情況
    當180度是 w=0,可以通過計算得到
    a = x, b=y,c=z
    計算過程是正確的,因此這種情況不需要特殊的去分析。
    綜合上面整體的描述,代碼如下:

        void getRotate(value_type& angle, value_type& x, value_type& y, value_type& z) const {Quat q1 = *this;if (_v[3] > 1)q1.normalize();angle = 2 * acos(q1.w());value_type s = sqrt(1 - q1.w()*q1.w());if (s < 1e-6){x = q1.x();y = q1.y();z = q1.z();}else{x = q1.x() / s;y = q1.y() / s;z = q1.z() / s;}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

2.3 向量使用四元數進行旋轉

這么辛苦寫了四元數的類,為的就是使用它對頂點和向量進行旋轉的操作,也就是說我們需要完成下面的函數實現:

        //Rotate a vector by this quaternionVec3<value_type> operator* (const Vec3<value_type>& v);
  • 1
  • 2

四元數變換向量的算法如下:
1. 創建一個以v為虛部的純虛的向量,(v.x + v.y + v.z + 0)
2. 左乘四元數 q 接著右乘四元數q的共軛四元數 q*
3. 計算得到的結果也是一個純的四元數,它的虛部就是變換之后的向量v’
盡管這樣做可以得到變換后的向量,如果計算過程完全按照四元數乘法法則去展開計算,計算量略大 ,可以使用下面的方式優化一下:

        Vec3<value_type> operator* (const Vec3<value_type>& v){// nVidia SDK implementationVec3<value_type> uv, uuv;Vec3<value_type> qvec(_v[0], _v[1], _v[2]);uv = qvec ^ v;uuv = qvec ^ uv;uv *= ( 2.0f * _v[3] );uuv *= 2.0f;return v + uv + uuv;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

2.4 四元數的插值

使用四元數來表示旋轉,在插值時非常的方便和平滑,如果使用歐拉角來進行插值運算,除了會出現萬向節死鎖外,插值的效果顯得十分的生硬。四元數的球面插值使用下面的公式:

這里寫圖片描述

其中:
- qm:插值的四元數
- qa: 插值四元數的第一個值(起點)
- qb:插值四元數的第二個值(終點)
- t: (0.0,1.0)之間的一個數
- θ

: qa和qb夾角的一半

實現如下:

void dslerp( value_type t, const Quat& from, const Quat& to )
{const double epsilon = 0.00001;double omega, cosomega, sinomega, scale_from, scale_to ;osg::Quat quatTo(to);// this is a dot productcosomega = from.asVec4() * to.asVec4();if ( cosomega <0.0 ){cosomega = -cosomega;quatTo = -to;}if( (1.0 - cosomega) > epsilon ){omega= acos(cosomega) ;  // 0 <= omega <= Pi (see man acos)sinomega = sin(omega) ;  // this sinomega should always be +ve so// could try sinomega=sqrt(1-cosomega*cosomega) to avoid a sin()?scale_from = sin((1.0-t)*omega)/sinomega ;scale_to = sin(t*omega)/sinomega ;}else{/* --------------------------------------------------The ends of the vectors are very closewe can use simple linear interpolation - no needto worry about the "spherical" interpolation-------------------------------------------------- */scale_from = 1.0 - t ;scale_to = t ;}*this = (from*scale_from) + (quatTo*scale_to);
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37

參考文獻:

  1. Understanding Quaternions
  2. 如何形象地理解四元數?知乎Yang Eninala的解答
  3. Quaternion
  4. Quaternion
  5. Maths - Quaternions
  6. Beautiful maths simplification: quaternion from two vectors
  7. Rotating vector3 by a quaternion
  8. quaternion vector product四元數變換向量算法的原理

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/251989.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/251989.shtml
英文地址,請注明出處:http://en.pswp.cn/news/251989.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

31、SAM文件中flag含義解釋工具--轉載

轉載&#xff1a;http://www.cnblogs.com/nkwy2012/p/6362996.html SAM是Sequence Alignment/Map 的縮寫。像bwa等軟件序列比對結果都會輸出這樣的文件。samtools網站上有專門的文檔介紹SAM文件。具體地址&#xff1a;http://samtools.sourceforge.net/SAM1.pdf很多人困惑SAM文…

《Head First設計模式》批注系列(一)——觀察者設計模式

最近在讀《Head First設計模式》一書&#xff0c;此系列會引用源書內容&#xff0c;但文章內容會更加直接&#xff0c;以及加入一些自己的理解。 觀察者模式&#xff08;有時又被稱為模型-視圖&#xff08;View&#xff09;模式、源-收聽者(Listener)模式或從屬者模式&#xff…

PYPL 4 月排行:Python 最流行,Java 還行不行?

開發四年只會寫業務代碼&#xff0c;分布式高并發都不會還做程序員&#xff1f; PYPL 發布了 4 月份的編程語言排行榜。 前五的分別是&#xff1a;Python、Java、Javascript、C# 和 PHP。可以看到&#xff0c;榜單沒有什么大變化&#xff0c;但是相比去年 4 月份&#xff0c;…

兩個向量的旋轉矩陣與四元素

兩向量的夾角 2017年06月20日 17:38:11 csxiaoshui 閱讀數&#xff1a;36764 怎么計算兩個向量間的夾角呢&#xff1f; 這里主要分兩種情況&#xff0c;對于二維向量和三維向量來分別討論。 1. 二維向量 二維向量的情況相對簡單&#xff0c;根據向量間的點乘關系 v1?v2|…

順序表

一、數據是如何在內存中存儲的&#xff1f; 32位系統中char&#xff0c;int型數據在內存中的存儲方式&#xff1a; char占1byte&#xff08;8bit&#xff09;int占4byte&#xff08;32bit&#xff09;假設我們有一個int類型的值&#xff0c;它從0x01開始&#xff0c;一個int占據…

Establishing SSL connection without server's identity verification is not recommended.

完全描述:Establishing SSL connection without servers identity verification is not recommended. According to MySQL 5.5.45, 5.6.26 and 5.7.6 requirements SSL connection must be established by default if explicit option isnt set. For compliance with existing …

四元素的真面目..........簡單粗暴

作者&#xff1a;Yang Eninala 鏈接&#xff1a;https://www.zhihu.com/question/23005815/answer/33971127 來源&#xff1a;知乎 著作權歸作者所有。商業轉載請聯系作者獲得授權&#xff0c;非商業轉載請注明出處。 根據我的理解&#xff0c;大多數人用漢密爾頓四元數就只…

2.自定義變量調節器

① 使用registerPlugin()方法來擴充變量調節器 該方法接收3個參數 1. 字符串modifier 2. 插件函數的名字 3. PHP回調函數 示例&#xff1a;自定義一個變量調節器&#xff0c;可以改變文字的顏色和大小 第一步&#xff1a;調用smarty對象的registerPlugin&#xff08;&#x…

SpringBoot2構建基于RBAC權限模型的駕校代理小程序后端

本項目是使用SpringBoot2構建的一套基于RBAC權限模型的后臺管理系統&#xff0c;前端是微信小程序。 項目地址: github.com/fuyunwang/D… 項目的緣由 最近接了個外包,主要是針對于駕校開發一個代理小程序。目的是為了方便駕校的管理來招攬學員,同時方便維護學員和代理信息。 項…

while read line的問題

循環中的重定向或許你應該在其他腳本中見過下面的這種寫法&#xff1a;while read linedo…done < file剛開始看到這種結構時&#xff0c;很難理解< file是如何與循環配合在一起工作的。因為循環內有很多條命令&#xff0c;而我們之前接觸的重定向都是為一條命令工作的。…

Linemod;理解

Linemod 代碼筆記 2019年03月11日 16:18:30 haithink 閱讀數&#xff1a;197 最近了解到 Linemod 這個模板匹配算法&#xff0c;印象不錯 準備仔細學習一下&#xff0c;先做點代碼筆記&#xff0c;免得后面不好回顧 目前的筆記基本上把 核心流程都分析得比較清楚了&#xff0…

Swift3中數組創建方法

轉載自&#xff1a;http://blog.csdn.net/bwf_erg/article/details/70858865 數組是由一組類型相同的元素構成的有序數據集合。數組中的集合元素是有 序的&#xff0c;而且可以重復出現。 1 數組創建 在Swift語言中&#xff0c;數組的類型格式為&#xff1a; Array<ElementT…

BZOJ 5249: [2018多省省隊聯測]IIIDX(貪心 + 線段樹)

題意 這一天&#xff0c;\(\mathrm{Konano}\) 接到了一個任務&#xff0c;他需要給正在制作中的游戲 \(\mathrm{《IIIDX》}\) 安排曲目 的解鎖順序。游戲內共有\(n\) 首曲目&#xff0c;每首曲目都會有一個難度 \(d\) &#xff0c;游戲內第 \(i\) 首曲目會在玩家 Pass 第 \(\lf…

手眼標定

Eye-in-hand和Eye-to-hand問題求解和實驗 2018年12月07日 00:00:40 百川木易 閱讀數 3018 2018/12/5 By Yang Yang&#xff08;yangyangipp.ac.cn&#xff09; 本文所有源碼和仿真場景文件全部公開&#xff0c;點擊Gitee倉庫鏈接。 文章目錄 問題描述Eye-in-hand問題求解公式…

RNN總結

RNN既可以表述為循環神 經網絡&#xff08;recurrent neural network&#xff09;&#xff0c;也可以表述為遞歸神經網絡&#xff08;recursive neural network&#xff09;&#xff0c;前者一般用于處理以時間序列為輸入的問題&#xff08;比如把一個句子看成詞組成的序列&…

Problem 2. number題解

number&#xff1a;數學二分圖匹配 首先&#xff0c;如果S<N,那么S1&#xff0c;S2...N這些數直接放在S1,S2...N的位置上(如果其他數x放在這些位置上面&#xff0c;這些數不放在對應位置&#xff0c;那么x一定能放在這些數放的位置&#xff0c;所以直接交換即可)所以可以直接…

SSD列子

一、介紹 本博文主要介紹實現通過SSD物體檢測方式實現工件裂紋檢測。裂紋圖像如下所示&#xff1a; 二、關于SSD算法 具體算法不再闡述&#xff0c;詳細請參考&#xff1a; https://blog.csdn.net/u013989576/article/details/73439202 https://blog.csdn.net/xiaohu2022/arti…

linux硬鏈接與軟鏈接

Linux 系統中有軟鏈接和硬鏈接兩種特殊的“文件”。 軟鏈接可以看作是Windows中的快捷方式&#xff0c;可以讓你快速鏈接到目標檔案或目錄。 硬鏈接則透過文件系統的inode來產生新檔名&#xff0c;而不是產生新檔案。 創建方法都很簡單&#xff1a; 軟鏈接&#xff08;符號鏈接…

int轉時間

int轉時間 public static string FormatDuration(int duration) { if (duration 0) return "00:00:00"; int hours duration / 3600; int minutes duration % 3600 / 60; int seconds duration % 3600 % 60; string _hours hours.ToString("00") &qu…

企業級區塊鏈現狀研究報告:小企業的投資總額是大企業的28倍

根據企業級區塊鏈現狀研究報告表明&#xff0c;當前企業采用區塊鏈技術的勢頭正在逐步增強。參與該報告的企業表示&#xff0c;區塊鏈投資今年共增長了 62% &#xff0c;預計到 2025 年區塊鏈將成為主流技術。其中&#xff0c;有 28% 的企業正在積極開展區塊鏈發展計劃。現在看…