Rotate camera preview to Portrait Android OpenCV Camera

前端 未结 17 1534
日久生厌
日久生厌 2020-12-07 15:45

I am trying to use OpenCV 2.4.3.2 to create a camera app and do some opencv processing. I would like it to be able to have multiple UI orientations, not just Landscape.

17条回答
  •  独厮守ぢ
    2020-12-07 16:34

    Thanks to @Kaye Wrobleski for his answer. I have extended it to allow both landscape and portrait orientation. This is basically just a little extra code to allow easily switching between the default code that gives landscape orientation, and his code for portrait.

    Insert his code as a new method in CameraBridgeViewBase.java

    protected void deliverAndDrawFramePortrait(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();
                // Rotate canvas to 90 degrees
                canvas.rotate(90f, canvas.getWidth()/2, canvas.getHeight()/2);
                if (canvas != null) {
                    canvas.drawColor(0, android.graphics.PorterDuff.Mode.CLEAR);
                    Log.d(TAG, "mStretch value: " + mScale);
    
                    if (mScale != 0) {
                        // Resize
                        Bitmap bitmap = Bitmap.createScaledBitmap(mCacheBitmap, canvas.getHeight(), canvas.getWidth(), true);
                        // Use bitmap instead of mCacheBitmap
                        canvas.drawBitmap(bitmap, new Rect(0,0,bitmap.getWidth(), bitmap.getHeight()), new Rect(
                                (int)((canvas.getWidth() - mScale*bitmap.getWidth()) / 2),
                                (int)((canvas.getHeight() - mScale*bitmap.getHeight()) / 2),
                                (int)((canvas.getWidth() - mScale*bitmap.getWidth()) / 2 + mScale*bitmap.getWidth()),
                                (int)((canvas.getHeight() - mScale*bitmap.getHeight()) / 2 + mScale*bitmap.getHeight())), null);
                    } else {
                        Bitmap bitmap = Bitmap.createScaledBitmap(mCacheBitmap, canvas.getHeight(), canvas.getWidth(), true);
                        // Use bitmap instead of mCacheBitmap
                        canvas.drawBitmap(bitmap, new Rect(0,0,bitmap.getWidth(), bitmap.getHeight()), new Rect(
                                (int)((canvas.getWidth() - bitmap.getWidth()) / 2),
                                (int)((canvas.getHeight() - bitmap.getHeight()) / 2),
                                (int)((canvas.getWidth() - bitmap.getWidth()) / 2 + bitmap.getWidth()),
                                (int)((canvas.getHeight() - bitmap.getHeight()) / 2 + bitmap.getHeight())), null);
                    }
    
                    if (mFpsMeter != null) {
                        mFpsMeter.measure();
                        mFpsMeter.draw(canvas, 20, 30);
                    }
                    getHolder().unlockCanvasAndPost(canvas);
                }
            }
        }
    

    Then modify JavaCameraView.java

    Add a new variable to track whether we are in portrait or landscape mode

    private boolean portraitMode;

    Add two methods to set the orientation mode

    public void setLandscapeMode() {
            portraitMode = false;
        }
        public void setPortraitMode() {
            portraitMode = true;
        }
    

    Now replace these lines in the JavaCameraView CameraWorkerClass, run() method

    if (!mFrameChain[1 - mChainIdx].empty())
                            deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]);
    

    With these lines:

    if (!mFrameChain[1 - mChainIdx].empty()) {
                            if (!portraitMode) {
                                deliverAndDrawFrame(mCameraFrame[1 - mChainIdx]);
                            } else {
                                deliverAndDrawFramePortrait(mCameraFrame[1 - mChainIdx]);
                            }
                        }
    

    To switch between orientations, simply call either setLandscapeMode() or setPortraitMode() on your JavaCameraView object.

    Please note that reverse portrait and reverse landscape orientations will still be upside-down. You will need to rotate them 180 degrees to get them right-side up, which is easily done with OpenCV's warpAffine() method. Note when using the back camera (LENS_FACING_BACK), portrait mode will flip the images upside down.

提交回复
热议问题