2016/08/28整理编辑,方法三已整理完毕
2017/03/25整理编辑
这里面的教程自己只在官方的颜色跟踪案例修改过。由于很久不搞安卓了,其他案例可能就没法去一一验证了。
文章只提供可行的思路,建议要修改的朋友先看下修改的原理再去改动。
2017/05/13 之前的代码,Github项目地址见文尾
Android终端下,OPENCV打开摄像头后,默认为横屏输入流,当设置为竖屏时,相机预览的图像可以看到如下图所示,并不能全屏。
下面介绍使得摄像头竖屏全屏的方法 ,方法一与方法二来自stackoverflow,方法三为笔者总结
实现后效果如下
方法一:
步骤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 项目地址 链接