OpenCV4Android中图像预览旋转90度的问题

本文介绍了解决OpenCV在Android应用中预览图像旋转90度的问题。通过修改CameraBridgeViewBase中的deliverAndDrawFrame方法,实现了图像正确显示且全屏的效果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在将OpenCV4Android导入到Android项目之后,可以使用JavaCameraView控件调用相机,但是显示预览时,可能出现图像旋转了90度的情况。

在网上找到几种办法,都是修改OpenCV4Android中的CameraBridgeViewBase中的deliverAndDrawFrame方法,分别试了一下:

1、Android开发使用OpenCv中JavaCameraView预览图左旋90度问题

试用了,方法无效,不知道是不是我的其他配置的问题

2、参考了Rotate camera preview to Portrait Android OpenCV Camera的回复

protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
    Mat modified;

    if (mListener != null) {
        modified = mListener.onCameraFrame(frame);
    } else {
        modified = frame.rgba();
    }

    boolean bmpValid = true;
    if (modified != null) {
        try {
            Utils.matToBitmap(modified, mCacheBitmap);
        } catch (Exception e) {
            Log.e(TAG, "Mat type: " + modified);
            Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
            Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
            bmpValid = false;
        }
    }

    if (bmpValid && mCacheBitmap != null) {
        Canvas canvas = getHolder().lockCanvas();
        if (canvas != null) {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
            // 修改预览旋转90问题
            // 能够通过旋转,正常显示预览,但是图像被缩放了
            //canvas.drawBitmap(mCacheBitmap, (canvas.getWidth() - mCacheBitmap.getWidth()) / 2, (canvas.getHeight() - mCacheBitmap.getHeight()) / 2, null);
            //Change to support portrait view
            Matrix matrix = new Matrix();
            matrix.preTranslate((canvas.getWidth() - mCacheBitmap.getWidth()) / 2, (canvas.getHeight() - mCacheBitmap.getHeight()) / 2);

            if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
                matrix.postRotate(90f, (canvas.getWidth()) / 2, (canvas.getHeight()) / 2);
            canvas.drawBitmap(mCacheBitmap, matrix, new Paint());
            // 修改预览旋转90问题end

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

修改后的效果就是图像没有全屏。

3、还是参考上面的回答

protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
    Mat modified;

    if (mListener != null) {
        modified = mListener.onCameraFrame(frame);
    } else {
        modified = frame.rgba();
    }

    boolean bmpValid = true;
    if (modified != null) {
        try {
            Utils.matToBitmap(modified, mCacheBitmap);
        } catch (Exception e) {
            Log.e(TAG, "Mat type: " + modified);
            Log.e(TAG, "Bitmap type: " + mCacheBitmap.getWidth() + "*" + mCacheBitmap.getHeight());
            Log.e(TAG, "Utils.matToBitmap() throws an exception: " + e.getMessage());
            bmpValid = false;
        }
    }

    if (bmpValid && mCacheBitmap != null) {
        Canvas canvas = getHolder().lockCanvas();
        if (canvas != null) {
            canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);

            // 修改预览旋转90度问题
            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);
            // 修改预览旋转90度问题end

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

这样预览图片可以全屏,并且是正的了。



<think>好的,我现在需要帮助用户解决OpenCVAndroid中竖屏摄像头旋转问题。首先,我得回顾一下用户提供的引用内容,看看里面有哪些解决方案。引用1提到竖屏模式下的图像方向不正确,引用2和3则具体说明了使用CameraBridgeViewBase类以及如何通过代码旋转图像。引用4提到可能需要修改SDK中的图像获取模块,但用户可能希望更直接的解决方案。用户的问题很明确,就是如何在Android上使用OpenCV时处理竖屏摄像头旋转。我需要整理出几个步骤,确保解决方案清晰易懂。根据引用3,Activity需要设置屏幕方向,并且实现onCameraFrame方法,在竖屏时旋转Mat对象。同时要注意前置和后置摄像头旋转方向不同,可能还需要翻转。另外,引用2提到CameraBridgeViewBase类的使用,这可能涉及到XML布局中的配置,比如设置摄像头方向。用户可能需要代码示例,所以应该提供Java或Kotlin的代码片段,说明如何调整旋转和翻转。还要考虑AndroidManifest.xml中的配置,确保Activity的屏幕方向正确。此外,是否需要在初始化时调整预览方向?比如调用setCameraIndex或setCameraPermissionHint等方法。可能还需要检查设备方向,根据当前方向动态调整旋转方式。例如,在竖屏时旋转90,横屏时不需要。同时处理前置摄像头镜像的问题,使用Core.flip进行水平翻转。最后,确保提供的代码正确无误,语法正确,并且用户能够直接复制到项目中进行测试。可能还需要提醒用户测试不同设备和摄像头的情况,因为不同厂商可能有不同的默认方向。总结步骤应该是:配置Activity方向,调整CameraBridgeViewBase参数,在onCameraFrame中根据方向旋转图像,处理前置摄像头翻转。这样分点回答,结构清晰,用户容易跟随。</think>### OpenCV Android竖屏摄像头旋转问题解决方案 在Android开发中使用OpenCV处理竖屏摄像头图像时,需通过代码调整图像旋转方向和布局配置。以下是具体步骤: #### 1. 配置Activity屏幕方向 在`AndroidManifest.xml`中指定Activity为竖屏模式: ```xml <activity android:name=".MainActivity" android:screenOrientation="portrait" /> ``` #### 2. 初始化摄像头视图 在XML布局文件中使用`CameraBridgeViewBase`类: ```xml <org.opencv.android.JavaCameraView android:id="@+id/camera_view" android:layout_width="match_parent" android:layout_height="match_parent" /> ``` #### 3. 图像旋转处理 在Activity中实现`CvCameraViewListener2`接口,修改`onCameraFrame`方法: ```java @Override public Mat onCameraFrame(CvCameraViewFrame inputFrame) { Mat rgba = inputFrame.rgba(); // 竖屏模式下旋转图像 if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { if (mCameraView.isFrontCamera()) { Core.rotate(rgba, rgba, Core.ROTATE_90_COUNTERCLOCKWISE); Core.flip(rgba, rgba, 1); // 前置摄像头镜像翻转 } else { Core.rotate(rgba, rgba, Core.ROTATE_90_CLOCKWISE); } } return rgba; } ``` #### 4. 设置摄像头预览方向 初始化时调用`setCameraPermissionHint`: ```java mCameraView.setCameraPermissionHint(CameraBridgeViewBase.CAMERA_ID_ANY); mCameraView.setCvCameraViewListener(this); ``` #### 技术原理 OpenCV默认以横屏模式采集图像,竖屏时需手动旋转$90^\circ$。通过`Core.rotate()`函数实现矩阵旋转,其中: - `Core.ROTATE_90_CLOCKWISE`对应顺时针旋转$90^\circ$ - `Core.ROTATE_90_COUNTERCLOCKWISE`对应逆时针旋转$90^\circ$ 前置摄像头需额外使用`Core.flip()`进行水平镜像翻转,解决图像左右颠倒问题[^3][^4]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值