Skip to content

Instantly share code, notes, and snippets.

@heaversm
Last active March 29, 2024 18:30
Show Gist options
  • Save heaversm/63e8036af6a124aecf3b26898bd2a0ad to your computer and use it in GitHub Desktop.
Save heaversm/63e8036af6a124aecf3b26898bd2a0ad to your computer and use it in GitHub Desktop.
Renders openCV's camera in portrait mode on android - to be placed in `CameraBridgeViewBase.java`
private final Matrix mMatrix = new Matrix();
private void updateMatrix() {
float mw = this.getWidth();
float mh = this.getHeight();
float hw = this.getWidth() / 2.0f;
float hh = this.getHeight() / 2.0f;
float cw = (float)Resources.getSystem().getDisplayMetrics().widthPixels; //Make sure to import Resources package
float ch = (float)Resources.getSystem().getDisplayMetrics().heightPixels;
float scale = cw / (float)mh;
float scale2 = ch / (float)mw;
if(scale2 > scale){
scale = scale2;
}
boolean isFrontCamera = mCameraIndex == CAMERA_ID_FRONT;
mMatrix.reset();
if (isFrontCamera) {
mMatrix.preScale(-1, 1, hw, hh); //MH - this will mirror the camera
}
mMatrix.preTranslate(hw, hh);
if (isFrontCamera){
mMatrix.preRotate(270);
} else {
mMatrix.preRotate(90);
}
mMatrix.preTranslate(-hw, -hh);
mMatrix.preScale(scale,scale,hw,hh);
}
@Override
public void layout(int l, int t, int r, int b) {
super.layout(l, t, r, b);
updateMatrix();
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
updateMatrix();
}
/**
* This method shall be called by the subclasses when they have valid
* object and want it to be delivered to external client (via callback) and
* then displayed on the screen.
* @param frame - the current frame to be delivered
*/
protected void deliverAndDrawFrame(CvCameraViewFrame frame) { //replaces existing deliverAndDrawFrame
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 saveCount = canvas.save();
canvas.setMatrix(mMatrix);
if (mScale != 0) {
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, new Rect(0,0,mCacheBitmap.getWidth(), mCacheBitmap.getHeight()),
new Rect((canvas.getWidth() - mCacheBitmap.getWidth()) / 2,
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2,
(canvas.getWidth() - mCacheBitmap.getWidth()) / 2 + mCacheBitmap.getWidth(),
(canvas.getHeight() - mCacheBitmap.getHeight()) / 2 + mCacheBitmap.getHeight()), null);
}
//Restore canvas after draw bitmap
canvas.restoreToCount(saveCount);
if (mFpsMeter != null) {
mFpsMeter.measure();
mFpsMeter.draw(canvas, 20, 30);
}
getHolder().unlockCanvasAndPost(canvas);
}
}
}
@sontqq
Copy link

sontqq commented Aug 7, 2019

Works fine. Thank you!

@topherbuckley
Copy link

@heaversm Have you submitted a pull request for any of this in the opencv repo? It would be nice to have this functionality built in rather than directly modifying their library files.

@topherbuckley
Copy link

Also, it appears there is some ambiguity to the Matrix package. android.graphics and android.opengl both have a Matrix class. It appears the reset() and preScae() methods are from android.graphics.Matrix. Maybe include a comment on this? Side note: is there any reason you can't use the native Mat type in openCV?

@homandiy
Copy link

homandiy commented Apr 7, 2020

It works! Let's clap for Mike. Here is my record: https://www.linkedin.com/pulse/android-opencv-349-part-2-cameraview-homan-huang/?published=t
I have 17fps.

@oppicool
Copy link

thanks a lot!

@winterwindwang
Copy link

thank a lot!

@kishandonga
Copy link

thanks it's working

@SpookyMask
Copy link

Thank you! I just can't translate a point backward from the screen to the mat, any idea how to do that?

@jusjinuk
Copy link

thx! Helped a lot.

@MohammadAzimi
Copy link

awsome!

@koai-dev
Copy link

Thank you very much! <3 <3 <3

@emirsahin1
Copy link

You are an absolute legend for fixing this. Thank you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment