返回

深入浅出,相机预览及简单滤镜开发详解

Android

相机预览

相机预览是指将摄像头的实时画面显示在屏幕上。实现相机预览的基本原理是:摄像头采集图像数据,然后将这些数据传输给图像处理单元,图像处理单元对图像数据进行处理,最后将处理后的图像数据显示在屏幕上。

相机预览及简单滤镜开发

接下来,我们将详细讲解如何使用Opengles进行相机预览并添加滤镜。

1. 准备工作

在开始开发之前,我们需要准备以下工具和材料:

  • Android Studio
  • OpenCV库
  • EGL库
  • GLES库

2. 创建Android项目

首先,我们需要创建一个新的Android项目。打开Android Studio,点击“新建项目”,然后选择“空项目”。在“项目名称”中输入项目的名称,在“包名称”中输入项目的包名,然后点击“下一步”。

3. 添加依赖项

接下来,我们需要添加OpenCV库、EGL库和GLES库的依赖项。在Android Studio的“项目结构”窗口中,点击“依赖项”选项卡,然后点击“添加依赖项”。在“依赖项”对话框中,选择“库依赖项”,然后搜索OpenCV库、EGL库和GLES库。找到这些库后,点击“确定”按钮。

4. 创建相机预览Activity

接下来,我们需要创建一个相机预览Activity。在Android Studio中,右键点击项目的包名,然后选择“新建” > “Activity” > “空Activity”。在“Activity名称”中输入Activity的名称,然后点击“完成”按钮。

5. 实现相机预览

接下来,我们需要实现相机预览功能。在相机预览Activity的Java文件中,添加以下代码:

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;

import org.opencv.android.OpenCVLoader;

import java.nio.ByteBuffer;
import java.util.Arrays;

public class CameraPreviewActivity extends AppCompatActivity {

    private static final String TAG = "CameraPreviewActivity";

    private TextureView mTextureView;
    private Button mButton;
    private CameraManager mCameraManager;
    private CameraDevice mCameraDevice;
    private CameraCaptureSession mCameraCaptureSession;
    private ImageReader mImageReader;
    private Surface mSurface;
    private boolean mIsPreviewing = false;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_camera_preview);

        mTextureView = (TextureView) findViewById(R.id.textureView);
        mButton = (Button) findViewById(R.id.button);

        mCameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);

        // 申请相机权限
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, 100);
            return;
        }

        // 打开相机
        try {
            String[] cameraIds = mCameraManager.getCameraIdList();
            for (String cameraId : cameraIds) {
                CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
                if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) {
                    mCameraManager.openCamera(cameraId, mStateCallback, null);
                    break;
                }
            }
        } catch (CameraAccessException e) {
            Log.e(TAG, "打开相机失败", e);
        }

        // 创建ImageReader
        mImageReader = ImageReader.newInstance(640, 480, ImageFormat.YUV_420_888, 2);
        mImageReader.setOnImageAvailableListener(new ImageReader.OnImageAvailableListener() {
            @Override
            public void onImageAvailable(ImageReader reader) {
                Image image = reader.acquireLatestImage();
                if (image != null) {
                    // 处理图像数据
                    ByteBuffer buffer = image.getPlanes()[0].getBuffer();
                    byte[] data = new byte[buffer.remaining()];
                    buffer.get(data);

                    // 释放图像
                    image.close();
                }
            }
        }, null);

        // 创建SurfaceTexture
        mSurfaceTexture = new SurfaceTexture(100);
        mSurfaceTexture.setOnFrameAvailableListener(new SurfaceTexture.OnFrameAvailableListener() {
            @Override
            public void onFrameAvailable(SurfaceTexture surfaceTexture) {
                // 更新纹理视图
                mTextureView.updateViewLayout(mTextureView.getWidth(), mTextureView.getHeight());
                mTextureView.invalidate();
            }
        });

        // 创建Surface
        mSurface = new Surface(mSurfaceTexture);

        // 创建CaptureRequest
        CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
        builder.addTarget(mSurface);
        builder.addTarget(mImageReader.getSurface());

        // 创建CameraCaptureSession
        mCameraDevice.createCaptureSession(Arrays.asList(mSurface, mImageReader.getSurface()), mSessionCallback, null);
    }

    private CameraDevice.StateCallback mStateCallback = new CameraDevice.StateCallback() {
        @Override
        public void onOpened(@NonNull CameraDevice camera) {
            mCameraDevice = camera;
            mIsPreviewing = true;

            // 启动预览
            mCameraDevice.createCaptureSession(Arrays.asList(mSurface, mImageReader.getSurface()), mSessionCallback, null);
        }

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

        @Override
        public void onError(@NonNull CameraDevice camera, int error) {
            mIsPreviewing = false;
            mCameraDevice.close();
            mCameraDevice = null;
        }
    };

    private CameraCaptureSession.StateCallback mSessionCallback = new CameraCaptureSession.StateCallback() {
        @Override
        public void onConfigured(@NonNull CameraCaptureSession session) {
            mCameraCaptureSession = session;

            // 设置自动对焦
            CaptureRequest.Builder builder = mCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            builder.addTarget(mSurface);
            builder.addTarget(mImageReader.getSurface());
            builder.set(CaptureRequest.CONTROL_AF_MODE, CaptureRequest.CONTROL_AF_MODE_CONTINUOUS_PICTURE);

            // 启动预览
            mCameraCaptureSession.setRepeatingRequest(builder.build(), null, null);
        }

        @Override
        public void onConfigureFailed(@NonNull CameraCaptureSession session) {
            Log.e(TAG, "配置CameraCaptureSession失败");
        }
    };

    @Override
    protected void onResume() {
        super.onResume();

        if (OpenCVLoader.initDebug()) {
            Log.i(TAG, "OpenCV加载成功");
        } else {
            Log.e(TAG, "OpenCV加载失败");
        }

        if (!mIsPreviewing) {
            // 重新打开相机
            try {
                String[] cameraIds = mCameraManager.getCameraIdList();
                for (String cameraId : cameraIds) {
                    CameraCharacteristics characteristics = mCameraManager.getCameraCharacteristics(cameraId);
                    if (characteristics.get(CameraCharacteristics.LENS_FACING) == CameraCharacteristics.LENS_FACING_BACK) {
                        mCameraManager.openCamera(