Camera2 API触发闪光灯/无闪光灯图像的问题 [英] Camera2 api problems firing flash/no flash images

查看:246
本文介绍了Camera2 API触发闪光灯/无闪光灯图像的问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将解释我的情况. 我正在尝试做一个应用程序,其中每5秒钟将拍摄一张图像,一个不带闪光灯,然后在5秒钟后一个带闪光灯,并每次重复一次.因此,将需要一个不带闪光灯的,一个带闪光灯的,一个不带闪光灯的,一个带闪光灯的...无限.

I will explain my case. I'm trying to do an application in which every 5 seconds will take an image, one without flash, and then after 5 seconds one with flash, and repeat this every time. So it will take one without flash, one with flash, one without flash, one with flash... infinitely.

情况是,使用我的代码,我可以在某些设备中执行此操作,但相同的代码将无法在其他设备中正常工作.即:

The case is that with my code I can do this in some devices, but the same code won't work in others as I want. i.e:

  • BQ Aquaris X5 Plus :无闪光图像正确,但闪光图像仅为白色.
  • BQ Aquaris E5 :不会闪光.
  • BQ Aquaris X5 Plus : The no-flash image is correct, but the flash image will be just white.
  • BQ Aquaris E5 : Won't fire the flash.

这怎么可能,我尝试过的所有设备都是Camera2 API的LEGACY硬件支持级别.

How can this be possible, all devices in which I have tried are LEGACY hardware support level for Camera2 API.

这是我代码中的一些重要方法(由于字符数限制,我无法发布所有代码).我从Google示例开始:

This are some important methods in my code (I can't post all code due to char limit). I started from the Google Example:

此setAutoFlash会执行上述操作.

This setAutoFlash does the mentioned above.

private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
        if (mFlashSupported) {
            if(phototaken) {
                requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
            }else{
                requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_SINGLE);
            }
        }
    }

这另一台设备可在某些设备和bq aquaris e5中使用,但不会在bq aquaris x5 plus中闪光.

This other one works in some devices and the bq aquaris e5 but doesn't fire the flash in the bq aquaris x5 plus.

private void setAutoFlash(CaptureRequest.Builder requestBuilder) {
        if (mFlashSupported) {
            if(phototaken) {
                requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
                requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
            }else{
                requestBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_ALWAYS_FLASH);
                requestBuilder.set(CaptureRequest.FLASH_MODE, CaptureRequest.FLASH_MODE_OFF);
            }
        }
    }

还有我的captureStillPicture

And my captureStillPicture

private void captureStillPicture() {
        try {
            final Activity activity = getActivity();
            if (null == activity || null == mCameraDevice) {
                return;
            }
            // This is the CaptureRequest.Builder that we use to take a picture.
            final CaptureRequest.Builder captureBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_STILL_CAPTURE);
            captureBuilder.addTarget(mImageReader.getSurface());

            // Use the same AE and AF modes as the preview.
            captureBuilder.set(CaptureRequest.CONTROL_AF_MODE,
                    CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            setAutoFlash(captureBuilder);

            // Orientation
            int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
            captureBuilder.set(CaptureRequest.JPEG_ORIENTATION, getOrientation(rotation));

            CameraCaptureSession.CaptureCallback CaptureCallback
                    = new CameraCaptureSession.CaptureCallback() {
                @Override
                public void onCaptureCompleted(@NonNull CameraCaptureSession session,
                                               @NonNull CaptureRequest request,
                                               @NonNull TotalCaptureResult result) {
                    showToast("Saved: " + mFile);
                    Log.d(TAG, mFile.toString());
                    unlockFocus();
                }
            };

            mCaptureSession.stopRepeating();
            mCaptureSession.capture(captureBuilder.build(), CaptureCallback, null);
            phototaken = !phototaken;

        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
}

问题是,我在做什么错,因此它不适用于所有设备?任何帮助都会很棒.

The question is, what am i doing wrong so it doesn't work in all devices? Any help will be great.

推荐答案

闪光灯有两种控制级别-手动和自动曝光例程控制.您目前正在将它们混合在一起.

There are two levels of control for the flash - manual, and controlled by the auto-exposure routine. You're currently mixing them together.

如果要手动闪光,则需要将AE_MODE设置为AE_MODE_OFF或AE_MODE_ON.并非任何FLASH模式.然后,FLASH_MODE将控制闪光灯针对给定请求是处于手电筒模式,关闭还是闪光一次.

If you want to fire the flash manually, then you need to set AE_MODE to either AE_MODE_OFF or AE_MODE_ON; not any of the FLASH modes. Then, FLASH_MODE will control whether the flash will be in torch mode, off, or fire once for a given request.

由于您始终将AE_MODE保持为FLASH状态之一,因此对FLASH_MODE所做的操作无关紧要,除非某些特定设备中存在错误.

Since you're always leave AE_MODE in one of the FLASH states, what you do to FLASH_MODE should not matter, barring a bug in some specific device.

如果要保证每隔一张照片都闪光,则需要对强制闪光照片使用AE_MODE_ON_ALWAYS_FLASH,而对于不闪光照片则需要使用AE_MODE_ON;请勿触摸FLASH_MODE. 现在,使用AUTO_FLASH取决于设备是否闪光,因此您将看到不同设备和光照条件下的不同行为-有些会闪光,有些不会闪光.

If you want to guarantee flash firing in every other picture, you need to use AE_MODE_ON_ALWAYS_FLASH for the force-flash photos, and you need to use AE_MODE_ON for the no-flash phoots; don't touch FLASH_MODE. Right now, with AUTO_FLASH, it's up to the device whether to fire a flash or not, so you'll see different behavior from different devices and lighting conditions - some will fire, some won't.

您没有做的另一项关键操作是运行预捕获序列.这对闪光灯图片至关重要,因为它使设备可以触发预闪以确定正确的闪光灯功率,聚焦和白平衡.

The other key thing you're not doing is running a precapture sequence; this is essential for flash pictures, because it allows the device to fire the preflash to determine correct flash power, focus, and white balance.

要运行预捕获,请根据需要设置AE_MODE,然后针对一个请求将AE_PRECAPTURE_TRIGGER设置为START.这会将AE_STATE转换为PRECAPTURE,并将在其中停留一些帧;一旦AE_STATE不再是PRECAPTURE,则可以发出实际的图像捕获请求.在整个过程中,请确保AE_MODE保持一致.

To run precapture, set the AE_MODE as desired, and then set AE_PRECAPTURE_TRIGGER to START for one request. This will transition AE_STATE to PRECAPTURE, and it'll stay there for some number of frames; once AE_STATE is no longer PRECAPTURE, you can issue the actual image capture request. Make sure you keep the AE_MODE consistent throughout this.

示例应用程序 Camera2Basic 实现了预捕获序列,因此请看这里;它还具有一些优化功能,可以在场景不足够黑暗以至于无法使用闪光灯的情况下跳过预捕获,但是由于您要强制闪光,因此这与您无关.

The sample app Camera2Basic implements the precapture sequence, so take a look there; it also has some optimizations that skip precapture in case the scene is not dark enough to need flash, but since you want to force-fire flash, that's not relevant to you.

这篇关于Camera2 API触发闪光灯/无闪光灯图像的问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