2016-10-03 194 views
1

在Samsung Galaxy S7邊緣設備上拍攝照片時出現不良行爲。camera2拍攝的照片模糊

我在拍照前同時等待對焦和曝光,但最後我有一種模糊的圖像,與本機相機應用輸出相比。

該問題在放大圖像上尤其明顯,但在未放大時也存在。我也嘗試啓用光學防抖,但問題並未解決。

下面是解釋問題的示例圖片。

Native camera image

My camera image

下面是代碼:

private void triggerFocusAndExposure(boolean picture) { 
    setState(WAIT_PRECAPTURE_PICTURE); 

    if (isAFEnabled()) { 
     previewBuilder.set(CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_START); 
    } 

    if (isAEEnabled()) { 
     previewBuilder.set(CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_START); 
    } 

    try { 
     cameraSession.capture(previewBuilder.build(), new SCameraCaptureSession.CaptureCallback() { 
      @Override public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) { 
       setState(PRECAPTURE_TRIGGERED_PICTURE); 
      } 
     }, backgroundHandler); 
    } catch (CameraAccessException e) { 
     return; 
    } 

    try { 
     previewBuilder.set(CONTROL_AF_TRIGGER, CONTROL_AF_TRIGGER_IDLE); 
     previewBuilder.set(CONTROL_AE_PRECAPTURE_TRIGGER, CONTROL_AE_PRECAPTURE_TRIGGER_IDLE); 
     cameraSession.setRepeatingRequest(previewBuilder.build(), mSessionCaptureCallback, backgroundHandler); 
    } catch (CameraAccessException e) { 
    } 
} 

public void capturePicture() { 
    CameraState state = getState(); 
    if (state != IDLE && state != CLOSING && state != TAKE_PICTURE) { 
      boolean af = false; 
      boolean ae = false; 
      if (isAFEnabled()) { 
       af = true; 
      } else if (isAEEnabled()) { 
       ae = true; 
      } 

      if (!af && !ae) { 
       takePicture(); 
      } else { 
       triggerFocusAndExposure(true); 
      } 
    } 

    return; 
} 

用於觸發聚焦和曝光方法:

對圖象取入步驟1的方法種

方法等待對焦和曝光:

的畫面捕獲步驟2
private void waitPrecapture(STotalCaptureResult result, boolean picture) { 
    // Check if AF/AE triggered and/or finished 
    if ((!isAFTriggered(result) || isAfFinished(result)) && (!isAETriggered(result) || isAEFinished(result))) { 
     takePicture(); 
    } 
} 

private boolean isAFTriggered(STotalCaptureResult result) { 
    Integer afMode = result.get(SCaptureResult.CONTROL_AF_MODE); 
    return afMode != CONTROL_AF_MODE_OFF && 
      afMode != CONTROL_AF_MODE_EDOF; 
} 

private boolean isAfFinished(STotalCaptureResult result) { 
    int afState = result.get(SCaptureResult.CONTROL_AF_STATE); 
    return afState == CONTROL_AF_STATE_FOCUSED_LOCKED || afState == CONTROL_AF_STATE_NOT_FOCUSED_LOCKED 
      || afState == CONTROL_AF_STATE_PASSIVE_FOCUSED || afState == CONTROL_AF_STATE_PASSIVE_UNFOCUSED; 
} 

private boolean isAETriggered(STotalCaptureResult result) { 
    boolean aeMode = result.get(SCaptureResult.CONTROL_AE_MODE) != SCaptureResult.CONTROL_AE_MODE_OFF; 
    return aeMode && cameraCharacteristics.get(SCameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL) 
      != SCameraCharacteristics.INFO_SUPPORTED_HARDWARE_LEVEL_LEGACY; 
} 

private boolean isAEFinished(STotalCaptureResult result) { 
    Integer aeState = result.get(SCaptureResult.CONTROL_AE_STATE); 
    return aeState == null || aeState == SCaptureResult.CONTROL_AE_STATE_CONVERGED || aeState == SCaptureResult.CONTROL_AE_STATE_FLASH_REQUIRED 
      || aeState == SCaptureResult.CONTROL_AE_STATE_LOCKED; 
} 

方法:

public void takePicture(){ 
    imageReader.setOnImageAvailableListener(reader -> { 
     Image image = reader.acquireLatestImage(); 
     ByteBuffer buffer = image.getPlanes()[0].getBuffer(); 
     byte[] bytes = new byte[buffer.remaining()]; 
     buffer.get(bytes); 
     image.close(); 
     singleSubscriber.onSuccess(bytes); 
    }, imageSavingHandler); 

    try { 
     cameraSession.capture(captureBuilder.build(), new SCameraCaptureSession.CaptureCallback() { 
      @Override 
      public void onCaptureCompleted(SCameraCaptureSession session, SCaptureRequest request, STotalCaptureResult result) { 
       if (getState() == CameraState.CLOSING) { 
        return; 
       } 
       cancelAF(); 
      } 

      @Override 
      public void onCaptureStarted(SCameraCaptureSession session, SCaptureRequest request, long timestamp, long frameNumber) { 
       super.onCaptureStarted(session, request, timestamp, frameNumber); 
       shutterCallback.call(); 
      }  

      @Override public void onCaptureFailed(SCameraCaptureSession session, SCaptureRequest request, SCaptureFailure failure) { 
        singleSubscriber.onError(new RuntimeException("Error taking picture, onCaptureFailed")); 
        if (getState() == CameraState.CLOSING) { 
         return; 
        } 
        cancelAF(); 
      } 
     }, backgroundHandler); 

     setState(CameraState.TAKE_PICTURE); 
    } catch (CameraAccessException e) { 
     singleSubscriber.onError(new RuntimeException("Error capturing image", e)); 
    } 
} 
+0

更多代碼請 – Vyacheslav

+0

非常有趣。 'Thanks'。爲了什麼?這是一個編程站點。我看到很少的編程。 – greenapps

+0

你使用哪個教程進行圖像捕捉? – abbath

回答

7

我已經找到了修復。 captureBuilder自動設置CaptureRequest.NOISE_REDUCTION_MODE_HIGH_QUALITYCaptureRequest.EDGE_MODE_HIGH_QUALITY但在我的情況下,設備有一些問題處理這些選項。設置CaptureRequest.NOISE_REDUCTION_MODE_FASTCaptureRequest.EDGE_MODE_FAST可解決問題。