Android OpenCV 实例笔记3 -- 摄像头竖屏全屏的设置,更新完整代码

 Android OpenCV 实例笔记3 -- 三种方法  摄像头竖屏全屏的设置

 

 2016/08/28整理编辑,方法三已整理完毕

2017/03/25整理编辑

这里面的教程自己只在官方的颜色跟踪案例修改过。由于很久不搞安卓了,其他案例可能就没法去一一验证了。

文章只提供可行的思路,建议要修改的朋友先看下修改的原理再去改动。

2017/05/13 之前的代码,Github项目地址见文尾


Android终端下,OPENCV打开摄像头后,默认为横屏输入流,当设置为竖屏时,相机预览的图像可以看到如下图所示,并不能全屏。

下面介绍使得摄像头竖屏全屏的方法 ,方法一与方法二来自stackoverflow,方法三为笔者总结





实现后效果如下


Android OpenCV 实例笔记3 -- 摄像头竖屏全屏的设置,更新完整代码_第1张图片



方法一:

步骤1:

在CameraBridgeViewBase.JAVA文件的所有构造函数里,声明初始化一个 windowManager

具体如下。

先声明public WindowManager windowManager;

public CameraBridgeViewBase 里增加以下语句

windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);

步骤2:

在CameraBridgeViewBase.deliverAndDrawFrame(CvCameraViewFrame frame) 方法里:

//找到并替换已有if语句:
if (bmpValid && mCacheBitmap != null) {
        Canvas canvas = getHolder().lockCanvas();
        if (canvas != null) {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
            int rotation = windowManager.getDefaultDisplay().getRotation();
            int degrees = 0;
            // config degrees as you need
            switch (rotation) {
                case Surface.ROTATION_0:
                    degrees = -90;
                    break;
                case Surface.ROTATION_90:
                    break;
                case Surface.ROTATION_180:
                    break;
                case Surface.ROTATION_270:
                    degrees = 180;
                    break;
            }

            Matrix matrix = new Matrix();
            matrix.postRotate(degrees);
            Bitmap outputBitmap = Bitmap.createBitmap(mCacheBitmap, 0, 0, mCacheBitmap.getWidth(), mCacheBitmap.getHeight(), matrix, true);

            if (outputBitmap.getWidth() <= canvas.getWidth()) {
                mScale = getRatio(outputBitmap.getWidth(), outputBitmap.getHeight(), canvas.getWidth(), canvas.getHeight());
            } else {
                mScale = getRatio(canvas.getWidth(), canvas.getHeight(), outputBitmap.getWidth(), outputBitmap.getHeight());
            }

            if (mScale != 0) {
                canvas.scale(mScale, mScale, 0, 0);
            }
            Log.d(TAG, "mStretch value: " + mScale);

            canvas.drawBitmap(outputBitmap, 0, 0, null);

            if (mFpsMeter != null) {
                mFpsMeter.measure();
                mFpsMeter.draw(canvas, 20, 30);
            }
            getHolder().unlockCanvasAndPost(canvas);

        }
    }


步骤3: 增加下面这个方法(得到屏幕宽高比例)

private float getRatio(int widthSource, int heightSource, int widthTarget, int heightTarget) {
    if (widthTarget <= heightTarget) {   //
        return (float) heightTarget / (float) heightSource;
    } else {
        return (float) widthTarget / (float) widthSource;
    }
}


结果可以看到,在竖屏状态下也可以全屏了,但处理速度有所下降。


方法二

deliverAndDrawFrame()函数中,修改以下部分

 
  
if (canvas != null) {
    canvas.rotate(90,0,0);
    float scale = canvas.getWidth() / (float)mCacheBitmap.getHeight();
    float scale2 = canvas.getHeight() / (float)mCacheBitmap.getWidth();
    if(scale2 > scale){
        scale = scale2;
    }
    if (scale != 0) {
        canvas.scale(scale, scale,0,0);
    }
    canvas.drawBitmap(mCacheBitmap, 0, -mCacheBitmap.getHeight(), null);
   // canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
    Log.d(TAG, "mStretch value: " + mScale);

  /*  if (mScale != 0) {
        canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
                new Rect((int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2),
                        (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2),
                        (int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()),
                        (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2 + mScale*mCacheBitmap.getHeight())), null);
    } else {
        canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
                new Rect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,
                        (canvas.getHeight() - mCacheBitmap.getHeight()) / 2,
                        (canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
                        (canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
    }*/

方法三:

 
  
 
  
方法一和方法二经过实测,存在一定的问题,且会影响颜色跟踪处理速度。
方法三则采用了OPENCV自带的函数实现了相应的全屏,且处理速度也跟上了。
 
  

CameraBridgeViewBase.java 文件修改

以下以官方的颜色检测例程为例修改

旋转函数

//Imgproc.drawContours(mRgba,contours, -1, CONTOUR_COLOR); //在这个位置下添加
Core.transpose(this.mRgba,this.mRgbaT); //转置函数,可以水平的图像变为垂直
Imgproc.resize(this.mRgbaT,this.mRgbaF, this.mRgbaF.size(), 0.0D, 0.0D, 0); //将转置后的图像缩放为mRgbaF的大小
Core.flip(this.mRgbaF, this.mRgba,1);  //flipCode>0将mRgbaF水平翻转(沿Y轴翻转)得到mRgba

修改坐标转换算法(在涉及到坐标转换的函数里修改,如onTouch函数为例)
改为 
int cols = mRgba.cols();
int rows = mRgba.rows();
// int xOffset = (mOpenCvCameraView.getWidth() - cols) / 2;
//int yOffset = (mOpenCvCameraView.getHeight() - rows) / 2;
int x =(int)(event.getX()/mOpenCvCameraView.getWidth()*cols);
int y =(int)(event.getY()/mOpenCvCameraView.getHeight()*rows);
05/13 项目地址 链接
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
  
 
 

你可能感兴趣的:(安卓开发)