【问题标题】:Android: how to detect if camera flashedAndroid:如何检测相机是否闪烁
【发布时间】:2015-10-27 16:33:45
【问题描述】:

我正在使用 Android 的 Camera2 API,我目前希望相机在准备闪光时执行特定操作。

在构建 CaptureRequest 时,以下行:

captureRequest.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);

允许相机在低光照条件下闪光。但是,我不知道如何检测相机是否准备好闪光。似乎有关此特定动作的在线文献很少。

我在处理相机的CaptureCallback 中的部分结果时尝试检查FLASH_STATE 是否在FLASH_STATE_READY 中,但似乎密钥不可用 - 它一直返回null。也许我检查的地方不对?

相机的CaptureCallback,如下所示(基于谷歌的Camera2Basic 代码示例):

private CameraCaptureSession.CaptureCallback mCaptureCallback
        = new CameraCaptureSession.CaptureCallback()    {
    private void process(CaptureResult result)  {
        switch(mState)  {
            case STATE_PREVIEW: break;
            case STATE_WAITING_LOCK:
                // checking if result.get(CaptureResult.FLASH_STATE) == 
                // CaptureResult.FLASH_READY over here didn't work because
                // null was returned
                int afState = result.get(CaptureResult.CONTROL_AF_STATE);
                if (CaptureResult.CONTROL_AF_STATE_FOCUSED_LOCKED == afState ||
                        CaptureResult.CONTROL_AF_STATE_NOT_FOCUSED_LOCKED == afState) {
                    Integer aeState = result.get(CaptureResult.CONTROL_AE_STATE);
                    if (aeState == null ||
                            aeState == CaptureResult.CONTROL_AE_STATE_CONVERGED) {
                        mState = STATE_WAITING_NON_PRECAPTURE;
                        captureStillPicture();
                    } else {
                        runPrecaptureSequence();
                    }
                }
                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_WAITING_NON_PRECAPTURE;
                }
                break;
            case STATE_WAITING_NON_PRECAPTURE:
                Integer aeState1 = result.get(CaptureResult.CONTROL_AE_STATE);
                if (aeState1 == null || aeState1 != CaptureResult.CONTROL_AE_STATE_PRECAPTURE) {
                    mState = STATE_PICTURE_TAKEN;
                    captureStillPicture();
                }
                break;
        }
    }

    @Override
    public void onCaptureProgressed(CameraCaptureSession session,
                                    CaptureRequest request, CaptureResult partialResult) {
        super.onCaptureProgressed(session, request, partialResult);
        process(partialResult);
    }

    @Override
    public void onCaptureCompleted(CameraCaptureSession session,
                                   CaptureRequest request, TotalCaptureResult result) {
        super.onCaptureCompleted(session, request, result);
        process(result);
    }
};

【问题讨论】:

  • 在Camera2 API中检查以下类以获取Flash,stackoverflow.com/questions/27420594/…
  • 要读取闪存状态,请等待总捕获结果并在那里检查闪存状态;部分可能还没有所有字段(通常它们具有完成 AF 等所需的字段以提高速度)。

标签: java android android-camera


【解决方案1】:

documentation 中,您可以阅读FLASH_STATE 键的以下语句:

可选 - 此值在某些设备上可能为空。

基本上,即使您使用的是 Lollipop 设备,也不能确定是否支持 Camera2 APi 的所有功能。功能受限的设备称为“受限设备”。

有关更多信息,请查看this 页面。这很好地描述了它。

编辑: 要回答基本上错误的评论: 文件说:

当相机设备没有闪光灯单元时(即 android.flash.info.available == false),此状态将始终为 UNAVAILABLE。其他状态表示当前的 flash 状态。

因此,如果设备上没有闪存,FLASH_STATE 也存在并将返回UNAVAILABLE

文档说明了您必须知道的几乎所有内容。最重要的事实是,它取决于硬件级别/硬件模式。


让我们总结一下

对于旧设备

它将返回以下内容

  • 如果 AE 模式设置为 ON_ALWAYS_FLASH 则触发
  • 如果闪光灯模式设置为手电筒则触发
  • 如果相机没有闪光灯,则不可用。

当设备至少是 LEVEL_LIMITED 时:

这些值是可能的,但不能保证它们都有效:

  • 不可用
  • 充电中
  • 准备好了
  • 被解雇
  • 部分

