Android Camera2开启电子防抖(EIS)和光学防抖(OIS)

这篇具有很好参考价值的文章主要介绍了Android Camera2开启电子防抖(EIS)和光学防抖(OIS)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

刚好当前项目有录像功能,使用了第三方框架是基于Camera2引擎开发,当使用 Camera2 API 开发相机应用时,启用和关闭 EIS(电子防抖)是一个重要的功能。EIS 可以帮助减少相机拍摄时的抖动,从而提高图像和视频的稳定性;OIS是光学图片想稳定器,功能是通过镜头的浮动透镜来纠正“光轴偏移”,需要硬件的支持,两者同时开启在录像时效果更佳。

EIS原理:

使用CCD偏移来实现防抖,通过降低图像失真和抖动,从而提高图像质量,首先把CCD安置在一个可以上下左右移动的支架上,然后当陀螺传感器检测到抖动的时候,就会把抖动的方向、速度和移动量等参数经过处理,计算出足以抵消抖动的CCD移动量,简单说就是通过放大录像焦距,根据陀螺仪旋转时预留周边的视角通过进行补帧移动画面给人感觉没有那么抖动,但效果没有光学防抖的好。

OIS原理:

其原理是通过镜头内的陀螺仪侦测到微小的移动,然后将信号传至微处理器,处理器立即计算需要补偿的位移量,然后通过补偿镜片组,根据镜头的抖动方向及位移量加以补偿。

对比开启EIS和OIS的摄像对比

eis开

eis关

1. 检查设备支持的特性

在使用 Camera2 API 开启 EIS 之前,我们需要首先检查设备是否支持 EIS 特性。我们可以通过 CameraCharacteristics 类来获取相机设备的特性信息。

 CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraDevice.getId());
            boolean isModeHaveStabilization = false; // 支持电子防抖
        
            final int[] availableVideoStabilization = characteristics.get(
                    CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES);
            if (availableVideoStabilization == null || availableVideoStabilization.length == 0) {
                Log.e(TAG, "Optical stabilization not available");
                return;
            }
            for (int mode : availableVideoStabilization) {
                if (mode == CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON) {
                    isModeHaveStabilization = true;
                    Log.d(TAG, "Using video stabilization.");
                    break;
                }
            }


  int[] stabilizationModes = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION);
            if (stabilizationModes == null || stabilizationModes.length == 0) {
                Log.e(TAG, "Optical stabilization not available");
                return;
            }
            for (int mode : stabilizationModes) {
                if (mode == CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON) {
                    isModeSupported = true;   // 支持光学防抖
                    break;
                }
            }
2. 启用 EIS和关闭EIS

记得判断是否支持EIS

// 开启EIS
mPreviewBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);

//关闭EIS
mPreviewBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF);
3. 启用OIS和关闭OIS
 captureRequestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,
                        mEisEnabled ? CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON :
                                CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_OFF);

在创建预览请求的时候注意一定要设置成录制模式,预览模式开启不了EIS,设置无效

mPreviewBuilder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);

下面时完整代码片段,希望可以帮助到有需要的人

public class Camera2Activity extends AppCompatActivity {

    private static final String TAG = "Camera2Example";
    private TextureView mTextureView;
    private CameraDevice mCameraDevice;
    private CaptureRequest.Builder mPreviewBuilder;
    private CameraCaptureSession mCaptureSession;
    // private SurfaceTexture mSurfaceTexture;
    private Button captureModel;
    //private Camera2Helper mCamera2Helper;
    boolean mEisEnabled = true;
    private Handler backgroundHandler;
    private HandlerThread backgroundThread;

