web-dev-qa-db-fra.com

Faire pivoter l'aperçu de l'appareil photo vers Portrait Android OpenCV Camera

J'essaie d'utiliser OpenCV 2.4.3.2 pour créer une application d'appareil photo et effectuer un traitement opencv. J'aimerais qu'il puisse avoir plusieurs orientations d'interface utilisateur, pas seulement Paysage.

Le problème est que lorsque je change l'orientation en portrait, l'image sort latéralement.

Je comprends que je pourrais simplement faire pivoter l'image d'entrée avant de faire le traitement d'image (et donc laisser l'orientation uniquement en paysage), ce qui est bien et fonctionne, mais ne résout pas le problème que le reste de mon L'interface utilisateur sera dans la mauvaise orientation.

J'ai également essayé d'utiliser ce code pour faire pivoter la caméra à 90 degrés, mais cela ne semble pas fonctionner.

mCamera.setDisplayOrientation(90);

Soit il n'a aucun effet, soit il suffit parfois de masquer l'aperçu

Quelqu'un a-t-il réussi cela avec OpenCV? Ma classe s'étend de JavaCameraView. portrait image with sideways preview

Éditer

J'ai apporté une amélioration, c'est que j'ai fait pivoter l'image à l'intérieur d'OpenCV telle qu'elle est affichée dans la classe CameraBridgeViewBase.Java.

Dans la méthode du cadre de livraison et de dessin:

if (canvas != null) {
            canvas.drawColor(0, Android.graphics.PorterDuff.Mode.CLEAR);
            //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());

... Fondamentalement, cela fait simplement rentrer l'image d'entrée comme ça

input image rotated 90

C'est mieux, mais je veux évidemment que ce soit en plein écran.

35
Jameo

J'ai eu le même problème en essayant d'implémenter OpenCV. J'ai pu le corriger en apportant les modifications suivantes à la méthode deliveryAndDrawFrame.

  1. Faire pivoter l'objet canevas

    Canvas canvas = getHolder().lockCanvas();
    // Rotate canvas to 90 degrees
    canvas.rotate(90f, canvas.getWidth()/2, canvas.getHeight()/2);
    
  2. Redimensionnez le bitmap pour l'adapter à toute la taille du canevas avant de dessiner

    // 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);
    
    // Unlock canvas
    getHolder().unlockCanvasAndPost(canvas);
    
12
Kaye Wrobleski

en fait, vous pouvez simplement créer un parent mathématique de largeur ou de hauteur (plein écran).

if (canvas != null) {
        Bitmap bitmap = Bitmap.createScaledBitmap(mCacheBitmap, canvas.getHeight(), canvas.getWidth(), true);
        canvas.rotate(90,0,0);
        float scale = canvas.getWidth() / (float)bitmap.getHeight();
        float scale2 = canvas.getHeight() / (float)bitmap.getWidth();
        if(scale2 > scale){
            scale = scale2;
        }
        if (scale != 0) {
            canvas.scale(scale, scale,0,0);
        }
        canvas.drawBitmap(bitmap, 0, -bitmap.getHeight(), null);

...

Vous pouvez également agrandir la taille de l'aperçu par rapport à l'écran. Modifiez simplement l'échelle.

10
K Lam

J'ai modifié CameraBridgeViewBase.Java comme suit:

protected Size calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) {
    int calcWidth = 0;
    int calcHeight = 0;

    if(surfaceHeight > surfaceWidth){
        int temp = surfaceHeight;
        surfaceHeight = surfaceWidth;
        surfaceWidth = temp;
    }

Et dans la fonction "deliveryAndDrawFrame":

            if (mScale != 0) {
                if(canvas.getWidth() > canvas.getHeight()) {
                canvas.drawBitmap(mCacheBitmap, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
                     new Rect((int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2),
                     (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2),
                     (int)((canvas.getWidth() - mScale*mCacheBitmap.getWidth()) / 2 + mScale*mCacheBitmap.getWidth()),
                     (int)((canvas.getHeight() - mScale*mCacheBitmap.getHeight()) / 2 + mScale*mCacheBitmap.getHeight())), null);
                } else {
                    canvas.drawBitmap(mCacheBitmap, rotateMe(canvas, mCacheBitmap), null);
                }

où rotationMe est défini comme suit:

private Matrix rotateMe(Canvas canvas, Bitmap bm) {
    // TODO Auto-generated method stub
    Matrix mtx=new Matrix();
    float scale = (float) canvas.getWidth() / (float) bm.getHeight();
    mtx.preTranslate((canvas.getWidth() - bm.getWidth())/2, (canvas.getHeight() - bm.getHeight())/2);
    mtx.postRotate(90,canvas.getWidth()/2, canvas.getHeight()/2);
    mtx.postScale(scale, scale, canvas.getWidth()/2 , canvas.getHeight()/2 );
    return mtx;
}

L'aperçu FPS est plus lent car pour les frais de calcul par rapport au mode paysage.

9
jaiprakashgogi

Malheureusement, Opencv4Android ne prend pas en charge la caméra portrait. Mais il existe un moyen de le surmonter. 1) Écrivez votre appareil photo personnalisé et réglez son orientation sur portrait. 2) Enregistrez-vous pour son rappel de prévisualisation. 3) Dans onPreviewFrame(byte[]data, Camera camera) créez Mat d'octets d'aperçu:

