Camera2點擊對焦實現2


https://www.aliyun.com/jiaocheng/22218.html

    • 阿里雲  >  教程中心   >  android教程  >  Camera2點擊對焦實現  
    • Camera2點擊對焦實現
    • 發布時間:2018-01-18 來源:網絡 上傳者:用戶

      關鍵字: 對焦 Camera2 實現 點擊

      發表文章
    • 摘要:android從5.0開始,廢棄了原有的Camera接口,提供了全新的Camera2接口。Camera2接口為了給app提供更強大更低級的攝像頭控制,將整個的攝像頭框架及流程進行了修改。在使用Camera2時,發現手工對焦的實現邏輯與舊的Camera實現該邏輯有較大不同,本文就談下如何使用Camera2進行手工對焦。1.操作攝像頭進行對焦mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS,newMeteri

    • android從5.0開始,廢棄了原有的Camera接口,提供了全新的Camera2接口。Camera2接口為了給app提供更強大更低級的攝像頭控制,將整個的攝像頭框架及流程進行了修改。在使用Camera2時,發現手工對焦的實現邏輯與舊的Camera實現該邏輯有較大不同,本文就談下如何使用Camera2進行手工對焦。


      1. 操作攝像頭進行對焦 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_REGIONS, new MeteringRectangle[] {new MeteringRectangle(rect, 1000)}); 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_REGIONS, new MeteringRectangle[] {new MeteringRectangle(rect, 1000)}); 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_AUTO); 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_START); 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CameraMetadata.CONTROL_AE_PRECAPTURE_TRIGGER_START); 
      mPreviewRequest = mPreviewRequestBuilder.build(); 
      try { 
      mCaptureSession.setRepeatingRequest(mPreviewRequest, mAfCaptureCallback, mBackgroundHandler); 
      } catch (CameraAccessException e) { 
      Log.e(TAG, "setRepeatingRequest failed, " + e.getMessage()); 

      主要步驟:


      指定自動對焦和自動嚗光測量的區域,這個區域就是手指點擊的圖像區域。 
      指定自動對焦模式為 CONTROL_AF_MODE_AUTO 模式,非點擊對焦的時候,模式應該為CONTROL_AF_MODE_CONTINUOUS_PICTURE 或者 CONTROL_AF_MODE_CONTINUOUS_VIDEO。 
      將對焦的狀態修改為開始對焦 
      觸發連續獲取圖像數據 
      2. 對焦完成恢復正常的預覽模式 
      if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState 
      || CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) { 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL); 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_VIDEO); 
      mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON); 
      mPreviewRequest = mPreviewRequestBuilder.build(); 
      try { 
      mCaptureSession.setRepeatingRequest(mPreviewRequest, null, mBackgroundHandler); 
      } catch (CameraAccessException e) { 
      Log.e(TAG, "setRepeatingRequest failed, errMsg: " + e.getMessage()); 


      點擊對焦完成后,將對焦模式修改為 CONTROL_AF_MODE_CONTINUOUS_VIDEO。


      3. 計算自動對焦區域 

      CONTROL_AF_REGIONS 的參數是指定用來測量對焦的區域,攝像頭設備使用這個區域來測量光度情況進行對焦,因此該區域坐標系基於攝像頭成像區域的坐標系。那么app接收到的圖像數據與成像區域的關系如何呢?


      手機攝像頭成像區域是固定的,因此系統對於app中需要采集不同分辨率的需求做法是:將成像區域按照需要的分辨率比例進行居中裁剪,然后縮放到對應的尺寸。


      Camera2通過不同的接口,給應用層提供了這方面的信息:



      SENSOR_INFO_PIXEL_ARRAY_SIZE 表示的是攝像頭成像區域所使用的內存大小。 
      SENSOR_INFO_ACTIVE_ARRAY_SIZE 表示真正接收光線的區域,因此成像的區域是該參數指定的區域,當然該矩形區域的坐標系基於SENSOR_INFO_PIXEL_ARRAY_SIZE 。 
      SCALER_CROP_REGION 表示最終的輸出內容是基於 SENSOR_INFO_ACTIVE_ARRAY_SIZE 裁剪的部分,而該值指定裁剪的區域。 

      Camera2點擊對焦實現 
      攝像頭輸出裁剪區域 

      如圖:整個區域(2000 x 1500)是整個成像所使用的內存區域,藍色部分(crop region)是輸出內容是使用的裁剪區域(根據我的測試結果發現,crop region基本等於成像區域大小),綠色的和橘黃色的部分就是不同分辨率所使用的區域。


      了解該裁剪流程之后,就可以知道如何計算對焦區域了:


      一般app拿到攝像頭來的數據之后,會將攝像頭進行合適的旋轉,然后根據屏幕比例居中裁剪圖像數據,再進行顯示。所以我們先將屏幕上面點擊區域的坐標轉化為app收到的圖像區域的坐標: 
      // 先取相對於view上面的坐標 
      double x = event.getX(), y = event.getY(), tmp; 
      // 取出來的圖像如果有旋轉角度的話,則需要將寬高交換下 
      int realPreviewWidth = mPreviewSize.width, realPreviewHeight = mPreviewSize.height; 
      if (90 == mDisplayRotate || 270 == mDisplayRotate) { 
      realPreviewWidth = mPreviewSize.height; 
      realPreviewHeight = mPreviewSize.width; 

      // 計算攝像頭取出的圖像相對於view放大了多少,以及有多少偏移 
      double imgScale = 1.0, verticalOffset = 0, horizontalOffset = 0; 
      if (realPreviewHeight * viewWidth > realPreviewWidth * viewHeight) { 
      imgScale = viewWidth * 1.0 / realPreviewWidth; 
      verticalOffset = (realPreviewHeight - viewHeight / imgScale) / 2; 
      } else { 
      imgScale = viewHeight * 1.0 / realPreviewHeight; 
      horizontalOffset = (realPreviewWidth - viewWidth / imgScale) / 2; 

      // 將點擊的坐標轉換為圖像上的坐標 
      x = x / imgScale + horizontalOffset; 
      y = y / imgScale + verticalOffset; 
      if (90 == mDisplayRotate) { 
      tmp = x; x = y; y = mPreviewSize.height - tmp; 
      } else if (270 == mDisplayRotate) { 
      tmp = x; x = mPreviewSize.width - y; y = tmp; 

      app取到的圖像是按照裁剪區域(crop region)按照預覽尺寸的比例進行居中裁剪的,所以需要計算app取到的圖像相對於裁剪區域進行了多少縮放,以及有多少位移: 
      // 計算取到的圖像相對於裁剪區域的縮放系數,以及位移 
      Rect cropRegion = mPreviewRequest.get(CaptureRequest.SCALER_CROP_REGION); 
      if (null == cropRegion) { 
      Log.e(TAG, "can't get crop region"); 
      cropRegion = mActiveArraySize; 

      int cropWidth = cropRegion.width(), cropHeight = cropRegion.height(); 
      if (mPreviewSize.height * cropWidth > mPreviewSize.width * cropHeight) { 
      imgScale = cropHeight * 1.0 / mPreviewSize.height; 
      verticalOffset = 0; 
      horizontalOffset = (cropWidth - imgScale * mPreviewSize.width) / 2; 
      } else { 
      imgScale = cropWidth * 1.0 / mPreviewSize.width; 
      horizontalOffset = 0; 
      verticalOffset = (cropHeight - imgScale * mPreviewSize.height) / 2; 

      將點擊區域相對於app取到的圖像坐標,轉化為相對於成像區域的坐標: 
      // 將點擊區域相對於圖像的坐標,轉化為相對於成像區域的坐標 
      x = x * imgScale + horizontalOffset + cropRegion.left; 
      y = y * imgScale + verticalOffset + cropRegion.top; 
      按照對焦區域為成像區域的0.1倍計算對焦的矩形: 
      double tapAreaRatio = 0.1; 
      Rect rect = new Rect(); 
      rect.left = clamp((int) (x - tapAreaRatio / 2 * cropRegion.width()), 0, cropRegion.width()); 
      rect.right = clamp((int) (x + tapAreaRatio / 2 * cropRegion.width()), 0, cropRegion.width()); 
      rect.top = clamp((int) (y - tapAreaRatio / 2 * cropRegion.height()), 0, cropRegion.height()); 
      rect.bottom = clamp((int) (y + tapAreaRatio / 2 * cropRegion.height()), 0, cropRegion.height()); 
      4. 總結 

      Camera2相對於就的Camera api來說,使用復雜度提升不少,但是提供更多的操作空間。同時,由於從Android 5.0就開始提供Camera2的接口,而有些機器並不一定支持全部的Camera2特性,所以需要通過 android.info.supportedHardwareLevel 查詢支持的程度:


      LEGACY:app調用Camera2的接口時,由框架將其轉調給Camera API1來實現對應的功能,因此不支持Camera2的某些特性,如:每幀控制。 
      FULL:設備支持所有的Camera2接口。 
      LIMITED:設備支持部分的Camera2接口。 

      demo地址在這,demo中並沒有查詢級別,如果demo跑得不正常時,可以檢查下支持級別是否是FULL。


      文中的理解來自於下面幾篇文章,有任何問題,歡迎指教:


      http://source.android.com/devices/camera/camera3_crop_reprocess.html 
      https://developer.android.com/reference/android/hardware/camera2/CaptureRequest.html#SCALER_CROP_REGION 
      https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_ACTIVE_ARRAY_SIZE
      https://developer.android.com/reference/android/hardware/camera2/CameraCharacteristics.html#SENSOR_INFO_PIXEL_ARRAY_SIZE



    • 以上是

Camera2點擊對焦實現

      的內容,更多 

對焦 Camera2 實現 點擊 

      的內容,請您使用右上方搜索功能獲取相關信息。
    •  1 2 3 4 
    • 相關文章


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM