Android Studio开发之路(七)CameraX&&Opencv的使用

一、前情提要以及工作目标

工作目标:做一个显示单通道图像的相机,实现预览和拍照。

原本是调用opencv-android里边的JavaCamera2View来实现,这个用起来比较方便,它提供了集成好的相机预览界面,并且提供了帧处理函数。但是问题是用opencv相机获取到的帧图片分辨率不高,达不到目标效果。

而CameraX作为Google发行的相机处理库,可以方便的做分辨率设置、对焦等操作,于是决定使用Camerax+opencv的方式完成工作目标。

二、CameraX基础

CameraX
Camerax(Android developer)
Camerax发布会(谷歌中国)
Camerax入门指南

三、工作几大难点以及解决方案

(1). 开发语言与版本

CameraX主流语言是Kotlin, 网上帖子用的也大多是Kotlin,而我使用的是Java

并且Camerax目前为止发行了不少的版本,还分了alpha,beta版本,不同的版本代码页不完全兼容。Java开发尽可能选择比较新的版本
Android CameraX 1.1.0 Java版本使用教程(Java)

(2). ImageProxy对象转Mat

CameraX将相机应用的主流场景分成三个"用例",每个用例都可以单独使用:
预览:将相机捕获的画面显示在屏幕上,PreviewView
拍照:拍摄保存图片
分析ImageAnalysis:提供每一帧图像用于处理。

分析用例提供的是 ImageProxy对象,帧图片是YUV类型,但是opencv处理的是Mat,所以需要进行转换,可参考这篇文章:
YUV转Mat

(3).图片处理后的再显示

我需要将每一帧处理后的图像想普通相机那样再显示在界面上,但是CameraX的分析用例没有提供返回,而且要将mat再转回也比较麻烦,所以普遍的方式是在预览界面的上面再叠放一个ImageView,每处理一帧就用ImageView显示出来。(根据我的目标,我只要显示处理之后的帧,所以我干脆没有使用预览用例)。

这里还要注意显示的大小。我的ImageAnalysis分辨率设置的是1280x720, 显示出来是不能占满屏幕的,那么就有两种处理方式:

1.使用ImageView的缩放设置setScaleType

ScaleType缩放设置

2.使用opencv的resize()函数

CameraX的预览用例官方文档中给出了预览时的缩放规则,我仿照这个规则使用resize函数将负片进行缩放,并且ImageView缩放类型设置为Center
CameraX预览用例

cpp 复制代码
    private class MyAnalyzer implements ImageAnalysis.Analyzer {
        @SuppressLint("UnsafeOptInUsageError")
        @Override
        public void analyze(@NonNull ImageProxy image) {
            Log.d(TAG, "Image's stamp is " + Objects.requireNonNull(image.getImage()).getTimestamp());
            Image img = image.getImage();

            int rotation = image.getImageInfo().getRotationDegrees();

            //在opencv的JavaCamera2View.java中添加了ImageUtil类,用于YUV类型到mat的图片转换
            ImageUtil imgutil = new ImageUtil(img);
            Mat rgb = imgutil.rgba();
            imgutil.rotation(rotation, rgb);    //图片旋转

            mChannelB = new Mat(rgb.height(), rgb.width(), CvType.CV_8UC1);
            //clahe 用于进行图像边缘增强对比度
            CLAHE clahe = createCLAHE();
            clahe.setClipLimit(8);
            clahe.setTilesGridSize(new Size(8, 8));
            //通道拆分,仅显示单通道图像
            List<Mat> imgList = new ArrayList<Mat>();
            Core.split(rgb, imgList);
            clahe.apply(imgList.get(2), mChannelB);

            //获取屏幕尺寸
            DisplayMetrics displayMetrics = getResources().getDisplayMetrics();
            int width = displayMetrics.widthPixels;
            int height = displayMetrics.heightPixels;
            double mu=Math.max(mlay.getWidth()*1.0/mChannelB.width(),mlay.getHeight()*1.0/mChannelB.height());

            Mat reRgb=new Mat();
            resize(mChannelB,reRgb,new Size(0,0),mu,mu,INTER_CUBIC);

            Bitmap bitmap = Bitmap.createBitmap(reRgb.width(), reRgb.height(), Bitmap.Config.ARGB_8888);
            Utils.matToBitmap(reRgb,bitmap);

            //TODO 处理我们要对Mat做的业务计算
            imgutil.release(); //要释放资源哦


            //  Toast.makeText(MainActivity.this,"mChannelB size:"+mChannelB.width()+";"+mChannelB.height(),Toast.LENGTH_SHORT).show();
         /*   String path= Environment.getExternalStorageDirectory()+"/DCIM/Camera/";
            //将拍摄准确时间作为文件名
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd_HH-mm-ss");
            String filename = sdf.format(new Date());
            String filePath= path  + filename + ".jpg";
            Imgcodecs.imwrite(filePath, mChannelB);
*/

            image.close();
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    m_imageView.setImageBitmap(bitmap);
                    String size=mlay.getWidth()+"/"+mlay.getHeight()+";"+bitmap.getWidth()+"/"+bitmap.getHeight()+";"+m_imageView.getWidth()+"/"+m_imageView.getHeight()+";"+reRgb.width()+"/"+reRgb.height()+";mu:"+mu;
                    m_textView.setText(size);
                    //  Toast.makeText(MainActivity.this,"imageview size:"+m_imageView.getWidth()+";"+m_imageView.getHeight(),Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
相关推荐
华清远见IT开放实验室24 分钟前
【每天学点AI】实战图像增强技术在人工智能图像处理中的应用
图像处理·人工智能·python·opencv·计算机视觉
只怕自己不够好38 分钟前
《OpenCV 图像缩放、翻转与变换全攻略:从基础操作到高级应用实战》
人工智能·opencv·计算机视觉
Dnelic-1 小时前
【单元测试】【Android】JUnit 4 和 JUnit 5 的差异记录
android·junit·单元测试·android studio·自学笔记
Eastsea.Chen3 小时前
MTK Android12 user版本MtkLogger
android·framework
安静读书6 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小陈phd7 小时前
OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算
人工智能·opencv·计算机视觉
长亭外的少年10 小时前
Kotlin 编译失败问题及解决方案:从守护进程到 Gradle 配置
android·开发语言·kotlin
如若12311 小时前
主要用于图像的颜色提取、替换以及区域修改
人工智能·opencv·计算机视觉
建群新人小猿13 小时前
会员等级经验问题
android·开发语言·前端·javascript·php
1024小神14 小时前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri