Opencv 攝像頭二次開發,橫豎屏切換,前後攝像頭切換,鋪滿全屏問題,一次解決(附源碼)

Android Opencv 4.2 攝像頭二次開發之 橫豎屏切換,前後攝像頭切換,鋪滿全屏問題,相機無法啓動問題,一次解決

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

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

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

 org.opencv.android.CameraBridgeViewBase#deliverAndDrawFrame

方法中調用的Utils.matToBitmap(modified, mCacheBitmap)方法時崩潰。這是個native方法,try-catch不起作用所以導致崩潰。

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

解決辦法1:調用JavaCameraView的setCvCameraViewListener 在onCameraViewStarted的回調方法中創建對應大小的mCacheBitmap,這裏又有兩種方式:
1.不想改上層源碼的話可以用反射
2.擴展一下源碼添加一個方法比如我在源碼中加了一個方法
org.opencv.android.CameraBridgeViewBase#AllocateCache2
在onCameraViewStarted 中調用保證在deliverAndDrawFrame調用的時候,mat和bitmap保證大小是一樣的

解決辦法2:繼承org.opencv.android.CameraBridgeViewBase,在改造deliverAndDrawFrame方法,在調用

Utils.matToBitmap(modified, mCacheBitmap);

之前保證mCacheBitmap和modified的大小一樣,或者屏蔽掉opencv的方法自己重寫,參考如下

com.demo.cv42.view.CustomJavaCameraView#deliverAndDrawFrame

問題2.前後攝像頭切換問題

描述:後攝像頭主要可能存在不能鋪滿全屏的問題(看設備),前置攝像頭可能會存在3個問題 1.不能鋪滿全屏,2.左右圖像反轉 3.被旋轉90度
所以要在攝像頭切換的時候解決這些問題:

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

解決辦法1:修改mScale這個縮放參數

org.opencv.android.CameraBridgeViewBase#mScale

JavaCameraView 有用到這個縮放係數,但是代碼有問題,源碼如下

mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth);

要保證全屏,這裏應該取最大而不是最小,而且比例是應該是JavaCameraView 的寬高比除以原始的mat的寬高比,opencv的源碼中寫反了,而且需要判斷如果mat本身大於JavaCameraView寬高,只需要把mScale設置爲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;//用自帶的縮放係數(當然也可以自己來縮放Mat 或者bitmap達到同樣的效果)
                } else {
                    mScale = 1.0f;
                }

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

問題3.橫豎屏切換自適應

橫豎屏切換要解決幾個問題
1.告訴JavaCameraView當前的手機方向
2.按照最新的分別率重新創建customCacheBitmap
3.重啓相機

做法

  1. 配置Activity android:configChanges=“orientation|screenSize”
  2. 重新Activity onConfigurationChanged 方法,在屏幕方向發生改變時告訴JavaCameraView 並重啓相機

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

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

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

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

    //當前是否豎屏
    private boolean isPortrait = true;

    //自動縮放到全屏取中間部分繪製
    private boolean autoFullScreen = true;

重寫了deliverAndDrawFrame 方法

com.demo.cv42.view.CustomJavaCameraView#deliverAndDrawFrame

統一解決,前後攝像頭切換,橫豎屏切換帶來的各種問題。

問題4.相機無法啓動問題

1.檢查是否給App授權使用相機的權限
2.很多情況下是因爲JavaCameraView 方法

org.opencv.android.CameraBridgeViewBase#calculateCameraFrameSize

這個方法是計算出一個最合適的輸出分辨率,但是這個方法會有個bug,有可能會計算出一個相機硬件不支持的分辨率(),這會導致相機無法啓動,直接崩潰,看不到任何日誌,需要debug跟蹤才能發現問題。所有的相機分辨率應該在API返回的列表中(mCamera.getParameters().getSupportedPreviewSizes())纔行。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章