    @SuppressLint("MissingInflatedId")
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera);
        initView();
    }
    private void initView() {
        captureModel = (Button) findViewById(R.id.captureModel);
        mTextureView = findViewById(R.id.textureView);
        mCaptureButton = findViewById(R.id.captureButton);
        if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.CAMERA}, 200);
            return;
        }
        findViewById(R.id.eisopen).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                enableEis();
            }
        });
        findViewById(R.id.eisclose).setOnClickListener(v -> {
            disableEis();
        });
        captureModel.setOnClickListener(v -> {
            switchMode();
        });
    }

    private TextureView.SurfaceTextureListener textureListener = new TextureView.SurfaceTextureListener() {
        @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            openCamera();
        }

        @Override
        public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
        }

        @Override
        public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
            return false;
        }

        @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {
        }
    };

    //打开相机
    public void openCamera() {
        CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
        try {
            String cameraId = cameraManager.getCameraIdList()[0];
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
                // 请求权限
                ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 200);

                return;
            }
            cameraManager.openCamera(cameraId, new CameraDevice.StateCallback() {
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    mCameraDevice = camera;
                    createCameraPreviewSession();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    mCameraDevice.close();
                    mCameraDevice = null;
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    mCameraDevice.close();
                    mCameraDevice = null;
                }
            }, null);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    // 创建CameraCaptureSession
    private void createCameraPreviewSession() {
        try {
            SurfaceTexture texture = mTextureView.getSurfaceTexture();
            // 设置预览尺寸
            texture.setDefaultBufferSize(mTextureView.getWidth(), mTextureView.getHeight());
            assert texture != null;
            // 创建预览Surface
            Surface surface = new Surface(texture);
            // 创建CaptureRequest.Builder
            mPreviewBuilder = mCameraDevice.createCaptureRequest(mCurrentMode);
            // 设置自动对焦模式
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);
            // 设置自动曝光模式
            mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE, CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);
            mPreviewBuilder.addTarget(surface);
            toggleStabilization(mPreviewBuilder);
            // 创建CameraCaptureSession
            mCameraDevice.createCaptureSession(Collections.singletonList(surface),
                    new CameraCaptureSession.StateCallback() {

                        @Override
                        public void onConfigured(@NonNull CameraCaptureSession cameraCaptureSession) {
                            // 相机已经关闭
                            if (null == mCameraDevice) {
                                return;
                            }
                            // 会话准备好后,我们开始显示预览
                            mCaptureSession = cameraCaptureSession;
                            updatePreview();
                        }

                        @Override
                        public void onConfigureFailed(@NonNull CameraCaptureSession cameraCaptureSession) {
                            //   showToast("Failed");
                        }
                    }, backgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    int mCurrentMode = CameraDevice.TEMPLATE_PREVIEW;

    // 在点击按钮时切换模式
    private void switchMode() {
        if (mCurrentMode == CameraDevice.TEMPLATE_PREVIEW) {
            // 切换到录制模式
            mCurrentMode = CameraDevice.TEMPLATE_RECORD;
            createCameraPreviewSession();
            captureModel.setText("切换到预览模式");
        } else {
            // 切换到预览模式
            mPreviewBuilder.set(CaptureRequest.CONTROL_AF_TRIGGER, CameraMetadata.CONTROL_AF_TRIGGER_CANCEL);
            mCurrentMode = CameraDevice.TEMPLATE_PREVIEW;
            createCameraPreviewSession();
            captureModel.setText("切换到录制模式");
        }
    }

    // 电子防抖和光学防抖
    private void toggleStabilization(CaptureRequest.Builder captureRequestBuilder) {
        if (mPreviewBuilder == null) {
            return;
        }
        try {

            CameraManager manager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
            CameraCharacteristics characteristics = manager.getCameraCharacteristics(mCameraDevice.getId());
            boolean isModeHaveStabilization = false; // 支持电子防抖
            boolean isModeSupported = false; // 支持光学防抖

            final int[] availableVideoStabilization = characteristics.get(
                    CameraCharacteristics.CONTROL_AVAILABLE_VIDEO_STABILIZATION_MODES);
            if (availableVideoStabilization == null || availableVideoStabilization.length == 0) {
                Log.e(TAG, "Optical stabilization not available");
                return;
            }
            for (int mode : availableVideoStabilization) {
                if (mode == CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON) {
                    isModeHaveStabilization = true;
                    Log.d(TAG, "Using video stabilization.");
                    break;
                }
            }
            // 开启EIS电子防抖功能
            if (mEisEnabled && isModeHaveStabilization) {
                mPreviewBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_ON);
                mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_USE_SCENE_MODE);
                mPreviewBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, CameraMetadata.CONTROL_SCENE_MODE_ACTION); // hrd 动作场景模式
            } else {
                mPreviewBuilder.set(CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE, CaptureRequest.CONTROL_VIDEO_STABILIZATION_MODE_OFF);
                mPreviewBuilder.set(CaptureRequest.CONTROL_MODE, CameraMetadata.CONTROL_MODE_USE_SCENE_MODE);
                mPreviewBuilder.set(CaptureRequest.CONTROL_SCENE_MODE, CameraMetadata.CONTROL_SCENE_MODE_ACTION); // hrd  动作场景模式
            }

            int[] stabilizationModes = characteristics.get(CameraCharacteristics.LENS_INFO_AVAILABLE_OPTICAL_STABILIZATION);
            if (stabilizationModes == null || stabilizationModes.length == 0) {
                Log.e(TAG, "Optical stabilization not available");
                return;
            }
            for (int mode : stabilizationModes) {
                if (mode == CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON) {
                    isModeSupported = true;
                    break;
                }
            }
            // 开启OIS光学防抖功能
            if (isModeSupported) {
                captureRequestBuilder.set(CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE,
                        mEisEnabled ? CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_ON :
                                CaptureRequest.LENS_OPTICAL_STABILIZATION_MODE_OFF);
            }
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    // 更新预览
    private void updatePreview() {
        if (null == mCameraDevice) {
            return;
        }
        try {
            mCaptureSession.setRepeatingRequest(mPreviewBuilder.build(), null, backgroundHandler);
        } catch (CameraAccessException e) {
            e.printStackTrace();
        }
    }

    // 开启EIS电子防抖功能
    private void enableEis() {
        mEisEnabled = true;
        toggleStabilization(mPreviewBuilder);
        updatePreview();
    }

    // 关闭EIS电子防抖功能
    private void disableEis() {
        mEisEnabled = false;
        toggleStabilization(mPreviewBuilder);
        updatePreview();
    }

    @Override
    protected void onResume() {
        super.onResume();
        startBackgroundThread();
        if (mTextureView.isAvailable()) {
            openCamera();
        } else {
            mTextureView.setSurfaceTextureListener(textureListener);
        }

    }

    @Override
    protected void onPause() {
        super.onPause();
        stopBackgroundThread();
        closeCamera();
    }

    private void closeCamera() {
        if (mCaptureSession != null) {
            mCaptureSession.close();
            mCaptureSession = null;
        }
        if (mCameraDevice != null) {
            mCameraDevice.close();
            mCameraDevice = null;
        }
    }


    private void startBackgroundThread() {
        backgroundThread = new HandlerThread("CameraBackground");
        backgroundThread.start();
        backgroundHandler = new Handler(backgroundThread.getLooper());
    }

    private void stopBackgroundThread() {
        backgroundThread.quitSafely();
        try {
            backgroundThread.join();
            backgroundThread = null;
            backgroundHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

翻译

搜索

复制文章来源地址https://www.toymoban.com/news/detail-799443.html

到了这里,关于Android Camera2开启电子防抖(EIS)和光学防抖(OIS)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • NDK Android平台camera2采集视频

    《Android平台使用camera2采集视频 代码实现 》链接: https://edu.csdn.net/learn/38258/606148?spm=1003.2001.3001.4157 在Android平台开发实时音视频项目,摄像头的采集是一个必不可少的流程;通常在Android平台上采集摄像头数据可以使用Camera1接口、Camera2接口或者CameraX接口。Camera1接口只支持

    2024年02月11日
    浏览(55)
  • Android Camera2 —CameraManager API详解

    一、CameraManager类概述 CameraManager是用于检测、表征和连接到 CameraDevices 的系统服务管理器。 CameraManager 是一个负责查询和建立相机连接的系统服务,它的功能不多,这里列出几个 CameraManager 的关键功能: 1)、将相机信息封装到 Camera Characteristics 中,并提获取 CameraCharacterist

    2024年02月12日
    浏览(43)
  • Android studio Camera2实现的详细流程

    前提 TextureView.SurfaceTextureListener是一个接口,用于监听TextureView中的SurfaceTexture的状态更改。在使用相机时,您可以使用TextureView来显示相机预览。通过实现SurfaceTextureListener接口,您可以在SurfaceTexture准备好时开始相机预览,并在SurfaceTexture销毁时停止预览。 注意 : 必须是在

    2024年02月05日
    浏览(34)
  • 十分钟实现 Android Camera2 视频录制

    因为工作中要使用 Android Camera2 API ,但因为 Camera2 比较复杂,网上资料也比较乱,有一定入门门槛,所以花了几天时间系统研究了下,并在 CSDN 上记录了下,希望能帮助到更多的小伙伴。 上两篇文章使用 Camera2 实现了相机预览和拍照的功能,这篇文章我们接着上文,来实现

    2024年02月11日
    浏览(38)
  • 十分钟实现 Android Camera2 相机预览

    因为工作中要使用 Android Camera2 API ,但因为 Camera2 比较复杂,网上资料也比较乱,有一定入门门槛,所以花了几天时间系统研究了下,并在 CSDN 上记录了下,希望能帮助到更多的小伙伴。 Camera2 API 的包名是 android.hardware.camera2 ,是 Android 5.0 后推出的一套调用摄像头设备的接口

    2024年02月13日
    浏览(52)
  • 十分钟实现 Android Camera2 相机拍照

    因为工作中要使用 Android Camera2 API ,但因为 Camera2 比较复杂,网上资料也比较乱,有一定入门门槛,所以花了几天时间系统研究了下,并在 CSDN 上记录了下,希望能帮助到更多的小伙伴。 上篇文章 我们使用 Camera2 实现了相机预览的功能,这篇文章我们接着上文,来实现 Cam

    2024年02月11日
    浏览(42)
  • android camera系列(Camera1、Camera2、CameraX)的使用以及输出的图像格式

    1.1.1、布局 1.1.2、实现预览 Camera.open() 打开摄像头 setPreviewDisplay 设置预览展示的控件 startPreview 开始预览 发现预览是横着的,需要使用 setDisplayOrientation 调整预览图像的方向 1.1.3、获取摄像头的原始数据 setPreviewCallback 设置预览数据的回调 2560*1440 默认返回图像的分辨率 Image

    2024年02月21日
    浏览(36)
  • 学习笔记 -- 从零开始学习Android Camera2 -- (1)

    学习一个框架,第一步学习肯定是照着代码看文档。 既然要看代码,就要看最权威的,这里我是代码是参照https://github.com/android/camera-samples android给的官方示例,结合官方文档https://developer.android.com/reference/android/hardware/camera2/package-summary来看,所以首先要先看一遍文档,然后重

    2024年02月03日
    浏览(36)
  • Android studio APK切换多个摄像头(Camera2)

    1.先设置camera的权限 2.布局 3.主界面代码 这部分代码是用来授权AndroidManifest.xml里面权限的第三方sdk代码 效果:

    2024年02月11日
    浏览(38)
  • Android 使用Camera2 API 和 GLSurfaceView实现相机预览

    GLSurfaceView 和 SurfaceView 是 Android 中用于显示图像的两个视图类,它们在实现方式和使用场景上有一些区别。 实现方式:GLSurfaceView 基于 OpenGL ES 技术实现,可以通过 OpenGL ES 渲染图像。而 SurfaceView 则是通过基于线程的绘制方式,可以在独立的线程中进行绘制操作。 性能:由于

    2024年02月09日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包