【问题标题】:Front Camera in Camera2 not capturing imageCamera2中的前置摄像头未捕获图像
【发布时间】:2015-10-14 13:53:14
【问题描述】:

我有来自https://github.com/googlesamples/android-Camera2Basic 的 Camera2 的代码。

我面临的问题是,当我打开前置摄像头时,我无法拍摄照片,但使用后置摄像头可以正常工作。

有人实现了Camera2 Api吗,请帮忙!

这里是sn-p的代码:

private void setUpCameraOutputs(int width, int height) {
    Activity activity = getActivity();
    CameraManager manager = (CameraManager) activity.getSystemService(Context.CAMERA_SERVICE);
    try {
        for (String cameraId : manager.getCameraIdList()) {
            CameraCharacteristics characteristics
                    = manager.getCameraCharacteristics(cameraId);

            // We don't use a front facing camera in this sample.
            int facing = characteristics.get(CameraCharacteristics.LENS_FACING);
            Log.i(TAG,"Front Cam ID: "+ facing);
            if (characteristics.get(CameraCharacteristics.LENS_FACING)==CameraCharacteristics.LENS_FACING_FRONT)
            {



                StreamConfigurationMap map = characteristics.get(
                        CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);


                // For still image captures, we use the largest available size.
                Size largest = Collections.max(
                        Arrays.asList(map.getOutputSizes(ImageFormat.JPEG)),
                        new CompareSizesByArea());
                mImageReader = ImageReader.newInstance(largest.getWidth(), largest.getHeight(),
                        ImageFormat.JPEG, /*maxImages*/2);
                mImageReader.setOnImageAvailableListener(
                        mOnImageAvailableListener, mBackgroundHandler);

                // Danger, W.R.! Attempting to use too large a preview size could  exceed the camera
                // bus' bandwidth limitation, resulting in gorgeous previews but the storage of
                // garbage capture data.
                mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture.class),
                        width, height, largest);

                // We fit the aspect ratio of TextureView to the size of preview we picked.
                int orientation = getResources().getConfiguration().orientation;
                if (orientation == Configuration.ORIENTATION_LANDSCAPE) {
                    mTextureView.setAspectRatio(
                            mPreviewSize.getWidth(), mPreviewSize.getHeight());
                } else {
                    mTextureView.setAspectRatio(
                            mPreviewSize.getHeight(), mPreviewSize.getWidth());
                }

                mCameraId = cameraId;
                return;
            }
            else
            {
                onActivityCreated(Bundle.EMPTY);
            }
        }
    } catch (CameraAccessException e) {
        e.printStackTrace();
    } catch (NullPointerException e) {
        // Currently an NPE is thrown when the Camera2API is used but not supported on the
        // device this code runs.
        ErrorDialog.newInstance(getString(R.string.camera_error))
                .show(getChildFragmentManager(), FRAGMENT_DIALOG);
    }
}

【问题讨论】:

  • 你是在真机还是模拟器上测试?
  • 你能帮帮我吗

标签: android


【解决方案1】:

问题在于许多前置摄像头都有固定焦距。因此,在lockFocus() 中的自动对焦触发后,自动对焦状态 (CONTROL_AF_STATE) 保持 INACTIVE 并且自动对焦触发器什么也不做。

因此,为了使其正常工作,您需要检查是否支持自动对焦。为此,请将以下内容添加到setUpCameraOutputs()

int[] afAvailableModes = characteristics.get(CameraCharacteristics.CONTROL_AF_AVAILABLE_MODES);

if (afAvailableModes.length == 0 || (afAvailableModes.length == 1
        && afAvailableModes[0] == CameraMetadata.CONTROL_AF_MODE_OFF)) {
    mAutoFocusSupported = false;
} else {
    mAutoFocusSupported = true;
}

最后,如果你想拍照的时候不支持,就不要锁定焦点:

private void takePicture() {
    if (mAutoFocusSupported) {
        lockFocus();
    } else {
        captureStillPicture();
    }
}

【讨论】:

  • 为我工作。 tks
【解决方案2】:

对于 Camera2 Api,Google 的视频示例适用于前置和后置摄像头,但对于图像捕获,Google 的示例仅适用于后置摄像头,不适用于前置摄像头。
适合我的解决方案是

lockFocus()方法中,替换行

mCaptureSession.capture(mPreviewRequestBuilder.build(),
                                                  mCaptureCallback, mBackgroundHandler);

captureStillPicture();

希望这会有所帮助!

【讨论】:

  • 嘿,这工作正常!但是捕获的图像旋转了180度,这个问题有什么解决方案吗??
  • @jaxon :您必须根据设备旋转图像。我认为谷歌的例子在代码中有这个。
  • 在 CaptureStillPicture() 方法中,替换 int rotation = getWindowManager().getDefaultDisplay().getRotation(); captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, ORIENTATIONS.get(rotation));带有 captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, cameraCharacteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)) 的行;这将解决您在 Android>=5.0 的所有设备上的问题
  • @Arvind Singh:感谢回复,我试过了,但输出仍然没有变化,
  • 我已经通过将 ORIENTATIONS.get(rotation) 更改为整数值 270 解决了旋转问题 -- captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, 270);像这样
【解决方案3】:

@ArvindSingh 的解决方案不是最好的,因为您还会禁用后置摄像头的对焦功能。更好的解决方案是像这样在 takePicture 中进行摄像头朝向检查:

private void takePicture() {
    if (CameraCharacteristics.LENS_FACING_FRONT == mSelectedFacing) {
        // front camera selected, so take a picture without focus
        captureStillPicture();
    } else {
        // back camera selected, trigger the focus before creating an image
        lockFocus();
    }
}

对于此解决方案,您只需将当前使用的朝向保存在 mSelectedFacing 中的某处即可

【讨论】:

    【解决方案4】:

    在lockFocus()方法中,替换行

    mCaptureSession.capture(mPreviewRequestBuilder.build(),
                                                  mCaptureCallback,    mBackgroundHandler);
    

    captureStillPicture();
    

    为了防止不需要的方向,您可以使用

    /** * 从屏幕旋转到 JPEG 方向的转换。 */

       static {
           ORIENTATIONS.append(Surface.ROTATION_0, 270);
           ORIENTATIONS.append(Surface.ROTATION_90, 0);
           ORIENTATIONS.append(Surface.ROTATION_180, 180);
           ORIENTATIONS.append(Surface.ROTATION_270, 270);
       }
    

    【讨论】:

      【解决方案5】:

      请尝试使用此代码进行捕获

      case STATE_WAITING_LOCK: {
                      Integer afState = result.get(CaptureResult.CONTROL_AF_STATE);
                      if (afState == null) {
                          captureStillPicture();
                      } else if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                              CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState ||
                               CaptureResult.CONTROL_AF_STATE_INACTIVE == afState /*add this*/) {
                          // 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_CONVERGED) {
                              mState = STATE_PICTURE_TAKEN;
                              captureStillPicture();
                          } else {
                              runPrecaptureSequence();
                          }
                      }
                      break;
                  }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-10-31
        相关资源
        最近更新 更多