Android通过OpenCV获取摄像头帧数据并在悬浮框显示

Android通过OpenCV获取摄像头帧数据并在悬浮框显示

由于Android手机摄像头采集的原始帧默认是横屏格式的,所以我们需要都原始帧进行旋转等操作。有上一篇博文中的需求我们需要获取的帧数据格式为Mat类型,使用AndroidSDK自带的camera类采集我们还需要自己再转化为Mat类型,所以在这里就直接使用opencv4android 中的CameraBridgeViewBase与AndroidSDK中CameraView类结合起来采集图片帧。

图片帧旋转

图片帧旋转主要是获取手机当前的姿态,然后根据当前角度,选择旋转角度从而达到正常的显示效果。

class MyOrientationDetector extends OrientationEventListener {
        public MyOrientationDetector(Context context) {
            super(context);
        }
        @Override
        public void onOrientationChanged(int orientation) {
            if (orientation == OrientationEventListener.ORIENTATION_UNKNOWN) {
                return; // 手机平放时,检测不到有效的角度
            }
            // 只检测是否有四个角度的改变
            if (orientation > 350 || orientation < 10) { // 0度
                orientation = 0;
                angle = 0f;
                orient = 0f;
            } else if (orientation > 80 && orientation < 100) { // 90度
                orientation = 90;
                angle = 270f;
                // angle = 90f;
                orient = 90f;
            } else if (orientation > 170 && orientation < 190) { // 180度
                orientation = 180;
                angle = 180f;
                // angle = 270f;
                orient = 180f;
            } else if (orientation > 260 && orientation < 280) { // 270度
                orientation = 270;
                angle = 90f;
                // angle = 90f;
                orient = 270f;
            } else {
                return;
            }
            Log.d("CameraService", orientation + "," + angle + "," + orient);
        }
    }   


    frameMat = inputFrame.rgba();   // 获取摄像头前景图像

    if (orient == 0) {// 竖放
        org.opencv.core.Core.flip(frameMat.t(), frameMat, 0);
    } else if (orient == 90) {
        org.opencv.core.Core.flip(frameMat, frameMat, -1);
    } else if (orient == 180) {
        org.opencv.core.Core.flip(frameMat.t(), frameMat, 1);
    } else if (orient == 270) {

    }                               
    mOpenCvCameraView.setRotate(angle);

悬浮窗显示

将经过旋转后的图片通过缩放尺寸大小后显示到悬浮窗中。

Size dsize = new Size(frameMat.width() * 0.25, frameMat.height() * 0.25); // 设置新图片的大小       
Imgproc.resize(frameMat, frameMat,dsize);//调用Imgproc的Resize方法,进行图片缩放  

创建悬浮窗

private void createFloatView()
{
    wmParams = new WindowManager.LayoutParams();
    //获取WindowManagerImpl.CompatModeWrapper
    mWindowManager = (WindowManager)getApplication().getSystemService(getApplication().WINDOW_SERVICE);
    //设置window type
    wmParams.type = LayoutParams.TYPE_PHONE; 
    //设置图片格式,效果为背景透明
    wmParams.format = PixelFormat.RGBA_8888; 
    //设置浮动窗口不可聚焦(实现操作除浮动窗口外的其他可见窗口的操作)
    wmParams.flags = LayoutParams.FLAG_NOT_FOCUSABLE;

    //调整悬浮窗显示的停靠位置为左侧置顶
    wmParams.gravity = Gravity.LEFT | Gravity.TOP; 

    // 以屏幕左上角为原点,设置xy初始值
    wmParams.x = 300;
    wmParams.y = 500;

    // 设置悬浮窗口长宽数据
    wmParams.width = 120;
    wmParams.height = 160;

    LayoutInflater inflater = LayoutInflater.from(getApplication());
    //获取浮动窗口视图所在布局
    mFloatLayout = (FrameLayout) inflater.inflate(R.layout.float_layout, null);
    //添加mFloatLayout
    mWindowManager.addView(mFloatLayout, wmParams);           
    mOpenCvCameraView = (BaseView) mFloatLayout.findViewById(R.id.CameraView);
    mFloatLayout.measure(View.MeasureSpec.makeMeasureSpec(0,
                View.MeasureSpec.UNSPECIFIED), View.MeasureSpec
                .makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));
    //设置监听浮动窗口的触摸移动
    mFloatLayout.setOnTouchListener(new OnTouchListener() {         
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            // TODO Auto-generated method stub
            wmParams.x = (int) event.getRawX() - mFloatLayout.getMeasuredWidth()/2;
            wmParams.y = (int) event.getRawY() - mFloatLayout.getMeasuredHeight()/2;
            mWindowManager.updateViewLayout(mFloatLayout, wmParams);
            return false;
        }
    });      
}

Demo(OpencvCamera)下载

你可能感兴趣的:(移动开发)