【讨论】:

  • 感谢您的快速响应和资源。所以我想一种解决方案是实现检查FLASH_STATE键并将其用于支持它的设备,但如果设备不支持它,是否仍然可以以其他方式进行检查?
  • 你是对的,通常的方法是检查你请求的值。我不确定是否有其他方法,但我想没有。因为智能手机厂商自己要实现一个硬件抽象层来支持camera2 api的功能。所以我猜如果你不能以这种方式请求状态,那么这个特性就缺少硬件和程序之间的通信接口。
  • 如果设备具有闪存单元,则将显示 FLASH_STATE。
【解决方案2】:

目前没有办法确定闪光灯是否会闪光 - 相机设备会在全分辨率拍摄前的最后一刻做出决定。一旦获得全分辨率捕获的最终捕获结果,如果闪光灯确实触发,它的flash state 应该是FIRED,但事后你会得到这个。确保等待来自onCaptureCompleted 的总捕获结果来检查此字段,而不是来自 onCaptureProgressed 的部分;部分结果可能缺少各个字段。

也就是说,如果在开始预捕获序列之前的AE state fieldFLASH_REQUIRED,那么如果 AE 模式允许闪光灯 (AE_MODE_ON_AUTO_FLASH / ALWAYS_FLASH / AUTO_FLASH_REDEYE),则很可能会触发闪光灯。这不是 100% 的保证,因为场景可能会在预捕获序列开始(将执行预捕获闪光以估计必要的闪光功率)和实际最终图片捕获之间的几帧内发生变化。但我怀疑 95% 的情况下这将是最终结果。

【讨论】:

  • 看起来很有希望,但即使是 CONTROL_AE_STATE 也是可选的! (即,如果您查看文档,上面写着Optional - This value may be null on some devices.)。在我的特定设备上确实如此,它始终输出null。我猜唯一有保证的检查 flash 是在它已经发生之后?
  • 您的设备是 LEGACY 级别的设备吗?如果是这样,是的,那么就没有什么可以透露这些信息了。由于缺乏直接的硬件支持,LEGACY 设备在旧 API 之上有效地运行 camera2 API,因此它们可以生成的信息相当有限。请注意,“可选”并不意味着该字段是否存在是完全任意的。这意味着配置存在于不存在的地方,因此应该小心,但大多数条目都有明确定义的存在要求。 AE_STATE 必须出现在 LIMITED 或以上的设备上。
【解决方案3】:

问题

您正在尝试检测您的应用拍摄的图片是否使用了闪光灯。

解决方案

您可以在使用相机时使用Camera.Parameters检查闪光灯的状态,无论闪光灯是AUTO、ON还是OFF。

代码

您可以使用以下代码示例来检查相机的闪光灯状态。

Camera.Parameters p = mCamera.getParameters();

if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_ON))
{
 //DO STUFF
}
else if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_OFF))
{
//DO STUFF
}
else if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_TORCH))
{
//DO STUFF
}
else if(p.getFlashMode().equals(android.hardware.Camera.Parameters.FLASH_MODE_AUTO))
{
//DO STUFF
}
else
{
//DO STUFF
}

【讨论】:

  • Camera.Parameters 自 API 21 起已弃用。将它与 Camera API2 结合使用是个好主意吗?
  • 感谢您的快速回复-尽管问题-如果相机设置为自动,我如何检查相机是否确实要闪光?因为有时在 AUTO 中它会闪烁,而其他时候则不会。
  • @rfblue2 在 AUTO 的情况下,您应该检查捕获图像后触发的 FLASH_STATE。希望这可以帮助。在开始编写代码之前,您可能需要参考此官方文档:developer.android.com/reference/android/hardware/camera2/…
【解决方案4】:

Camera API 没有被弃用,遵循 Camera2 API 的代码 sn-p 来检查闪光灯是否可用,

CameraManager mCameraManager = (CameraManager) context.getSystemService(Context.CAMERA_SERVICE);
//here to judge if flash is available

CameraCharacteristics cameraCharacteristics = mCameraManager.getCameraCharacteristics("0");
boolean flashAvailable = cameraCharacteristics.get(CameraCharacteristics.FLASH_INFO_AVAILABLE);
if (flashAvailable) {
         mCameraManager.openCamera("0", new MyCameraDeviceStateCallback(), null);
} else {
       //todo: throw Exception
}

【讨论】:

  • 感谢您的快速回复。我不是在寻找相机是否有闪光灯(已在其他问题中回答),而是在设置为自动闪光时闪光灯是否即将闪光,因为在自动模式下,闪光灯有时会闪光,有时会闪光没有
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-30
相关资源
最近更新 更多