2017-04-19 4 views
0

고정 (수동) 초점을 사용해야하는 Android 카메라 앱에서 작업 중이며 항상 플래시를 사용하고 있습니다. 플래시 타이밍과 관련있는 문제가 있습니다. 플래시는 항상 켜지고 이미지는 항상 수집되지만 플래시가 실제로 캡처 된 프레임을 비추 지 않는 경우가 있습니다. 일부 프레임은 플래시가 있고, 일부는 과다 노출되어 있으며, 일부는 어둡습니다. 기본적으로 일관성이없고 예측할 수 없습니다.Android Camera2 플래시 타이밍 문제

내 코드는 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 샘플에 다음 세 줄을 추가 : 플래시가 활성화되고 repeatingRequest가 시작되면

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

, 수동 설정이 어떤 종류의 덮어 쓰기되고 기본적으로 설정 (센서 감도 : 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