zoukankan      html  css  js  c++  java
  • opencv-android笔记1:android studio 2.3 + opencv-android-sdk 实现 camera预览

    Android studio环境配置不再赘述,可以参照我的其他博客。 
    Android应用程序开发环境搭建:http://blog.csdn.net/ja33son/article/details/61192072

    Opencv-android-sdk:链接:http://pan.baidu.com/s/1boI67nh 密码:umu2

    新建项目后,File-New-Import Module,选择解压后sdk中android项目的路径:opencv-3.2.0-android-sdkOpenCV-android-sdksdkjava,引入module!

    引入Module

    出现错误了不要紧,先不去管它,切换到project界面下,打开app的build.gradle文件,以及引入的module的build.gradle文件。将app中build.gradle的部分字段复制到module中,字段包括compileSdkVersion、buildToolsVersion、minSdkVersion、targetSdkVersion,复制到对应位置,目的是为了使两个module的编译环境相同。不这么做,就报错给你看。

    同步编译环境

    不要忘记,改变build.gradle以后,Sync你的工程。Sync工程

    Sync工程

    下一步是很关键的,将解压后的库文件(opencv-3.2.0-android-sdkOpenCV-android-sdksdk ative下的libs文件夹)添加到项目目录(app/src/main/)中。要将目录名字改为jniLibs。 
    注:我们使用到的库,只有每个平台文件夹(arm64-v8a、armeabi、armeabi-v7a、mips、mips64、x86、x86_64)下的libopencv_java3.so,感兴趣的同学可以将其他库移除,会有效减小apk体积。也可以使用Lint Cleaner Plugin或者AndroidStudio自带的瘦身工具,这里不做演示。

    jniLibs构建

    之后,将引入的module作为外部库项目导入到app中,开发环境就搭建好了。 
    注:Project Structure的快捷键是Ctrl+Shift+Alt+s

    导入module

    环境搭建完成后,就可以做一些简单的工作了。以下是获取opencv camera图像数据,并对图像进行简单处理的demo。


    首先是Manifest.xml配置文件,声明一下相机的权限。由于Android M以后,权限机制改变,只声明已经失效了,需要在activity中申请,后面会详细说明。

    添加以下权限: 
    <uses-permission android:name="android.permission.CAMERA" />

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.ja3son.cvcamera">
    
        <uses-permission android:name="android.permission.CAMERA" />
    
        <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:roundIcon="@mipmap/ic_launcher_round"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
            <activity android:name=".MainActivity">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    
    </manifest>

    然后是布局文件:

    <?xml version="1.0" encoding="utf-8"?>
    <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:opencv="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    
        <org.opencv.android.JavaCameraView
            android:id="@+id/camera_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            opencv:show_fps="true" />
    
    </FrameLayout>

    在引入org.opencv.android.JavaCameraView的时候,preview窗口可能会报错,只需要在preview窗口提示的信息中,点击一下build,就可以解决了。 
    注:以上解决方法在Android Studio2.3中适用,其他版本中没有进行测试,即使现在不build,最后运行项目的时候也会build的。以上方法只提供给强迫症患者

    JavaCameraView就是提供相机预览的类了,但让人失望的是,JavaCameraView没有调用Camera API2接口,而是使用老版本Camera API1。后续会做opencv接入Camera API2的东西,感兴趣的同学可以持续关注。


    之后就是Activity文件:

    import android.Manifest;
    import android.os.Build;
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    
    import org.opencv.android.CameraBridgeViewBase;
    import org.opencv.android.JavaCameraView;
    import org.opencv.android.OpenCVLoader;
    import org.opencv.core.Mat;
    
    public class MainActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
    
        private JavaCameraView camera_view;
        private int M_REQUEST_CODE = 203;
        private String[] permissions = {Manifest.permission.CAMERA};
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            camera_view = (JavaCameraView) findViewById(R.id.camera_view);
            camera_view.setCvCameraViewListener(this);
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                requestPermissions(permissions, M_REQUEST_CODE);
            }
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            if (camera_view != null) {
                camera_view.disableView();
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            if (OpenCVLoader.initDebug()) {
                camera_view.enableView();
            }
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            if (camera_view != null) {
                camera_view.disableView();
            }
        }
    
        @Override
        public void onCameraViewStarted(int width, int height) {
        }
    
        @Override
        public void onCameraViewStopped() {
        }
    
        @Override
        public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
            return inputFrame.rgba();
        }
    }

    简单解释一下activity中进行的操作:

    activity实现CameraBridgeViewBase.CvCameraViewListener2接口,实现对camera数据的监听和控制。

    onCreate方法中初始化View,申请权限,设置监听。camera_view.setCvCameraViewListener(this)设置监听后,重写方法就可以获得camera预览数据了。直接调用requestPermissions方法,就会在程序初始化时弹出系统预制的权限申请对话框,在Android N中是如此,其他版本中未验证。由于此代码只是demo,且本人懒,所以没做权限拒绝申请相关的处理,感兴趣的同学可以实现onRequestPermissionsResult方法进行控制。

    onResume方法中初始化opencv库,初始化成功,则进行camera_view.enableView()操作,使view开始预览。如果全部按照前面步骤操作,就不存在初始化库失败的情况。如果存在,请参考前文,重新来过。

    onCameraFrame方法中只是返回了原始图像,return inputFrame.rgba()。这时运行程序,就能在屏幕上看到相机的图像了。只不过图像是横着的,因为我懒,没旋转。以下代码是对图像进行简单图像处理的代码,将

        @Override
        public void onCameraViewStarted(int width, int height) {
        }
    
        @Override
        public void onCameraViewStopped() {
        }
    
        @Override
        public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
            return inputFrame.rgba();
        }

    全部替换为:

        private Mat mCannyResult;
    
        @Override
        public void onCameraViewStarted(int width, int height) {
            mCannyResult = new Mat(height, width, CvType.CV_8UC1);
        }
    
        @Override
        public void onCameraViewStopped() {
            mCannyResult.release();
        }
    
        @Override
        public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
            Imgproc.Canny(inputFrame.gray(), mCannyResult, 60, 80);
            return mCannyResult;
        }

    结果图就是

    结果图

    对图像的处理可以简单说明一下: 
    在StartCamera的时候,初始化一个Mat,这个Mat是8位无符号整形单通道矩阵(CvType.CV_8UC1),为什么是单通道呢?都知道RGB是三个通道,每个颜色一个,RGBA是四通道,多出一个Alpha透明度通道。灰度图,不需要颜色通道,所以一个通道就够了。因为我们只需要取灰度数据就足够检测边缘了,没错,我们对图像简单的处理就是Canny检测边缘。 
    有了Mat以后,在onCameraFrame方法中,调用Imgproc.Canny(inputFrame.gray(), mCannyResult, 60, 80)方法,简单说一下参数,第一个为原始数据,就是camera预览的灰度图。第二个是输出图像,就是Canny以后的数据。后两个double类型的参数,就是边缘检测的阈值边界。以例子为准的话,低于60的点不算作边缘。在60与80之间的点,参考周围点,如果周围有边界点,则记为边缘点。高于80的点,为边缘点。

    以上就是opencv的入门demo了,结合这个就可以做很多有意思的东西了。后续会做android studio 结合NDK开发opencv的例子,敬请关注。

  • 相关阅读:
    update语句更新多条记录, 标记下
    点击超链接从VSTF、SVN及文件共享服务器上下载文件
    批量插入数据, 将DataTable里的数据批量写入数据库的方法
    SqlServer规范, 标记下
    学习笔记Mysql操作总结
    今拾到了个联合查询, 琢磨了好几个小时, 标记一下
    【读书笔记】 拜读潘加宇的《软件方法》一书的摘抄(上)
    关于引用类型的 ref 传参操作
    sed 正则表达式处理日志
    各省市个税计算器
  • 原文地址:https://www.cnblogs.com/huaxingtianxia/p/8516863.html
Copyright © 2011-2022 走看看