Unity EasyAR 使用自定义UVC相机(安卓)

项目是安卓接入AR眼镜,使用AR眼镜的Camera进行识别

首先安卓手机接入AR眼镜后,不能直接打开相机,需要使用AndroidStudio写一个驱动注册,这部分是网上的代码,因为不是做安卓驱动开发的所以具体也不清楚,就不讲了。

然后自己使用AndroidStudio在网上代码上封装了打开关闭相机,以及回调byte[] 的图片数据

使用Unity调用测试成功。

结合EasyAR

easyAr 3.0有一个CustomCamera 的示例,这个示例会调用相机然后获取图片byte[]数组,然后传给EasyAR的识别部分。这个自定义相机要安卓支持,所以直接使用是不行的。

CustomCameraProxy类中,写了具体和相机的交互。

在数据回调中会使用  HandleSink(buffer, format, imageSize, orientation, cameraType, timestamp);这个函数。

因此只需要在自己相机回调中,调用这个函数就可以了。

 

EasyAR的CustomCamera安卓jar包中也封装了数据的结构,可以仿照他的代码写。


测试有效 ,但是需要修改AR Session代码中的调用函数。图片格式不能是压缩格式,easyar只支持固定的几种格式,因此在获取相机byte[] 数据后,格式不对的需要转换。

 

用这个逻辑,识别其实不一定要视频,图片应该也是可以的,EasyAR底层只是接收了图片数据

包括陀螺仪的数据,其实也是可以自己修改的,但是需要重新编译EasyAR的jar包,这样就可以实现AR眼镜的slam效果了。通过将眼镜Camera的图像替换,和眼镜陀螺仪数据替换,因为本身没有这个接口(所以只能重新编译jar包),希望后期还是能开放一下这些接口吧

 

这是我写的修改的CustomCameraProxy类,如果你自己要修改的话,需要根据你们自己java代码写法修改的。java层代码就不方便公布了,因为有很多其他数据在里面。其实你们把EasyAR那个CustomCamera的jar包打开看看就能明白了



#if EasyAR3Project
using AOT;
using UnityEngine;
using System;
using System.Runtime.InteropServices;

namespace easyar
{
    public class CustomCameraProxy
    {
        private InputFrameSink targetSink;
        

        public void Init()
        {
             WorldCamera.SetFrameCallBack(UpdateFrame);
        }

        private void UpdateFrame(AndroidJavaObject dataWrapper)
        {
            if (targetSink == null)
            {
                return;
            }

            var byteArray = dataWrapper.Get("Buffer");
            var jniByteArray = byteArray.GetRawObject();

            var buffer = JniUtility.wrapByteArray(jniByteArray, true, () => { byteArray.Dispose(); });
            var param = dataWrapper.Get("camParams");
            int cameraType = param.Call("getCameraType");
            double timestamp = param.Call("getTimestamp") * 1e-9;
            var imageWidth = param.Call("getWidth");
            var imageHeight = param.Call("getHeight");
            var imageSize = new Vector2(imageWidth, imageHeight);
            //HandleSink(buffer, PixelFormat.RGBA8888, imageSize, 0 , 1 , timestamp);
            HandleSink(buffer, PixelFormat.Gray, imageSize, 0, 1, timestamp);
        }

        public void Start()
        {
             WorldCamera.Open();
        }

        public void Stop()
        {
              WorldCamera.Close();
        }

        public void Dispose()
        {
          
        }

        public void Connect(InputFrameSink sink)
        {
            targetSink = sink;
        }

        private void HandleSink(Buffer imageBuffer, PixelFormat format, Vector2 imageSize, int orientation, int cameraType, double timestamp)
        {
            var cameraParams = CameraParameters.createWithDefaultIntrinsics(new Vec2I((int)imageSize.x, (int)imageSize.y), (CameraDeviceType)cameraType, orientation);
            var image = new Image(imageBuffer, format, (int)imageSize.x, (int)imageSize.y);
            var frame = InputFrame.createWithImageAndCameraParametersAndTemporal(image, cameraParams, timestamp);
            targetSink.handle(frame);

            imageBuffer.Dispose();
            frame.Dispose();
            image.Dispose();
            cameraParams.Dispose();
        }
    }
}
#endif

 

 

 

你可能感兴趣的:(Unity,EasyAR)