Mat mat = new Mat(previewSize.height, previewSize.width, CvType.CV_8UC1);
mat.put(0, 0, data);

Core.transpose(mat, mat);
Core.flip(mat, mat, -1); // rotates Mat to portrait

CvType dépend du format de prévisualisation utilisé par votre appareil photo.

PS. n'oubliez pas de libérer toutes les instances Mat que vous avez créées lorsque vous avez terminé.

PPS. il est bon de gérer votre caméra sur un thread séparé afin de ne pas surcharger le thread d'interface lors de la détection.

5
vitaliy.gerasymchuk

j'ai le même problème, j'ai compris !! et voici ma solution:

dans le cadre du premier, Dans CameraBridgeViewBase.Java, les deux constructeurs, ajoutez l'initialisation de WindowManager:

public CameraBridgeViewBase(Context context, int cameraId) {  
   super(context);  
   mCameraIndex = cameraId;  
   getHolder().addCallback(this);  
   mMaxWidth = MAX_UNSPECIFIED;  
   mMaxHeight = MAX_UNSPECIFIED;  
   windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  

}

public CameraBridgeViewBase(Context context, AttributeSet attrs) {  
   super(context, attrs);  
   int count = attrs.getAttributeCount();  
   Log.d(TAG, "Attr count: " + Integer.valueOf(count));  

   TypedArray styledAttrs = getContext().obtainStyledAttributes(attrs, R.styleable.CameraBridgeViewBase);  
   if (styledAttrs.getBoolean(R.styleable.CameraBridgeViewBase_show_fps, false))  
       enableFpsMeter();  

   mCameraIndex = styledAttrs.getInt(R.styleable.CameraBridgeViewBase_camera_id, -1);  

   getHolder().addCallback(this);  
   mMaxWidth = MAX_UNSPECIFIED;  
   mMaxHeight = MAX_UNSPECIFIED;  
   windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);  
   styledAttrs.recycle();  

}

ensuite, vous devez remplacer la fonction deliverAndDrawFrame(CvCameraViewFrame frame) comme suit,

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);  
          int rotation = windowManager.getDefaultDisplay().getRotation();  
          int degrees = 0;  
          // config degrees as you need  
          switch (rotation) {  
              case Surface.ROTATION_0:  
                  degrees = 90;  
                  break;  
              case Surface.ROTATION_90:  
                  degrees = 0;  
                  break;  
              case Surface.ROTATION_180:  
                  degrees = 270;  
                  break;  
              case Surface.ROTATION_270:  
                  degrees = 180;  
                  break;  
          }  

          Matrix matrix = new Matrix();  
          matrix.postRotate(degrees);  
          Bitmap outputBitmap = Bitmap.createBitmap(mCacheBitmap, 0, 0, mCacheBitmap.getWidth(), mCacheBitmap.getHeight(), matrix, true);  

          if (outputBitmap.getWidth() <= canvas.getWidth()) {  
              mScale = getRatio(outputBitmap.getWidth(), outputBitmap.getHeight(), canvas.getWidth(), canvas.getHeight());  
          } else {  
              mScale = getRatio(canvas.getWidth(), canvas.getHeight(), outputBitmap.getWidth(), outputBitmap.getHeight());  
          }  

          if (mScale != 0) {  
              canvas.scale(mScale, mScale, 0, 0);  
          }  
          Log.d(TAG, "mStretch value: " + mScale);  

          canvas.drawBitmap(outputBitmap, 0, 0, null);  

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

      }  
  }  

}

