java 在 Android 上的 OpenCV 中旋转 VideoCapture

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12949793/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 10:55:36  来源:igfitidea点击:

Rotate VideoCapture in OpenCV on Android

javaandroidopencvvideo-capture

提问by user1755546

How to rotate the camera when using class VideoCapture on OpenCV? (Sample Face Detection on Android). I'm rotating the canvas with:

在 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);
}

but image from Camera doesn't rotate: Face Detect dont work.

但来自相机的图像不旋转:人脸检测不起作用。

The camera receives the stream from the following:

相机从以下位置接收流:

protected Bitmap processFrame(VideoCapture capture) {

    capture.retrieve(mRgba, Highgui.CV_CAP_ANDROID_COLOR_FRAME_RGBA);

    capture.retrieve(mGray,
    Highgui.CV_CAP_ANDROID_GREY_FRAME);

UPDATE I did the following:

更新我做了以下事情:

@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);

But is dont work. When I run the program in portret orientation(on android device)- program don't start When i run the rogram in landscape orientation - programm work, but when i rotation the device, program work, but image on display dont rotation

但不工作。当我以 portret 方向运行程序时(在 android 设备上)-程序不启动当我以横向运行程序时-程序工作,但是当我旋转设备时,程序工作,但显示的图像不旋转

回答by Rui Marques

Your question is mostly a duplicate of this, except that you are looking for the Android version. It is quite similar but here it is, 90o rotation can be obtained by transposing and then flipping the image:

您的问题主要是this重复,只是您正在寻找 Android 版本。它非常相似,但在这里,可以通过转置然后翻转图像来获得 90o 旋转:

# rotate 90o counter-clockwise
Core.flip(mRgba.t(), mRgba, 0); //mRgba.t() is the transpose

# rotate 90o clockwise
Core.flip(mRgba.t(), mRgba, 1);

For other rotations you can use warpAffine:

对于其他旋转,您可以使用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);

EDIT - more complete examples follow:

编辑 - 更完整的示例如下:

    /** 
     * 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);
    }

Note:

笔记:

  • These examples might be orientation-specific, I made them for landscape orientation.
  • You should not call the code from these examples for every video frame. Some of the code should only run once.
  • 这些示例可能是特定于方向的,我将它们用于横向。
  • 您不应为每个视频帧调用这些示例中的代码。一些代码应该只运行一次。

回答by Jan Moritz

If you only need to do 90, 180, or 270 degrees rotation (Which seems to be your case) you better use Core.flip() which is faster. Here below a method that does it for you:

如果您只需要旋转 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;
}