10

在 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 时 - 程序工作,但是当我旋转设备时,程序工作,但显示的图像不旋转

4

2 回答 2

11

您的问题主要与此重复,除了您正在寻找 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);
    }

笔记:

  • 这些示例可能是特定于方向的,我将它们用于横向。
  • 您不应为每个视频帧调用这些示例中的代码。有些代码应该只运行一次。
于 2012-10-21T14:20:26.493 回答
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;
}
于 2017-04-12T10:52:34.187 回答