矩陣是什么我就不必介紹了,如果一個n*m(n行m列)的矩陣和a*b(a行b列)矩陣要相乘,那么必須滿足m==a這個條件。相加的話需要滿足n==a && m==b條件。
這里我們先介紹一些關鍵詞:
1、線性相關:
β = m*α1 + n*α2
數學稱β可以由向量組{α1,α2}線性表示,同時稱β,α1,α2為線性相關。
ps:反過來就是說假如β不能由{α1,α2}線性表示,則稱β,α1,α2為線性無關。
2、向量空間和子空間
在OA,OB,OZ張成的立體空間中任意向量β = m*OA + n*OB + k*OZ(m,n,k>0),β就是{OA,OB,OZ}的線性表示,當然假如m,n,k為任意實數,就是”張成“了xyz的全部空間了。
這里就有個名詞蹦出來了,就是子空間,假如我們把上面m,n,k為任意實數構成的空間叫做S,那么m,n,k>0構成的空間S1就是S的一個子空間。
一個向量組{α1,α2,α3....αn},這個向量組的所有線性組合生成一個向量合集:
{x1*α1 + x2*α2 + x3*α3 ...+xn*αn }且x1,x2...xn屬於R
這個向量集合稱為Span{α1,α2,α3....αn},稱為向量組{α1,α2,α3....αn}張成的向量空間。
3、向量空間的基
對於向量空間S中的一個有序向量組{α1,α2,α3....αn},假如α1,α2,α3....αn線性無關,且任意向量β = x1*α1 + x2*α2 + x3*α3 ...+xn*αn
那么我們稱向量組{α1,α2,α3....αn}為向量空間S的一個基,向量組的向量個數稱為S的維數,有序實數組{x1,x2,x3...xn}為向量β在基{α1,α2,α3....αn}上的坐標。
4、仿射坐標系
在空間中選取一點做為O原點,從O為起點做任意三個不共面的向量α1,α2,α3,這種方式建立的坐標系叫做仿射坐標系,寫成:{O;α1,α2,α3},那么任意一個向量α可以用實數組(x,y,z)來表示,既:α = x*α1+y*α2+z*α3,這里我們稱(x,y,z)為向量α的坐標。
ps:仿射坐標系右分為左手和右手坐標系,具體紙面上的區別就是z軸朝紙面內還是紙面外,如果用手來表示就是食指中指拇指成90度夾角,大拇指朝x軸,食指朝y軸,那么中指和z軸的朝向就是區分左右手了。
5、轉置矩陣
將矩陣的行列互換得到的新矩陣稱為轉置矩陣
矩陣可以把一個向量變換成另外一個向量(也就是向量變換)。
6、矢量和向量
矢:空間中的一個直線段,當規定其兩個端點中一個為起始點,一個位終止點,這個線段就稱為一個矢。
向量:具有同樣長度和方向的失的集合稱為一個向量,單獨的一個矢為向量的一個代表。
7、透視空間
假如我們站在現實世界中的一條很遠的馬路上,馬路盡頭在我們眼中就交匯成了一個點,這種現象被稱為透視現象,同樣的存在這種現象的空間被稱為透視空間。透視現象在現實生活中無處不在,計算機視覺中也遵循這個原理。在笛卡爾空間中,兩條平行線是永遠不會相交的,但是在透視空間中,兩條平行線會相交於一點,這是兩種空間最大的區別。
首先想像有個絕對不變的坐標系,記為W,然后以W為參照,建立兩個坐標系O1和O2, O1的原點在W的(1,1)處,O2的原點在W的(2,2)處。那么W中的一個點P(x,y)在O1中將變為P(x-1,y-1),在O2中將是P(x-2, y-2),這樣同一個點P在不同的坐標系下就具有了不同的表示。這會產生一個問題:顯然,P點在二維空間的位置是唯一的,是與坐標系無關的,而不同坐標系下的表示看上去體現不了這種無關性。
我們使用的是坐標系這樣一個概念,坐標系忽略了坐標原點所具有的重要意義:正是原點標示了該坐標系處於哪個參照位置。如果用矩陣來表示一個二維坐標系,將會是如下形式:
|1 0|
|0 1| ,其中(1 0)T表示一個基矢量,(0 1)T表示另一個基矢量,它們互相垂直,因此能利用它們標記整個二維空間。
(x, y)|1 0| = (x, y)
|0 1|
這就是二維坐標的實際意義。
現在考慮將坐標原點(a,b)也引入到這個矩陣表示中來:
|1 0 |
|0 1 |
|a b |
我們用這個矩陣可以表示二維空間中任意位置的一個坐標系,當然,這個坐標系的基矢量可以不為(0 1)T和(1 0)T,為了和坐標系區分,我們稱這種新表示為標架表示。
好,問題來了,如果我們仍然用(x y)來表示點P,那么根據矩陣的乘法規則,我們無法完成其乘法:mx N 的矩陣只能和 N xk的矩陣相乘。解決的辦法就是: 給P點添一個尾巴,這個尾巴通常為1:P(x y 1),這就是P的齊次坐標,利用新的齊次坐標和矩陣相乘得到的結果為:
(x+a, y+b),這樣同一個點在不同標架下的不同表示最終會得到同一個計算結果,它反映了這樣一個事實:同一個點在不同標架下的不同表示其實是等價的,這一點恰恰是使用坐標系無法體現出來的。
顯然上面那個 3x2的矩陣和P的齊次表示相乘得到的不是齊次坐標,所以應該將它擴充成3x3的方陣:
|1 0 0|
|0 1 0|
|a b 1|
齊次點具有下列幾個性質:
1)如果實數a非零,則(x, y, x, w)和(ax, ay, az, aw)表示同一個點,類似於x/y = (ax)/( ay)。
2)三維空間點(x, y, z)的齊次點坐標為(x, y, z, 1.0),二維平面點(x,y)的齊次坐標為(x, y, 0.0, 1.0)。
3)當w不為零時,齊次點坐標(x, y, z, w)即三維空間點坐標(x/w, y/w, z/w);當w為零時,齊次點(x, y, z, 0.0)表示此點位於某方向的無窮遠處。
齊次坐標有什么優點呢?
1.它提供了用矩陣運算把二維、三維甚至高維空間中的一個點集從一個坐標系變換到另一個坐標系的有效方法。
2.它可以表示無窮遠的點。n+1維的齊次坐標中如果h=0,實際上就表示了n維空間的一個無窮遠點。對於齊次坐標[a,b,h],保持a,b不變, 點沿直線 ax+by=0 逐漸走向無窮遠處的過程。 第一:許多圖形應用涉及到幾何變換,主要包括平移、旋轉、縮放。以矩陣表達式來計算這些變換時,平移是矩陣相加,旋轉和縮放則是矩陣相乘,綜合起來可以表示為p' = p *m1+ m2(m1旋轉縮放矩陣, m2為平移矩陣, p為原向量 ,p'為變換后的向量)。引入齊次坐標的目的主要是合並矩陣運算中的乘法和加法,表示為p' = p*M的形式。即它提供了用矩陣運算把二維、三維甚至高維空間中的一個點集從一個坐標系變換到另一個坐標系的有效方法。
其次,它可以表示無窮遠的點。n+1維的齊次坐標中如果h=0,實際上就表示了n維空間的一個無窮遠點。對於齊次坐標(a,b,h),保持a,b不變,|V|=(x1*x1,y1*y1,z1*z1)^1/2的過程就表示了標准坐標系中的一個點沿直線 ax+by=0 逐漸走向無窮遠處的過程。
實例:
前面我們從理論上理解了圖形學中圖形的變換過程,具體可以理解為如果要對一個圖形A進行變換,那么存在圖形A所處的相同原點的仿射空間SpaceA(或者說仿射空間SpaceA中原點處存在一個圖形A),這時候我們暫時忽略圖形A,只考慮SpaceA經過各種變換最終變換成另一個仿射空間SpaceB(或者說變換后的仿射空間SpaceA與另一個仿射空間SpaceB重合),因為仿射空間SpaceA變換后可能被伸縮或者被旋轉同時又移動了,那么仿射空間SpaceA中的圖形A同時跟着被變換成了另外的樣子,如下圖:
想像一下,假設把你自己當作一個“圖形”,這時候出現一個任務,就是讓躺在床上的你從家里出發去公司坐在辦公椅上上班寫代碼,你應該怎么做呢,首先你要起床(從平躺的向量變成豎着的向量,這就經歷了一個人體旋轉的過程),然后出發,經過一條長長的街道xxx路(從xxx路的起點路口到xxx路的終點路口,這就經歷了一個人體平移的過程),然后拐彎進入yyy路並且繼續行走(這就經歷了人體旋轉加人體平移兩個過程),然后進入公司走到辦公椅前坐下(從豎着站立狀態變成坐下的坐立狀態,這可以人為人體進行了形變縮放)。
這么一看,我們對於變換的理解就可以分解為旋轉、平移、縮放三個過程。
前面我們對齊次坐標的理解,知道了旋轉和縮放這兩個過程可以通過矩陣T進行線性變換處理,但是平移卻是需要將矩陣T擴充“平移維度”得到矩陣T'才能進行線性變換處理,所以數學上我們處理n維空間的圖形變換就要使用n+1維齊次坐標以及n+1行n+1列矩陣來得到。接下來我們就來具體推導二維仿射坐標系下的旋轉/平移/縮放。
1.矩陣操作仿射坐標系旋轉,還是老辦法,建立單位圓進行逆時針旋轉θ角(三角函數中規定逆時針旋轉為正角)的旋轉矩陣輔助推導,如下圖:
我們通過矩陣T_rotate旋轉變換仿射坐標系xoy到x1oy1,矩陣T_rotate的推導也是通過建立線性方程組解方程得到T_rotate的未知數。那么仿射坐標系所“容納”的原點圖形也就跟着變換了。因為旋轉變換不需要額外擴充成齊次坐標表示也能進行變換,所以我們忽略“平移維度”。
2.矩陣操作仿射坐標系縮放,建立輔助單位圓,如下圖:
上面我們首先推導了標准縮放,也就是xy縮放比例K相同,接下來縮放比例不同x縮放m/y縮放n,依舊是通過建立矩陣T_scale以及轉換成線性方程組就很容易得到矩陣T_scale了。
3.矩陣操作仿射坐標系平移,特殊情況來了!前面我們講過仿射坐標系平移是不能直接進行線性變換的,而需要擴充平移維度進行輔助計算,如下圖:
同樣的,因為二維平移只有xy軸兩個方向,我們建立仿射坐標系觀察,同時擴充“平移維度”,建立矩陣T_translate和線性方程組,就能得到我們需要的平移矩陣T_translate。
前面我們推了二維情況下仿射坐標系旋轉,縮放,平移的變換矩陣T_rotate,T_scale,T_translate,但是三個矩陣太不規范了,有的是2x2有的是3x3,有的使用了齊次坐標,有的又只使用了普通坐標,這對我們程序中進行計算是非常不友好的。之前我們說了平移變換是通過擴充“平移維度”來處理的,並不影響“旋轉維度”和“縮放維度”,同時GPU設計的重要指標之一就是極快速處理4x4及以下的矩陣計算,所以我們通過將T_rotate和T_scale擴充維度到T_translate的行列數,用來統一傳入GPU進行處理。
擴充方式如下圖:
這里我們只需要將“平移維度”填入“旋轉維度”和“縮放維度”就行了,如果不放心的話我們就驗證一下擴充后的矩陣的計算結果,如下圖:
縮放矩陣同理也可以計算出來結果。
這么一來我們就把旋轉平移縮放的變換全部使用齊次坐標和3x3矩陣給統一化了,但是我們還是覺得麻煩,因為我處理一個圖形變換居然還需要使用三個矩陣去分別計算,我們能不能直接把這三個矩陣通過什么方法變成一個呢,接下來我們來觀察矩陣乘法的性質,繼續由簡入難。
假設我們有兩個2x2的矩陣T1,T2來變換一個2x1的矩陣V(2x1的矩陣也就是一個二維向量),按照平常方法我們肯定就是先使用T1*V變換得到V1,然后再使用T2*V1變換得到V2,整個過程我們記為T2*(T1*V)。我們希望優化中間環節,盡量少的直接將V帶入運算,希望變換成(T2*T1)*V,先將T2*T1得到矩陣T3,然后將T3*V變換得到V2,此時我們的問題就變成T2*T1得到的矩陣T3是否起到了T1、T2分別變換V相同的作用。
我們知道矩陣A*矩陣B的規則就是矩陣A的行m與矩陣B的列n的元素分別相乘再相加最終得到的元素放置於結果矩陣C的m行n列中,那么上面的問題矩陣T1*V得到的V1再使用T2*V1得到的結果和T2*T1得到T3*V的結果相同,因為這種矩陣乘法的計算規律在獨立出每個行列計算后得到單個元素的分解式符合乘法分配律(c*(a+b) = c*a + c*b)運算然后拆分組合成另外的乘法分配律的組合體,這時候我們必須通過實際運算來觀察,因為紅色語言的描敘都過於復雜到無法直接心算,如下圖:
最后的乘法分配組合經過分解拆分繼續組合成乘法分配律組合體。
這時候我們可以將原本的旋轉平移縮放三次矩陣操作T_rotate*(T_translate*(T_scale*Vector))變化成T_all(T_all = T_rotate*(T_translate*T_scale)) *Vector,保證Vector經過一個矩陣的一次變換達到目標。
原文鏈接:https://blog.csdn.net/yinhun2012/article/details/79544205
參考博客:https://blog.csdn.net/yinhun2012/article/details/79566148
https://blog.csdn.net/yinhun2012/article/details/79544205
http://blog.sina.com.cn/s/blog_758521400102voww.html
前面我們從理論上理解了圖形學中圖形的變換過程,具體可以理解為如果要對一個圖形A進行變換,那么存在圖形A所處的相同原點的仿射空間SpaceA(或者說仿射空間SpaceA中原點處存在一個圖形A),這時候我們暫時忽略圖形A,只考慮SpaceA經過各種變換最終變換成另一個仿射空間SpaceB(或者說變換后的仿射空間SpaceA與另一個仿射空間SpaceB重合),因為仿射空間SpaceA變換后可能被伸縮或者被旋轉同時又移動了,那么仿射空間SpaceA中的圖形A同時跟着被變換成了另外的樣子,如下圖:
想像一下,假設把你自己當作一個“圖形”,這時候出現一個任務,就是讓躺在床上的你從家里出發去公司坐在辦公椅上上班寫代碼,你應該怎么做呢,首先你要起床(從平躺的向量變成豎着的向量,這就經歷了一個人體旋轉的過程),然后出發,經過一條長長的街道xxx路(從xxx路的起點路口到xxx路的終點路口,這就經歷了一個人體平移的過程),然后拐彎進入yyy路並且繼續行走(這就經歷了人體旋轉加人體平移兩個過程),然后進入公司走到辦公椅前坐下(從豎着站立狀態變成坐下的坐立狀態,這可以人為人體進行了形變縮放)。
這么一看,我們對於變換的理解就可以分解為旋轉、平移、縮放三個過程。
前面我們對齊次坐標的理解,知道了旋轉和縮放這兩個過程可以通過矩陣T進行線性變換處理,但是平移卻是需要將矩陣T擴充“平移維度”得到矩陣T'才能進行線性變換處理,所以數學上我們處理n維空間的圖形變換就要使用n+1維齊次坐標以及n+1行n+1列矩陣來得到。接下來我們就來具體推導二維仿射坐標系下的旋轉/平移/縮放。
1.矩陣操作仿射坐標系旋轉,還是老辦法,建立單位圓進行逆時針旋轉θ角(三角函數中規定逆時針旋轉為正角)的旋轉矩陣輔助推導,如下圖:
我們通過矩陣T_rotate旋轉變換仿射坐標系xoy到x1oy1,矩陣T_rotate的推導也是通過建立線性方程組解方程得到T_rotate的未知數。那么仿射坐標系所“容納”的原點圖形也就跟着變換了。因為旋轉變換不需要額外擴充成齊次坐標表示也能進行變換,所以我們忽略“平移維度”。
2.矩陣操作仿射坐標系縮放,建立輔助單位圓,如下圖:
上面我們首先推導了標准縮放,也就是xy縮放比例K相同,接下來縮放比例不同x縮放m/y縮放n,依舊是通過建立矩陣T_scale以及轉換成線性方程組就很容易得到矩陣T_scale了。
3.矩陣操作仿射坐標系平移,特殊情況來了!前面我們講過仿射坐標系平移是不能直接進行線性變換的,而需要擴充平移維度進行輔助計算,如下圖:
同樣的,因為二維平移只有xy軸兩個方向,我們建立仿射坐標系觀察,同時擴充“平移維度”,建立矩陣T_translate和線性方程組,就能得到我們需要的平移矩陣T_translate。
前面我們推了二維情況下仿射坐標系旋轉,縮放,平移的變換矩陣T_rotate,T_scale,T_translate,但是三個矩陣太不規范了,有的是2x2有的是3x3,有的使用了齊次坐標,有的又只使用了普通坐標,這對我們程序中進行計算是非常不友好的。之前我們說了平移變換是通過擴充“平移維度”來處理的,並不影響“旋轉維度”和“縮放維度”,同時GPU設計的重要指標之一就是極快速處理4x4及以下的矩陣計算,所以我們通過將T_rotate和T_scale擴充維度到T_translate的行列數,用來統一傳入GPU進行處理。
擴充方式如下圖:
這里我們只需要將“平移維度”填入“旋轉維度”和“縮放維度”就行了,如果不放心的話我們就驗證一下擴充后的矩陣的計算結果,如下圖:
縮放矩陣同理也可以計算出來結果。
這么一來我們就把旋轉平移縮放的變換全部使用齊次坐標和3x3矩陣給統一化了,但是我們還是覺得麻煩,因為我處理一個圖形變換居然還需要使用三個矩陣去分別計算,我們能不能直接把這三個矩陣通過什么方法變成一個呢,接下來我們來觀察矩陣乘法的性質,繼續由簡入難。
假設我們有兩個2x2的矩陣T1,T2來變換一個2x1的矩陣V(2x1的矩陣也就是一個二維向量),按照平常方法我們肯定就是先使用T1*V變換得到V1,然后再使用T2*V1變換得到V2,整個過程我們記為T2*(T1*V)。我們希望優化中間環節,盡量少的直接將V帶入運算,希望變換成(T2*T1)*V,先將T2*T1得到矩陣T3,然后將T3*V變換得到V2,此時我們的問題就變成T2*T1得到的矩陣T3是否起到了T1、T2分別變換V相同的作用。
我們知道矩陣A*矩陣B的規則就是矩陣A的行m與矩陣B的列n的元素分別相乘再相加最終得到的元素放置於結果矩陣C的m行n列中,那么上面的問題矩陣T1*V得到的V1再使用T2*V1得到的結果和T2*T1得到T3*V的結果相同,因為這種矩陣乘法的計算規律在獨立出每個行列計算后得到單個元素的分解式符合乘法分配律(c*(a+b) = c*a + c*b)運算然后拆分組合成另外的乘法分配律的組合體,這時候我們必須通過實際運算來觀察,因為紅色語言的描敘都過於復雜到無法直接心算,如下圖:
最后的乘法分配組合經過分解拆分繼續組合成乘法分配律組合體。
這時候我們可以將原本的旋轉平移縮放三次矩陣操作T_rotate*(T_translate*(T_scale*Vector))變化成T_all(T_all = T_rotate*(T_translate*T_scale)) *Vector,保證Vector經過一個矩陣的一次變換達到目標。————————————————版權聲明:本文為CSDN博主「羊羊2035」的原創文章,遵循CC 4.0 BY-SA版權協議,轉載請附上原文出處鏈接及本聲明。原文鏈接:https://blog.csdn.net/yinhun2012/article/details/79544205