Android从零开始配置opencv+tensorflow进行人脸识别+口罩识别(二:opencv展示当前图像并作适当调整)

前言

上一章已经成功导入了opencv,但并没说如何展示从摄像头获取图像并展示出来,这章将简单的说说怎么展示,以及里面出现的问题作修正

一、使用opencv正常展示图像

首先准备一个空的activity页面,在其xml布局中添加JavaCameraView,这个view宽高都可以,不过,我为了在这个view下面添加功能按钮,所以给了高度限制
示例代码

  <org.opencv.android.JavaCameraView
            android:id="@+id/cameraView"
            android:layout_width="@dimen/dp_300"
            android:layout_height="@dimen/dp_250"
            android:layout_gravity="center" 
            />

添加后,在activity中对其生命周期作一下简单的绑定,我个人是写在onResume,onPause和onDestroy三个生命周期中去了
示例代码

onResume中的代码

 override fun onResume() {
        super.onResume()
        {你自己的的JavaCameraView的名字}.connectCamera(width, height)
    }

onResume中的代码

 override fun onResume() {
        super.onResume()
    	//这里的width和height是view的宽高,方便去获取一个最佳的展示的分辨率,毕竟你不想在一个小格子里展示4k图,也不想在一个大格子里展示160x120分辨率的图 by yinjun
        {你自己的的JavaCameraView的名字}.connectCamera(width, height)
    }

onPause中的代码

 override fun onPause() {
        super.onPause()
        //临时关闭camera,别锁屏还一直录,小心烧了你那4k摄像头 by yinjun
        {你自己的的JavaCameraView的名字}.cameraView.releaseCamera()
    }

onDestroy中的代码

 override fun onDestroy() {
        super.onDestroy()
        //直接释放摄像头,页面都没了,还要摄像头干嘛?by yinjun
        {你自己的的JavaCameraView的名字}.cameraView.disableView()
    }

做完上面的操作,运行到手机上,你的opencv就可以正常展示第一个图像。。。等等,似乎有一点点不对劲?
![请添加图片描述](https://img-blog.csdnimg.cn/a472609ad9e74433aa8b3df51d640aef.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAd2VpeGluXzQ3NDkxNjY4,size_20,color_FFFFFF,t_70,g_se,x_16请添加图片描述
这个东西,为啥是歪着的?看来得作一些小小的调优

二、opencv抓取画面调优

1.错误的角度调整

首先,是吧图片给转过来,让其可以正常展示图片,JavaCameraView中有一个监听方法setCvCameraViewListener,这个监听器除了能监听当前摄像头是开启还是关闭以外,它的onCameraFrame方法所返回的mat就是javaCameraView中展示的东西,吧这个mat旋转,展示正确的图像,需要注意的地方都写注释里了

代码如下(示例):

	cameraView.setCvCameraViewListener(object : CameraBridgeViewBase.CvCameraViewListener2 {
            override fun onCameraViewStarted(width: Int, height: Int) {
                Log.e("hehe", "开始")
            }

            override fun onCameraViewStopped() {
                Log.e("hehe", "结束")
            }

            override fun onCameraFrame(inputFrame: CameraBridgeViewBase.CvCameraViewFrame?): Mat {
                var result: Mat? = null
     			//因为里面要干的事情有点多,这个回调又相当于子线程干完活要回主线程作展示,所以这里最好加个锁 by yinjun
                synchronized(this) {
                    if (result != null) {
                        //先把图片摆正
                        var angle = 90
                        //这里注意一下,如果直接旋转90度,不做其他处理会导致调用前摄像头时直接上下翻转,所以要根据当前是不是前摄像头来改旋转值by yinjun
                        if (cameraView.getmCameraIndex() == CameraBridgeViewBase.CAMERA_ID_FRONT) {
                            angle = 270
                        }
                        //记得,吧你那图像的宽高一起改一下,不改?等着看扁扁图吧 by yinjun
                        var size = Size(result.width().toDouble(), result.height().toDouble())
                        Imgproc.warpAffine(result, result, Imgproc.getRotationMatrix2D(Point((result.width() / 2).toDouble(), (result.height() / 2).toDouble()), angle.toDouble(), -1.0), size)
                    }
                }

				//这个返回的mat就是你要用来展示的图像,你可用对其作其他更改,比如变灰,加框什么的操作之后再返回,但这就是后话了
                return result!!

            }

        })

写到这里,肯定有人稍微有些蒙蔽,我的javaCameraView里没有getmCameraIndex啊,因为这个参在opencv哪里是一个私有的参,你需要自己去手写一个方法调取,写的也很简单,直接在javaCameraView中添加一个方法就可以了

 public int getmCameraIndex(){
        return mCameraIndex;
    }

2.如何旋转摄像头

上面的注释里写了需要吧前摄转270°,可是opencv里似乎没有直接转摄像头的方法,怎么办?自己来办,直接准备一个按钮,为其配置以下点击事件

{你的按钮的名字}.setOnClickListener {
			//现在是前摄,切回后摄,现在是后摄,切回前摄 by yinjun
            if (cameraView.getmCameraIndex() == CameraBridgeViewBase.CAMERA_ID_FRONT) {
                cameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_BACK)
            } else {
                cameraView.setCameraIndex(CameraBridgeViewBase.CAMERA_ID_FRONT)
            }
            //设定完新的摄像头下标后,就可用停用,然后重启摄像头了 by yinjun
            cameraView.releaseCamera();
            cameraView.connectCamera(width, height)
        }

结尾

上述操作完成后,你就可以正常使用opencv展示摄像头出现的图像了,并且自由切换前后摄像头了,opencv的mat的宽高是通过connectCamera(width, height)中传入的宽高,在你摄像头支持分辨率中找到一个最佳的分辨率,所以不需要担心我这8k摄像头的手机,会不会一直拿8k图像,读爆我的内存之类的,不会,至此,opencv部分的操作基本上就大功告成了,后面会说如何接入tensorflow以及如何用tensorflow-lite作人脸识别和口罩识别并展示出是否佩戴口罩

ps:本来早就准备好一起上,但opencv对人连带口罩时的读取识别度太低了,dlib表现不错,但dlib性能问题堪忧,而且还因为用的一个模型比较大,用在移动端上有点内存杀手的意思,所以选内存占用更小的tensorflow-lite,但tensorflowlite的人脸识别的模型构建我还没看,估计要一段时间了,可能会先出一个opencv读取人脸的教程混混?

  • 13
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值