Android Opencv 4.2 攝像頭二次開發(fā)之 橫豎屏切換垂寥,前后攝像頭切換腕柜,鋪滿全屏問題,相機(jī)無法啟動問題矫废,一次解決
問題1.橫豎屏切換崩潰問題
描述:
主要是原生的Opencv demo中沒有解決這樣的問題,橫豎屏切換會導(dǎo)致屏幕不能鋪滿或者直接崩潰問題砰蠢。
崩潰原因:
主要是org.opencv.android.CameraBridgeViewBase#mCacheBitmap 這個mCacheBitmap 大小和Opencv 得到的CvCameraViewFrame 寬度和高度不一樣蓖扑,導(dǎo)致在
org.opencv.android.CameraBridgeViewBase#deliverAndDrawFrame
方法中調(diào)用的Utils.matToBitmap(modified, mCacheBitmap)方法時崩潰。這是個native方法台舱,try-catch不起作用所以導(dǎo)致崩潰律杠。
解決辦法:
要解決這個問題潭流,主要是要在Utils.matToBitmap(modified, mCacheBitmap)調(diào)用之前,創(chuàng)建和CvCameraViewFrame中的mat一樣大小的Bitmap柜去。
解決辦法1:調(diào)用JavaCameraView的setCvCameraViewListener 在onCameraViewStarted的回調(diào)方法中創(chuàng)建對應(yīng)大小的mCacheBitmap灰嫉,這里又有兩種方式:
1.不想改上層源碼的話可以用反射
2.擴(kuò)展一下源碼添加一個方法比如我在源碼中加了一個方法
org.opencv.android.CameraBridgeViewBase#AllocateCache2
在onCameraViewStarted 中調(diào)用保證在deliverAndDrawFrame調(diào)用的時候,mat和bitmap保證大小是一樣的
解決辦法2:繼承org.opencv.android.CameraBridgeViewBase嗓奢,在改造deliverAndDrawFrame方法讼撒,在調(diào)用
Utils.matToBitmap(modified, mCacheBitmap);
之前保證mCacheBitmap和modified的大小一樣,或者屏蔽掉opencv的方法自己重寫,參考如下
com.demo.cv42.view.CustomJavaCameraView#deliverAndDrawFrame
問題2.前后攝像頭切換問題
描述:后攝像頭主要可能存在不能鋪滿全屏的問題(看設(shè)備)股耽,前置攝像頭可能會存在3個問題 1.不能鋪滿全屏根盒,2.左右圖像反轉(zhuǎn) 3.被旋轉(zhuǎn)90度
所以要在攝像頭切換的時候解決這些問題:
問題1.不能鋪滿全屏的問題
解決辦法1:修改mScale這個縮放參數(shù)
org.opencv.android.CameraBridgeViewBase#mScale
JavaCameraView 有用到這個縮放系數(shù),但是代碼有問題物蝙,源碼如下
mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);
要保證全屏炎滞,這里應(yīng)該取最大而不是最小,而且比例是應(yīng)該是JavaCameraView 的寬高比除以原始的mat的寬高比诬乞,opencv的源碼中寫反了册赛,而且需要判斷如果mat本身大于JavaCameraView寬高,只需要把mScale設(shè)置為1就可以了震嫉,源碼中mScale==0 事不起作用森瘪,正確代碼如下
if (srcMat.cols() < width || srcMat.rows() < height) {
float scaleWidth = width * 1.0f / srcMat.cols();
float scaleHeight = height * 1.0f / srcMat.rows();
float maxScale = Math.max(scaleHeight, scaleWidth);
mScale = maxScale;//用自帶的縮放系數(shù)(當(dāng)然也可以自己來縮放Mat 或者bitmap達(dá)到同樣的效果)
} else {
mScale = 1.0f;
}
這樣在繪制的時候保證無論是寬度和高度,都可以放大到足夠充滿全屏的比例责掏,在繪制的時候可能會有超出屏幕的部分柜砾,但是始終能鋪滿全屏。
問題3.橫豎屏切換自適應(yīng)
橫豎屏切換要解決幾個問題
1.告訴JavaCameraView當(dāng)前的手機(jī)方向
2.按照最新的分別率重新創(chuàng)建customCacheBitmap
3.重啟相機(jī)
做法
- 配置Activity android:configChanges="orientation|screenSize"
- 重新Activity onConfigurationChanged 方法换衬,在屏幕方向發(fā)生改變時告訴JavaCameraView 并重啟相機(jī)
針對以上3個問題的綜合解決辦法痰驱,我繼承了JavaCameraView,增加如下字段
//是否使用前置攝像頭
private boolean useFrontCamera = false;
//是否使用opencv自己的方式繪制來繪制
private boolean drawUseDefaultMethod = false;
//顯示Mat用的Bitmap
private Bitmap customCacheBitmap = null;
//當(dāng)前是否豎屏
private boolean isPortrait = true;
//自動縮放到全屏取中間部分繪制
private boolean autoFullScreen = true;
重寫了deliverAndDrawFrame 方法
com.demo.cv42.view.CustomJavaCameraView#deliverAndDrawFrame
統(tǒng)一解決瞳浦,前后攝像頭切換担映,橫豎屏切換帶來的各種問題。
問題4.相機(jī)無法啟動問題
1.檢查是否給App授權(quán)使用相機(jī)的權(quán)限
2.很多情況下是因?yàn)镴avaCameraView 方法
org.opencv.android.CameraBridgeViewBase#calculateCameraFrameSize
這個方法是計算出一個最合適的輸出分辨率叫潦,但是這個方法會有個bug蝇完,有可能會計算出一個相機(jī)硬件不支持的分辨率(),這會導(dǎo)致相機(jī)無法啟動矗蕊,直接崩潰短蜕,看不到任何日志,需要debug跟蹤才能發(fā)現(xiàn)問題傻咖。所有的相機(jī)分辨率應(yīng)該在API返回的列表中(mCamera.getParameters().getSupportedPreviewSizes())才行朋魔。