et ajoutez cette fonction supplémentaire,

private float getRatio(int widthSource, int heightSource, int widthTarget, int heightTarget) {  
   if (widthTarget <= heightTarget) {  
       return (float) heightTarget / (float) heightSource;  
   } else {  
       return (float) widthTarget / (float) widthSource;  
   }  

}

c'est bon, et si cette réponse vous est utile, veuillez cocher 'accepté' Aide Réputation

3
isicout

Toutes les réponses ici sont des hacks. je préfère cette solution:

changement dans le code JavaCameraView:

mBuffer = new byte[size];
mCamera.setDisplayOrientation(90); //add this
mCamera.addCallbackBuffer(mBuffer);

Deuxième changement:

//                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
//                        mSurfaceTexture = new SurfaceTexture(MAGIC_TEXTURE_ID);
//                        mCamera.setPreviewTexture(mSurfaceTexture);
//                    } else
//                       mCamera.setPreviewDisplay(null);
                    mCamera.setPreviewDisplay(getHolder());
2
Ofek Ron

Si vous utilisez openCV 2.4.9, essayez: 1) de copier le contenu du traitement mixte tutoriel opencv dans votre code; 2) corriger les erreurs de non concordance (nom d'activité et probablement référence de mise en page); 3) Modifiez votre manifeste en ajoutant Android:screenOrientation ="landscape" 4) corriger les erreurs des mineurs et courir !!!! bbaamm (cela devrait fonctionner correctement maintenant)

Remarque: avec cette méthode, la barre d'état apparaît sur le côté droit lorsque le téléphone est en position portrait. Puisque nous développons un projet de caméra, je vous conseille de supprimer la barre d'état de l'aperçu.

J'espère que cela aide !!!

1
Edess Elder

Il semble que la nouvelle classe OpenCV CameraBridgeViewBase.Java Soit de trop haut niveau et ne donne pas assez de contrôle sur la disposition de l'aperçu de la caméra. Jetez un œil à mon exemple de code , qui est basé sur certains des anciens exemples OpenCV et utilise le code Android code Android. Pour utiliser le tableau d'octets passé dans onPreviewFrame, put() en un Mat et convertissez de YUV en RGB:

mYuv = new Mat(previewHeight + previewHeight/2, previewWidth, CvType.CV_8UC1);
mYuv.put(0, 0, mBuffer);
Imgproc.cvtColor(mYuv, mRgba, Imgproc.COLOR_YUV420sp2RGBA, 4);

Vous pourrez peut-être trouver les anciens exemples d'OpenCV4Android sur Internet, bien qu'ils aient été retirés il y a quelques versions. Cependant, l'exemple de code lié et l'extrait ci-dessus devraient être suffisants pour vous aider à démarrer.

1
1''

Merci à @Kaye Wrobleski pour sa réponse. Je l'ai étendu pour permettre à la fois l'orientation paysage et portrait. Il s'agit essentiellement d'un petit code supplémentaire pour permettre de basculer facilement entre le code par défaut qui donne l'orientation paysage et son code pour le portrait.

Insérez son code comme nouvelle méthode dans 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);
            }
        }
    }

Modifiez ensuite JavaCameraView.Java

Ajoutez une nouvelle variable pour suivre si nous sommes en mode portrait ou paysage

private boolean portraitMode;

Ajoutez deux méthodes pour définir le mode d'orientation

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

Remplacez maintenant ces lignes dans la méthode JavaCameraView CameraWorkerClass, run ()

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

Avec ces lignes:

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

Pour basculer entre les orientations, appelez simplement setLandscapeMode () ou setPortraitMode () sur votre objet JavaCameraView.

Veuillez noter que les orientations portrait inversé et paysage inversé seront toujours à l'envers. Vous devrez les faire pivoter de 180 degrés pour les placer dans le bon sens, ce qui se fait facilement avec la méthode warpAffine () d'OpenCV. Notez que lorsque vous utilisez l'appareil photo arrière (LENS_FACING_BACK), le mode portrait renversera les images à l'envers.

0
BW25

Vous devez considérer quelques éléments:

  • onPreviewFrame () fournit toujours les données brutes de la caméra dans sa rotation assambled
  • getSupportedPreviewSizes () donne les proportions correspondantes
  • L'algorithme doit analyser le cadre en mode portrait pour détecter les objets correctement.
  • le bitmap créé (côté Java) pour stocker la trame résultante a également besoin du rapport d'aspect correct

Donc, pour une solution rapide et haute résolution, j'ai changé JavaCameraView.Java et ma partie JNI. dans JavaCameraView.Java:

...

      if (sizes != null) {
         /* Select the size that fits surface considering maximum size allowed */
         Size frameSize;
         if(width > height)
         {
            frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), width, height);
         }else{
            frameSize = calculateCameraFrameSize(sizes, new JavaCameraSizeAccessor(), height, width);
         }
...

         mCamera.setParameters(params);
         params = mCamera.getParameters();

         int bufFrameWidth, bufFrameHeight;
         bufFrameWidth = params.getPreviewSize().width;
         bufFrameHeight = params.getPreviewSize().height;

         if(width > height) {
             mFrameWidth = params.getPreviewSize().width;
             mFrameHeight = params.getPreviewSize().height;
         }else{
             mFrameWidth = params.getPreviewSize().height;
             mFrameHeight = params.getPreviewSize().width;
         }
...

         mFrameChain = new Mat[2];
         mFrameChain[0] = new Mat(bufFrameHeight + (bufFrameHeight/2), bufFrameWidth, CvType.CV_8UC1);
         mFrameChain[1] = new Mat(bufFrameHeight + (bufFrameHeight/2), bufFrameWidth, CvType.CV_8UC1);

         AllocateCache();

         mCameraFrame = new JavaCameraFrame[2];
         mCameraFrame[0] = new JavaCameraFrame(mFrameChain[0], bufFrameWidth, bufFrameHeight);
         mCameraFrame[1] = new JavaCameraFrame(mFrameChain[1], bufFrameWidth, bufFrameHeight);

Avec ces modifications, nous nous sommes assurés d'utiliser la plus haute résultante disponible pour le portrait (commutateurs hauteur/largeur dans CalculateCameraFrameSize). Nous traitons toujours le paysage en entrée de onPreviewFrame () mais avons créé un bitmap pour dessiner en portrait (AllocateCache).

Enfin, nous devons donner à l'algorithme le cadre portrait afin de lui permettre de détecter les objets "debout" et de le retourner pour enregistrer et rendre le bitmap. Donc suite aux modifications de votre activité:

public Mat rot90(Mat matImage, int rotflag){
    //1=CW, 2=CCW, 3=180
    Mat rotated = new Mat();
    if (rotflag == 1){
        rotated = matImage.t();
        flip(rotated, rotated, 1); //transpose+flip(1)=CW
    } else if (rotflag == 2) {
        rotated = matImage.t();
        flip(rotated, rotated,0); //transpose+flip(0)=CCW
    } else if (rotflag ==3){
        flip(matImage, rotated,-1);    //flip(-1)=180
    } else if (rotflag != 0){ //if not 0,1,2,3:
       Log.e(TAG, "Unknown rotation flag("+rotflag+")");
    }
    return rotated;
}

