Android Matrix 玫霎,Camera2橫屏情況下畫面方向錯誤問題
本文主要講解了Android Matrix對于圖像轉(zhuǎn)換的數(shù)學原理,文尾會給出Camera2在橫屏狀態(tài)下拔创,畫面方向錯誤(旋轉(zhuǎn)90°)的解決方案。
Matrix在android視圖應用中非常常見富蓄,比如照相剩燥,自定義view等,若要學習其邏輯原理需要有矩陣的數(shù)學知識立倍,最少要知道矩陣乘法的運算規(guī)則灭红。
Matrix本質(zhì)上是一個3×3的矩陣(本文會稱呼其為變換矩陣),如下圖口注,主要用來對坐標做變換映射比伏。
縮放
android中的矩陣轉(zhuǎn)換通過上圖的轉(zhuǎn)換矩陣乘以原坐標獲得新的坐標(矩陣不滿足乘法交換律,必須是轉(zhuǎn)換矩陣在前疆导,坐標矩陣在后赁项,否則的話轉(zhuǎn)換矩陣需要修改,各個位置含義與上圖不同)澈段。
講一個簡單的例子就能看懂是如何轉(zhuǎn)換的了:原坐標為x0,y0悠菜,變換矩陣為下圖中左側(cè)的矩陣,轉(zhuǎn)換后坐標為x1,y1败富,我們看下三者之間的關系悔醋。
可以得出
可以看出x坐標變換為原先的k1倍,y坐標變?yōu)樵鹊膋2倍兽叮。這也就是k1,k2位置為MSCALE_X芬骄,MSCALE_Y,的原因,這兩個位置決定了坐標的縮放鹦聪。
Matrix提供了兩個關于縮放的方法
void setScale(float sx, float sy);
void setScale(float sx, float sy, float px, float py);
前面兩個參數(shù)sx账阻,sy分別是X軸和Y軸的縮放比例;后面兩個參數(shù)px泽本,py淘太,則是用以確認以哪個點位中心進行縮放,若使用第一個方法,則相當于默認縮放點為坐標系原點(圖片左上角)蒲牧。
Matrix matrix = new Matrix()
matrix.setScale(2f, 2f, 100f, 100f);
經(jīng)過上邊的轉(zhuǎn)換后變換矩陣則變?yōu)椋?div id="obis6kb" class="image-package">
image.png
可以理解為縮放后又做了一次平移撇贺,上圖的變換矩陣乘以原坐標,可得:
位移
其實位移的數(shù)學原理其實我們也已經(jīng)了解了:
變換關系為:
矩陣表示為:
Matrix提供了一個位移方法
void setTranslate(float dx, float dy)
方法的參數(shù)很簡單冰抢,X軸方向的位移以及Y軸方向的位移松嘶。唯一需要了解的是,android的坐標系和我們平時習慣的不同挎扰,它是以左上角為原點喘蟆,向右為X軸正方向,向下為Y軸正方向鼓鲁。
錯切
錯切的矩陣轉(zhuǎn)換為:
可以獲得變換關系為:
一種x和y變換互相線性相關的趕腳。如下圖所示:這是k1和k2均為0.2時的錯切
void setSkew(float kx, float ky)
void setSkew(float kx, float ky, float px, float py)
錯切的方法一共有兩個港谊,參數(shù)類似于縮放變換骇吭。
旋轉(zhuǎn)
這個是本篇文章的重點,因為其很常用歧寺,且數(shù)學原理不是那么容易理解(其實認真一點的話燥狰,高中數(shù)學知識就夠用了)。
如圖所示斜筐,其實就是相當于求(x,y)點旋轉(zhuǎn)θ度得到(x1,y1)龙致。獲得(x1,y1)、(x,y)顷链、θ角之間的關系目代。
最終可得(推導過程先不詳細證明,稍后貼上):
矩陣描述則為:
void setRotate(float degrees)
void setRotate(float degrees, float px, float py)
Matrix提供的接口倒是很容易理解嗤练,第一個參數(shù)degrees是旋轉(zhuǎn)角度榛了,px,py煞抬,則是以哪個點為原心進行旋轉(zhuǎn)霜大。
(補充)推導過程:
Matrix最下面的三個位置
MPERSP_0、MPERSP_1革答、MPERSP_2战坤,這三個數(shù)字在3D變換中有著至關重要的作用,但我目前還未做研究残拐,且使用情況較少途茫,先不做討論,最后寫完再做補充溪食。
Matrix的復合變換
復合變換就是圖形出現(xiàn)兩種或者兩種以上的變換慈省,如果有較好的圖象思維能力,這部分會非常好理解和實踐的。
Matrix 的復合變換實際上就是矩陣相乘边败,原理很簡單袱衷。但是要知道矩陣不滿足交換律,所有變換矩陣的前后順序不能隨意改動笑窜。所以新的變換矩陣和舊的變換矩陣前后順序的不同會影響圖片最終的外觀致燥,也就是說在兩次變換中,[A]×[B]×[x0,y0]和[B]×[A]×[x0,y0]得到的坐標是不同的排截。
但是由于矩陣相乘滿足結(jié)合律嫌蚤,你實際上可以理解為靠近[x0,y0]的矩陣先進行變換:[A]×[B]×[x0,y0]相當于[A]×([B]×[x0,y0]),也就是原坐標先進行了B變換再進行A變換断傲。
當然Matrix類也停供了前置矩陣和后置矩陣來進行復合變換的方法(忘了說了脱吱,我們之前介紹的變換方法全部以set為開頭,比如setTranslate认罩,這些方法會重置之前的矩陣箱蝠,相當于直接覆蓋原矩陣):
//縮放
boolean preScale(float sx, float sy);
boolean preScale(float sx, float sy, float px, float py);
boolean postScale(float sx, float sy);
boolean postScale(float sx, float sy, float px, float py);
//平移
boolean preTranslate(float dx, float dy);
boolean postTranslate(float dx, float dy);
//錯切
boolean preSkew(float kx, float ky);
boolean preSkew(float kx, float ky, float px, float py);
boolean postSkew(float kx, float ky);
boolean postSkew(float kx, float ky, float px, float py);
//旋轉(zhuǎn)
boolean preRotate(float degrees);
boolean preRotate(float degrees, float px, float py);
boolean postRotate(float degrees);
boolean postRotate(float degrees, float px, float py);
Camera2橫屏情況下畫面方向錯誤解決方案
private void transformImage() {
Matrix matrix = new Matrix();
int rotation = getWindowManager().getDefaultDisplay().getRotation();
if (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) {
//當屏幕方向為橫屏時,我們先旋轉(zhuǎn)90°(以預覽界面的中心點為旋轉(zhuǎn)點哦?汛埂;掳帷!)
matrix.postRotate(90 * (rotation - 2), mPreviewTexture.getWidth() / 2.0f, mPreviewTexture.getHeight() / 2.0f);
//然后圖象的寬度要變?yōu)樵瓉淼母叨冉俎郑叨纫優(yōu)樵瓉淼膶挾取? //(如下间校,進行互換比例,當然還是要以預覽界面中心為原點進行伸縮)
matrix.postScale(1f * mPreviewTexture.getWidth() / mPreviewTexture.getHeight(),
1f * mPreviewTexture.getHeight() / mPreviewTexture.getWidth(),
mPreviewTexture.getWidth() / 2.0f, mPreviewTexture.getHeight() / 2.0f);
//設置變換矩陣
mPreviewTexture.setTransform(matrix);
}
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
序言:七十年代末页慷,一起剝皮案震驚了整個濱河市憔足,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌酒繁,老刑警劉巖四瘫,帶你破解...
序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異欲逃,居然都是意外死亡找蜜,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
文/潘曉璐 我一進店門稳析,熙熙樓的掌柜王于貴愁眉苦臉地迎上來洗做,“玉大人,你說我怎么就攤上這事彰居〕现剑” “怎么了?”我有些...
文/不壞的土叔 我叫張陵陈惰,是天一觀的道長畦徘。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么井辆? 我笑而不...
正文 為了忘掉前任关筒,我火速辦了婚禮,結(jié)果婚禮上杯缺,老公的妹妹穿的比我還像新娘蒸播。我一直安慰自己,他們只是感情好萍肆,可當我...
文/花漫 我一把揭開白布袍榆。 她就那樣靜靜地躺著,像睡著了一般塘揣。 火紅的嫁衣襯著肌膚如雪包雀。 梳的紋絲不亂的頭發(fā)上,一...
那天亲铡,我揣著相機與錄音才写,去河邊找鬼。 笑死奴愉,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的铁孵。 我是一名探鬼主播锭硼,決...
文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼蜕劝!你這毒婦竟也來了檀头?” 一聲冷哼從身側(cè)響起,我...
序言:老撾萬榮一對情侶失蹤岖沛,失蹤者是張志新(化名)和其女友劉穎暑始,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體婴削,經(jīng)...
正文 獨居荒郊野嶺守林人離奇死亡廊镜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了唉俗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片嗤朴。...
序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖虫溜,靈堂內(nèi)的尸體忽然破棺而出雹姊,到底是詐尸還是另有隱情,我是刑警寧澤衡楞,帶...
正文 年R本政府宣布吱雏,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏歧杏。R本人自食惡果不足惜镰惦,卻給世界環(huán)境...
文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望得滤。 院中可真熱鬧陨献,春花似錦、人聲如沸懂更。這莊子的主人今日做“春日...
文/蒼蘭香墨 我抬頭看了看天上的太陽沮协。三九已至龄捡,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間慷暂,已是汗流浹背聘殖。 一陣腳步聲響...
我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留行瑞,地道東北人奸腺。 一個月前我還...
正文 我出身青樓,卻偏偏與公主長得像血久,于是被迫代替她去往敵國和親突照。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
我們在自定義 View 控件時隨處可見 Matrix 的身影氧吐,主要用于坐標轉(zhuǎn)換映射讹蘑,我們可以通過 Matrix 矩...
前言 最近翻閱關于從2D視頻或者圖片中重構(gòu)3D姿態(tài)的文章及其源碼,發(fā)現(xiàn)都有關于攝像機參數(shù)的求解筑舅,查找了相關資料座慰,做...
一、Matrix的作用 累加平移翠拣、旋轉(zhuǎn)版仔、縮放... ...變換,Android幫我們封裝好了误墓,不需要我們自己去計算...
一邦尊、簡介 Android android.graphics.Matrix 類是一個3 x 3的矩陣(方陣),上一張...
寫在前面:本文主要通過學習安卓自定義View進階-Matrix原理這篇文章去學習Matrix 的原理优烧,因此大部分文...