Last active
March 29, 2024 18:30
-
-
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`
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | |
} | |
} | |
} |
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?
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.
thanks a lot!
thank a lot!
thanks it's working
Thank you! I just can't translate a point backward from the screen to the mat, any idea how to do that?
thx! Helped a lot.
awsome!
Thank you very much! <3 <3 <3
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
@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.