2017-04-19 139 views
0

我正在開發一款需要使用固定(手動)對焦並且始終使用閃光燈的Android相機應用程序。我遇到了一些似乎與閃光燈時間有關的問題。閃光燈總是閃光並且總是獲取圖像,但有時閃光燈並不實際照亮拍攝的畫面。一些幀有閃光燈,有些曝光過度,有些是黑暗的;基本上它是不一致的和不可預測的。Android Camera2 Flash時序問題

我基於Camera2Basic示例中的代碼。我想,我已經在這裏顯示的所有相關部分:

我的預覽請求生成器具有下列設置

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF); 
float minimumLens = mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE); 
mPreviewRequestBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, minimumLens); 
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AWB_MODE,CaptureRequest.CONTROL_AWB_MODE_OFF); 
mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH); 
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF); 

然後是(從Camera2Basic幾乎是筆直的)獲取圖像時的實際順序是:

private void takePicture() { 
    runPrecaptureSequence(); 
} 

private CameraCaptureSession.CaptureCallback mCaptureCallback = new CameraCaptureSession.CaptureCallback() { 

    private void process(CaptureResult result) { 
     switch (mState) { 
      case STATE_PREVIEW: { 
       break; 
      } 
      case STATE_WAITING_PRECAPTURE: { 
       Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); 
       if (aeState == null || 
         aeState == CaptureResult.CONTROL_AE_STATE_PRECAPTURE || 
         aeState == CaptureRequest.CONTROL_AE_STATE_FLASH_REQUIRED) { 
        mState = STATE_CAPTURE; 
       } 
       break; 
      } 

      case STATE_CAPTURE: { 
       // CONTROL_AE_STATE can be null on some devices 
       Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE); 
       if (aeState == null || aeState != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) { 
        mState = STATE_PICTURE_TAKEN; 
        captureStillPicture(); 
       } 
       break; 
      } 
     } 
    } 

    @Override 
    public void onCaptureProgressed(**ARGS**) { 
     process(partialResult); 
    } 

    @Override 
    public void onCaptureCompleted(**ARGS**) { 
     process(result); 
    } 

}; 

private void runPrecaptureSequence() { 
    try {   mPreviewRequestBuilder.set(CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER, CaptureRequest.CONTROL_AE_PRECAPTURE_TRIGGER_START); 
     mState = STATE_WAITING_PRECAPTURE; 
     mCaptureSession.capture(mPreviewRequestBuilder.build(), mCaptureCallback, mBackgroundHandler); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

private void captureStillPicture() { 
    try { 
     final Activity activity = getActivity(); 
     if (null == activity || null == mCameraDevice) { 
      return; 
     } 

     final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE); 
     captureBuilder.addTarget(mImageReader.getSurface()); 
     captureBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_OFF);   CaptureBuilder.set(CaptureRequest.CONTROL_AWB_MODE,CaptureRequest.CONTROL_AWB_MODE_OFF); 
     float minimumLens = mCameraCharacteristics.get(CameraCharacteristics.LENS_INFO_MINIMUM_FOCUS_DISTANCE); 
     captureBuilder.set(CaptureRequest.LENS_FOCUS_DISTANCE, minimumLens); 
     captureBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH); 
     captureBuilder.set(CaptureRequest.FLASH_MODE, CameraMetadata.FLASH_MODE_OFF); 
     int rotation = activity.getWindowManager().getDefaultDisplay().getRotation(); 
     captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation)); 

     mFileName = getFileNameFromTime() + ".jpg"; 

     CameraCaptureSession.CaptureCallback CaptureCallback 
       = new CameraCaptureSession.CaptureCallback() { 

      @Override 
      public void onCaptureCompleted(@NonNull CameraCaptureSession session, 
              @NonNull CaptureRequest request, 
              @NonNull TotalCaptureResult result) { 
       resumePreview(); 
      } 
     }; 

     mCaptureSession.stopRepeating(); 
     mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null); 
    } catch (CameraAccessException e) { 
     e.printStackTrace(); 
    } 
} 

保存圖像發生在ImageReader的onImageAvailableListener調用中,並且工作得很好。

它看起來好像閃光燈在圖像被採集之前發射,所以我嘗試了this answer中的建議,但FLASH_FIRED條件建議從未觸發過。

比我更熟悉Camera2的人能看到我搞砸了嗎?

回答

-1

以下三行添加到Camera2Basic樣品:

mPreviewRequestBuilder.set(CaptureRequest.CONTROL_MODE, CaptureRequest.CONTROL_MODE_OFF); 
mPreviewRequestBuilder.set(CaptureRequest.SENSOR_SENSITIVITY, 4000); 
mPreviewRequestBuilder.set(CaptureRequest.FLASH_MODE, FLASH_MODE_TORCH); 

當Flash被激活,repeatingRequest啓動,手動設置是由某種覆蓋默認設置(傳感器靈敏度:100 )。但要求明確規定傳感器靈敏度應該是4000 我在onCaptureCompleted法這兩條線進行了測試:

Log.d(TAG, "request: "+request.get(CaptureRequest.SENSOR_SENSITIVITY)); 
Log.d(TAG, "result: "+result.get(CaptureResult.SENSOR_SENSITIVITY)); 
+0

我還沒有機會測試還沒有,但是是修正的時機相對於快照的閃光燈,還是隻是讓曝光爲靜態? – jranalli

+0

所以這個解決方案在100%的時間內保留了閃光,這不是我所需要的。我仍然希望單獨閃光,但閃光燈正確閃光。 – jranalli