Android Opencv 4.2 攝像頭二次開發(fā)之 橫豎屏切換,前后攝像頭切換,鋪滿全屏問題,相機(jī)無法啟動(dòng)問題,一次解決

Android Opencv 4.2 攝像頭二次開發(fā)之 橫豎屏切換,前后攝像頭切換,鋪滿全屏問題,相機(jī)無法啟動(dòng)問題,一次解決

問題1.橫豎屏切換崩潰問題

描述
主要是原生的Opencv demo中沒有解決這樣的問題,橫豎屏切換會(huì)導(dǎo)致屏幕不能鋪滿或者直接崩潰問題。

崩潰原因:
主要是org.opencv.android.CameraBridgeViewBase#mCacheBitmap 這個(gè)mCacheBitmap 大小和Opencv 得到的CvCameraViewFrame 寬度和高度不一樣,導(dǎo)致在

 org.opencv.android.CameraBridgeViewBase#deliverAndDrawFrame

方法中調(diào)用的Utils.matToBitmap(modified, mCacheBitmap)方法時(shí)崩潰。這是個(gè)native方法,try-catch不起作用所以導(dǎo)致崩潰。

解決辦法:
要解決這個(gè)問題,主要是要在Utils.matToBitmap(modified, mCacheBitmap)調(diào)用之前,創(chuàng)建和CvCameraViewFrame中的mat一樣大小的Bitmap。

解決辦法1:調(diào)用JavaCameraView的setCvCameraViewListener 在onCameraViewStarted的回調(diào)方法中創(chuàng)建對(duì)應(yīng)大小的mCacheBitmap,這里又有兩種方式:
1.不想改上層源碼的話可以用反射
2.擴(kuò)展一下源碼添加一個(gè)方法比如我在源碼中加了一個(gè)方法
org.opencv.android.CameraBridgeViewBase#AllocateCache2
在onCameraViewStarted 中調(diào)用保證在deliverAndDrawFrame調(diào)用的時(shí)候,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è)備),前置攝像頭可能會(huì)存在3個(gè)問題 1.不能鋪滿全屏,2.左右圖像反轉(zhuǎn) 3.被旋轉(zhuǎn)90度
所以要在攝像頭切換的時(shí)候解決這些問題:

問題1.不能鋪滿全屏的問題

解決辦法1:修改mScale這個(gè)縮放參數(shù)

org.opencv.android.CameraBridgeViewBase#mScale

JavaCameraView 有用到這個(gè)縮放系數(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;
                }

這樣在繪制的時(shí)候保證無論是寬度和高度,都可以放大到足夠充滿全屏的比例,在繪制的時(shí)候可能會(huì)有超出屏幕的部分,但是始終能鋪滿全屏。

問題3.橫豎屏切換自適應(yīng)

橫豎屏切換要解決幾個(gè)問題
1.告訴JavaCameraView當(dāng)前的手機(jī)方向
2.按照最新的分別率重新創(chuàng)建customCacheBitmap
3.重啟相機(jī)

做法

  1. 配置Activity android:configChanges="orientation|screenSize"
  2. 重新Activity onConfigurationChanged 方法,在屏幕方向發(fā)生改變時(shí)告訴JavaCameraView 并重啟相機(jī)

針對(duì)以上3個(gè)問題的綜合解決辦法,我繼承了JavaCameraView,增加如下字段

    //是否使用前置攝像頭
    private boolean useFrontCamera = false;

    //是否使用opencv自己的方式繪制來繪制
    private boolean drawUseDefaultMethod = false;

    //顯示Mat用的Bitmap
    private Bitmap customCacheBitmap = null;

    //當(dāng)前是否豎屏
    private boolean isPortrait = true;

    //自動(dòng)縮放到全屏取中間部分繪制
    private boolean autoFullScreen = true;

重寫了deliverAndDrawFrame 方法

com.demo.cv42.view.CustomJavaCameraView#deliverAndDrawFrame

統(tǒng)一解決,前后攝像頭切換,橫豎屏切換帶來的各種問題。

問題4.相機(jī)無法啟動(dòng)問題

1.檢查是否給App授權(quán)使用相機(jī)的權(quán)限
2.很多情況下是因?yàn)镴avaCameraView 方法

org.opencv.android.CameraBridgeViewBase#calculateCameraFrameSize

這個(gè)方法是計(jì)算出一個(gè)最合適的輸出分辨率,但是這個(gè)方法會(huì)有個(gè)bug,有可能會(huì)計(jì)算出一個(gè)相機(jī)硬件不支持的分辨率(),這會(huì)導(dǎo)致相機(jī)無法啟動(dòng),直接崩潰,看不到任何日志,需要debug跟蹤才能發(fā)現(xiàn)問題。所有的相機(jī)分辨率應(yīng)該在API返回的列表中(mCamera.getParameters().getSupportedPreviewSizes())才行。

代碼地址
https://gitee.com/wangzy2018/Opencv42_study_demo.git

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容