public Mat onCameraFrame(CvCameraViewFrame inputFrame) {

    mRgba = rot90(inputFrame.rgba(), 1);
    mGray = rot90(inputFrame.gray(), 1);
...
0
SKR

La réponse du développeur "jaiprakashgogi" fonctionne pour moi. mais le problème est que l'aperçu est toujours enregistré en tant que paysage. cela signifie que si nous définissons l'aperçu sur imageview, il s'affiche sous forme de paysage.

La solution ci-dessus fonctionne jusqu'à afficher l'aperçu en tant que portrait mais pas enregistré en tant que portrait de manière persistante.

J'ai été résolu ce problème de la manière suivante.

  1. convertir les données d'octet ou de mat en bitmap
  2. faire pivoter la matrice à 90 degrés et appliquer au bitmap
  3. convertir le bitmap en tableau d'octets et l'enregistrer.

veuillez voir mon code ici ...

 public String writeToSDFile(byte[] data, int rotation){


    byte[]  portraitData=null;

   if(rotation==90){
       Log.i(TAG,"Rotation is : "+rotation);
       Bitmap bitmap= BitmapFactory.decodeByteArray(data,0,data.length);
       Matrix matrix = new Matrix();

       matrix.postRotate(90);

       Bitmap rotatedBitmap = Bitmap.createBitmap(bitmap , 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);
   portraitData=bitmapToByte(rotatedBitmap);


   }

    File dir=getDirectory();
    String imageTime=""+System.currentTimeMillis();

    String fileName=Constants.FILE_NAME+imageTime+"."+Constants.IMAGE_FORMAT;
    File file = new File(dir, fileName);

    try {
        FileOutputStream f = new FileOutputStream(file);

        if(rotation==90){
            f.write(portraitData);
        }else {
            f.write(data);
        }

        f.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
        Log.i(TAG, "******* File not found. Did you" +
                " add a WRITE_EXTERNAL_STORAGE permission to the   manifest?");
    } catch (IOException e) {
        e.printStackTrace();
    }
    Log.i(TAG,"\n\nFile written to "+file);

    return fileName;
}

 // convert bitmap to Byte Array

  public byte[] bitmapToByte(Bitmap bitmap){

    ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
  bitmap.compress(Bitmap.CompressFormat.JPEG,100,outputStream);

    byte[] array=outputStream.toByteArray();
   return array;
}

Cela résout complètement mon problème.

0
Kona Suresh

J'ai une orientation portrait avec CameraBridgeViewBase, mais j'ai dû changer JavaCameraView.Java à l'intérieur de OpenCV :( L'idée est la suivante: après le démarrage de la caméra, faites ensuite

setDisplayOrientation(mCamera, 90);
mCamera.setPreviewDisplay(getHolder());

et méthode setDisplayOrientation

protected void setDisplayOrientation(Camera camera, int angle){
    Method downPolymorphic;
    try
    {
        downPolymorphic = camera.getClass().getMethod("setDisplayOrientation", new Class[] { int.class });
        if (downPolymorphic != null)
            downPolymorphic.invoke(camera, new Object[] { angle });
    }
    catch (Exception e1)
    {
    }
}
0
Mary

Comme dans les autres réponses, j'ai écrit ma version personnelle de deliveryAndDrawFrame (j'ai également indiqué par des commentaires où mon code commence et se termine):

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);
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "mStretch value: " + mScale);
            }

            // Start of the fix
            Matrix matrix = new Matrix();
            matrix.preTranslate( ( canvas.getWidth() - mCacheBitmap.getWidth() ) / 2f, ( canvas.getHeight() - mCacheBitmap.getHeight() ) / 2f );
            matrix.postRotate( 90f, ( canvas.getWidth()) / 2f, canvas.getHeight() / 2f );
            float scale = (float) canvas.getWidth() / (float) mCacheBitmap.getHeight();
            matrix.postScale(scale, scale, canvas.getWidth() / 2f , canvas.getHeight() / 2f );
            canvas.drawBitmap( mCacheBitmap, matrix, null );

            // Back to original OpenCV code
            if (mFpsMeter != null) {
                mFpsMeter.measure();
                mFpsMeter.draw(canvas, 20, 30);
            }

            getHolder().unlockCanvasAndPost(canvas);
        }
    }

}

L'aperçu est maintenant en mode Portrait, comme vous pouvez le voir:

Portrait preview

0
Roses