AR相机的实现

首先需要声明的是,我并不是原创每个概念,而是在前人的基础上做了一个实现,原理如图:

AR红包

上面的图片来自AR红包Android端实现原理

上面的难点我觉得可能是处理一帧图像的方法,这个方法有两个,分别是Camera和Camera2提供的,先看看Camera2的示例:

  // 开始预览,主要是camera.createCaptureSession这段代码很重要,创建会话  
    private void startPreview(CameraDevice camera) throws CameraAccessException {  
        SurfaceTexture texture = mPreviewView.getSurfaceTexture();  

//      这里设置的就是预览大小  
        texture.setDefaultBufferSize(mPreviewSize.getWidth(), mPreviewSize.getHeight());</span>  
        Surface surface = new Surface(texture);  
        try {  
            // 设置捕获请求为预览,这里还有拍照啊,录像等  
            mPreviewBuilder = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);  
        } catch (CameraAccessException e) {  
            e.printStackTrace();  
        }  

//      就是在这里,通过这个set(key,value)方法,设置曝光啊,自动聚焦等参数!! 如下举例:  
//      mPreviewBuilder.set(CaptureRequest.CONTROL_AE_MODE,CaptureRequest.CONTROL_AE_MODE_ON_AUTO_FLASH);  



    mImageReader = ImageReader.newInstance(mSurfaceView.getWidth(), mSurfaceView.getHeight(), ImageFormat.JPEG/*此处还有很多格式,比如我所用到YUV等*/, 2/*最大的图片数,mImageReader里能获取到图片数,但是实际中是2+1张图片,就是多一张*/);   

        mImageReader.setOnImageAvailableListener(mOnImageAvailableListener, mHandler);  
       // 这里一定分别add两个surface,一个Textureview的,一个ImageReader的,如果没add,会造成没摄像头预览,或者没有ImageReader的那个回调!!  
        mPreviewBuilder.addTarget(surface);  
    mPreviewBuilder.addTarget(mImageReader.getSurface());  
        mCameraDevice.createCaptureSession(Arrays.asList(surface, mImageReader.getSurface()),mSessionStateCallback, mHandler);  
    }  

    private CameraCaptureSession.StateCallback mSessionStateCallback = new CameraCaptureSession.StateCallback() {  

        @Override  
        public void onConfigured(CameraCaptureSession session) {  
            try {  
                updatePreview(session);  
            } catch (CameraAccessException e) {  
                e.printStackTrace();  
            }  
        }  

        @Override  
        public void onConfigureFailed(CameraCaptureSession session) {  

        }  
    };  

    private void updatePreview(CameraCaptureSession session) throws CameraAccessException {  
        session.setRepeatingRequest(mPreviewBuilder.build(), null, mHandler);  
    }  

    private ImageReader.OnImageAvailableListener mOnImageAvailableListener  
            = new ImageReader.OnImageAvailableListener() {  

        /** 
         *  当有一张图片可用时会回调此方法,但有一点一定要注意: 
         *  一定要调用 reader.acquireNextImage()和close()方法,否则画面就会卡住!!!!!我被这个坑坑了好久!!! 
         *    很多人可能写Demo就在这里打一个Log,结果卡住了,或者方法不能一直被回调。 
         **/  
        @Override  
        public void onImageAvailable(ImageReader reader) {  
             Image img = reader.acquireNextImage();  
             /** 
              *  因为Camera2并没有Camera1的Priview回调!!!所以该怎么能到预览图像的byte[]呢?就是在这里了!!!我找了好久的办法!!! 
              **/  
              ByteBuffer buffer = img.getPlanes()[0].getBuffer();  
              byte[] data = new byte[buffer.remaining()];  
              buffer.get(data);      
              img.close();  
            }  
         };  
 }  

上述方法也可以实现图像的处理,但是我使用红米以及小米5在测试过程中发现卡顿非常严重,尽管检查了图片处理的线程是子线程,但是每秒钟大概处理6张预览图的时候还是依然卡顿,因此我排除了这个方法。

除了Camera2的方法以外,还有Camera的方法,而原理介绍中已经讲解了方法,如下:

三、获取一帧预览图像

Camera.setOneShotPreviewCallback(PreviewCallback cb)方法可以获取一帧预览图像,数据会返回到PreviewCallback 回调中的 onPreviewFrame(byte[] data,Camera camera)方法中,data即为帧数据。

由于我已经在Camera2测试了,因此我并没有直接使用这个方法来测试,而是参考了Zxing的二维码扫描这个库,因为这个二维码的处理逻辑其实是非常相似的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值