Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rotate camera preview to Portrait Android OpenCV Camera

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.

The problem is that when I change the orientation to portrait, the image comes out sideways.

I understand that I could just rotate the input image before doing image processing (and thus leave the orientation as landscape only), which is fine and works, but doesn't solve the problem that the rest of my UI will be in the wrong orientation.

I have also tried using this code to rotate the camera 90deg, but it just doesn't seem to work.

mCamera.setDisplayOrientation(90); 

It either has no effect, or sometimes just causes the preview to be blacked out

Has anyone done this successfully with OpenCV? My class extends from JavaCameraView. portrait image with sideways preview

Edit

I have made an improvement, which is that I have rotated the image inside of OpenCV as it is displayed in the CameraBridgeViewBase.java class.

In the deliver and draw frame method:

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

... Basically, this just roatates the input image like so

input image rotated 90

This is better, but I obviously want this to be full screen.

like image 777
Jameo Avatar asked Feb 11 '13 16:02

Jameo


People also ask

How do I change camera preview orientation on Android?

To force portrait orientation: set android:screenOrientation="portrait" in your AndroidManifest. xml and call camera. setDisplayOrientation(90); before calling camera.


2 Answers

I had the same problem trying to implement OpenCV. I was able to fix it by making the following changes to the deliverAndDrawFrame method.

  1. Rotate the canvas object

    Canvas canvas = getHolder().lockCanvas(); // Rotate canvas to 90 degrees canvas.rotate(90f, canvas.getWidth()/2, canvas.getHeight()/2); 
  2. Resize the bitmap to fit entire size of canvas before drawing

    // 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); 
like image 131
Kaye Wrobleski Avatar answered Sep 30 '22 11:09

Kaye Wrobleski


I modified the CameraBridgeViewBase.java as follows:

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

And in the function "deliverAndDrawFrame":

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

where rotateMe is defined as follows:

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

The preview FPS is slower because for computational overhead when compared to landscape mode.

like image 22
jaiprakashgogi Avatar answered Sep 30 '22 11:09

jaiprakashgogi