openCv CameraBridgeViewBase 竖屏显示对应的修改
16lz
2021-01-26
为了处理手机摄像头的图像,试图用openCv解决问题。尝试了openCv的demo,都是横屏显示,在手机上使用并不方便。
经过一些尝试,对org.opencv.android(v4.1.0)做了少量修改,实现了竖屏显示。
- Manifest
毫无疑问,为了实现竖屏显示,必须设置屏幕方向
android:screenOrientation="portrait"
- CameraBridgeViewBase.CvCameraViewListener2
这是必须在应用程序中实现的接口,包括三个监听器。
private var rgbaMat: Mat? = nulloverride fun onCameraViewStarted(width: Int, height: Int) { rgbaMat = Mat(width, height, CvType.CV_8UC4) } override fun onCameraViewStopped() { rgbaMat?.release() } override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame?): Mat? { rgbaMat = inputFrame?.rgba() Core.rotate(rgbaMat, rgbaMat, Core.ROTATE_90_CLOCKWISE) return rgbaMat }
监听器用kotlin实现,在onCameraFrame取得相机帧数据后,顺时针旋转90°,返回到屏幕上。此时预览图像与竖屏一致,但不是全屏。
- CameraBridgeViewBase
看来仅仅在自家APP上动手脚,不能完全解决问题,只好对SDK源代码下手。
// NOTE: On Android 4.1.x the function must be called before SurfaceTexture constructor! protected void AllocateCache() {// mCacheBitmap = Bitmap.createBitmap(mFrameWidth, mFrameHeight, Bitmap.Config.ARGB_8888); mCacheBitmap = Bitmap.createBitmap(mFrameHeight, mFrameWidth, Bitmap.Config.ARGB_8888); }
protected Size calculateCameraFrameSize(List<?> supportedSizes, ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) { int calcWidth = 0; int calcHeight = 0; int maxAllowedWidth = (mMaxWidth != MAX_UNSPECIFIED && mMaxWidth < surfaceWidth)? mMaxWidth : surfaceWidth; int maxAllowedHeight = (mMaxHeight != MAX_UNSPECIFIED && mMaxHeight < surfaceHeight)? mMaxHeight : surfaceHeight; for (Object size : supportedSizes) { int width = accessor.getWidth(size); int height = accessor.getHeight(size);// if (width <= maxAllowedWidth && height <= maxAllowedHeight) { if (height <= maxAllowedWidth && width <= maxAllowedHeight) { if (width >= calcWidth && height >= calcHeight) { calcWidth = (int) width; calcHeight = (int) height; } } } return new Size(calcWidth, calcHeight); }
修改处已经标出,但仍然得不到全屏显示。
4. JavaCameraView
原来这里也需要修改。
protected boolean initializeCamera(int width, int height) { ...//mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth); mScale = Math.min(((float)width)/mFrameHeight, ((float)height)/mFrameWidth); ... }
至此,以org.opencv.android.JavaCameraView为基类的视频View可以得到全竖屏显示。
5. JavaCamera2View
对于以org.opencv.android.JavaCamera2View为基类的View来说,修改有所不同。
@Override protected boolean connectCamera(int width, int height) { ... if ((getLayoutParams().width == LayoutParams.MATCH_PARENT) && (getLayoutParams().height == LayoutParams.MATCH_PARENT))// mScale = Math.min(((float)height)/mFrameHeight, ((float)width)/mFrameWidth); mScale = Math.min(((float)width)/mFrameHeight, ((float)height)/mFrameWidth); else mScale = 0; ... {
如果不修改这里,图像会显示怪异的颜色。
private class JavaCamera2Frame implements CvCameraViewFrame { ... @Override public Mat rgba() { ... else if (mPreviewFormat == ImageFormat.YUV_420_888) { assert (mUVFrameData != null);// Imgproc.cvtColorTwoPlane(mYuvFrameData, mUVFrameData, mRgba, Imgproc.COLOR_YUV2RGBA_NV21); Imgproc.cvtColorTwoPlane(mYuvFrameData, mUVFrameData, mRgba, Imgproc.COLOR_YUV2BGRA_NV21);... {
经过上述修改,虽然能够实现竖屏的全屏显示,但是由于图像数据90°旋转处理的资源占用较多,使得预览帧率下降严重,视频有迟滞现象,最终没有采用这个方案。
更多相关文章
- android 实现GridView多选效果
- Android中Gallery显示手机中的图片
- 一起学android之自定义控件一起制作自定义标签(39)
- DiscreteSeekBar使用简介,一个带气泡的SeekBar
- Android(安卓)DatePickerDialog 只显示年月
- android drawText/drawLines不显示的原因
- 【Orientation】详解Android中的屏幕方向
- 如何获取Android系统时间是24小时制还是12小时制
- Android(安卓)ListView中动态显示和隐藏Header&Footer的方法