在 Android 上的 OpenCV 中旋转 VideoCapture
Posted
技术标签:
【中文标题】在 Android 上的 OpenCV 中旋转 VideoCapture【英文标题】:Rotate VideoCapture in OpenCV on Android 【发布时间】:2012-10-08 14:59:12 【问题描述】:在 OpenCV 上使用 VideoCapture 类时如何旋转相机? (android 上的人脸检测示例)。 我正在旋转画布:
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
Matrix matrix = new Matrix();
matrix.preTranslate(
(canvas.getWidth() - bmp.getWidth()) / 2,
(canvas.getHeight() - bmp.getHeight()) / 2);
matrix.postRotate(270f, (canvas.getWidth()) / 2,
(canvas.getHeight()) / 2);
canvas.drawBitmap(bmp, matrix, null);
但来自相机的图像不旋转:人脸检测不起作用。
相机从以下接收流:
protected Bitmap processFrame(VideoCapture capture)
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
capture.retrieve(mGray,
Highgui.CV_CAP_ANDROID_GREY_FRAME);
更新 我做了以下事情:
@Override
protected Bitmap processFrame(VideoCapture capture)
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
Core.flip(mRgba.t(), mRgba, 0);
else
capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);
capture.retrieve(mDetect_thread.mGray,
Highgui.CV_CAP_ANDROID_GREY_FRAME);
但是不工作。当我以 portret 方向(在 android 设备上)运行程序时 - 程序不启动当我以横向方向运行 rogram 时 - 程序工作,但是当我旋转设备时,程序工作,但显示的图像不旋转
【问题讨论】:
【参考方案1】:您的问题主要是duplicate of this,只是您正在寻找Android版本。它非常相似,但在这里,可以通过转置然后翻转图像来获得 90º 旋转:
# rotate 90º counter-clockwise
Core.flip(mRgba.t(), mRgba, 0); //mRgba.t() is the transpose
# rotate 90º clockwise
Core.flip(mRgba.t(), mRgba, 1);
对于其他轮换,您可以使用warpAffine:
Point center = new Point(x,y);
double angle = 90;
double scale = 1.0;
Mat mapMatrix = Imgproc.getRotationMatrix2D(center, angle, scale);
Imgproc.warpAffine(srcMat, dstMat, mapMatrix, Imgproc.INTER_LINEAR);
编辑 - 更完整的示例如下:
/**
* Image is first resized-to-fit the dst Mat and then rotated.
* mRgba is the source image, mIntermediateMat should have the same type.
*/
private void rotationTutorial()
double ratio = mRgba.height() / (double) mRgba.width();
int rotatedHeight = mRgba.height();
int rotatedWidth = (int) Math.round(mRgba.height() * ratio);
Imgproc.resize(mRgba, mIntermediateMat, new Size(rotatedHeight, rotatedWidth));
Core.flip(mIntermediateMat.t(), mIntermediateMat, 0);
Mat ROI = mRgba.submat(0, mIntermediateMat.rows(), 0, mIntermediateMat.cols());
mIntermediateMat.copyTo(ROI);
/**
* Image is rotated - cropped-to-fit dst Mat.
*
*/
private void rotationAffineTutorial()
// assuming source image's with and height are a pair value:
int centerX = Math.round(mRgba.width()/2);
int centerY = Math.round(mRgba.height()/2);
Point center = new Point(centerY,centerX);
double angle = 90;
double scale = 1.0;
double ratio = mRgba.height() / (double) mRgba.width();
int rotatedHeight = (int) Math.round(mRgba.height());
int rotatedWidth = (int) Math.round(mRgba.height() * ratio);
Mat mapMatrix = Imgproc.getRotationMatrix2D(center, angle, scale);
Size rotatedSize = new Size(rotatedWidth, rotatedHeight);
mIntermediateMat = new Mat(rotatedSize, mRgba.type());
Imgproc.warpAffine(mRgba, mIntermediateMat, mapMatrix, mIntermediateMat.size(), Imgproc.INTER_LINEAR);
Mat ROI = mRgba.submat(0, mIntermediateMat.rows(), 0, mIntermediateMat.cols());
mIntermediateMat.copyTo(ROI);
注意:
这些示例可能是特定方向的,我将它们用于横向。 您不应为每个视频帧调用这些示例中的代码。有些代码应该只运行一次。【讨论】:
当然可以。人脸识别无法通过旋转图像开箱即用。 @gregm 我已经修复了原始帖子的一些错别字,并提供了一些更完整的示例。如果您之前没有设法让它工作,您可能无法正确输出结果图像。这些示例展示了如何输出它(但可以提高效率)。 @RuiMarques 你好。 FeatureDetector 现在偏离了 90 度。我该如何解决?【参考方案2】:如果您只需要进行 90、180 或 270 度旋转(这似乎是您的情况),您最好使用更快的 Core.flip()。 下面是一个为你做的方法:
public static Mat rotate(Mat src, double angle)
Mat dst = new Mat();
if(angle == 180 || angle == -180)
Core.flip(src, dst, -1);
else if(angle == 90 || angle == -270)
Core.flip(src.t(), dst, 1);
else if(angle == 270 || angle == -90)
Core.flip(src.t(), dst, 0);
return dst;
【讨论】:
以上是关于在 Android 上的 OpenCV 中旋转 VideoCapture的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Android 中将 OpenCV 旋转和平移矢量与 OpenGL ES 一起使用?
android opencv - 每次旋转是不是有可能捕捉到对 3D 对象的不同点击?