Android studio 3.0配置OpenCV初探

前言

之前一直想对OpenCV进行学习和使用,一直没有实践。这次痛下决心,一定要搞定。经过两天的折腾,遇到各种bug终于搞定了,希望能帮助到初学者,如果里面有那些写的不对的地方,还希望各位看官指正。

简介

  • 准备条件
  • Android Studio NDK环境搭建
  • Android Studio OpenCV使用
  • 常见问题

准备条件

NDK环境搭建

   首先,在Android Studio中打开File->setting->Android SDK->SDK Tools
选择CMake和NDK然后点击Apply等待下载完成即可。
Android Studio Ndk配置.png
  • 首先

       OpenCV是一个基于BSD许可(开源)发行的跨平台计算机视觉库,可以
     运行在Linux、Windows、Android和Mac OS操作系统上。它轻量级而且
     高效——由一系列 C 函数和少量 C++ 类,同时提供了Python、Ruby、
     MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。
     OpenCV用C++语言编写,它的主要接口也是C++语言,但是依然保留了大量的C语言接口。
     该库也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。
     这些语言的API接口函数可以通过在线文档获得。如今也提供对于C#、Ch、Ruby的支持。
    
  • 其次

        在Android Studio中新建Project,选中Include c++ support,之后一直默认选择,
    在C++版本选中c++11,然后finish完成创建,如下图所示。
    
Android Studio创建工程.png
  • 然后

       导入OpenCV中的Java库,这个库是OpenCV-android-sdk --->sdk--->java,选择java之后直接导入。
    之后点击Android Studio中的Project Structure,或者直接按ctrl+alt+shift+s打开库依赖面板,
    选择moudle Dependency,选择OpenCVLibrary330添加即可,如下图所示。
    
Android Studio 依赖项目.png
  • 再次

    在AS中打开CMakeLists.txt设置OpenCV的路径(此路径为你本地的路径)
    # ##################### OpenCV 环境 
    
    #设置OpenCV-android-sdk路径
    set( OpenCV_DIR E:/Source/OpenCV-android-sdk/sdk/native/jni )
    
    find_package(OpenCV REQUIRED )
    if(OpenCV_FOUND)
    include_directories(${OpenCV_INCLUDE_DIRS})
    message(STATUS "OpenCV library status:")
    message(STATUS "    version: ${OpenCV_VERSION}")
    message(STATUS "    libraries: ${OpenCV_LIBS}")
    message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
    else(OpenCV_FOUND)
    message(FATAL_ERROR "OpenCV library not found")
    endif(OpenCV_FOUND)
    

注意: 上面的set( OpenCV_DIR E:/Source/OpenCV-android-sdk/sdk/native/jni)把此路径换成你本地的路径。

  • 最后

        将OpenCV-android-sdk下面的sdk-->native-->libs下面的文件复制到AS中libs路径下。
     然后在app 的build.gradle的android下添加如下代码:
    
      task nativeLibsToJar(type: Jar, description: 'create a jar archive of the native libs') {
         destinationDir file("$buildDir/native-libs")
         baseName 'native-libs'
         from fileTree(dir: 'libs', include: '**/*.so')
         into 'lib/'
     }
    
     tasks.withType(JavaCompile) {
         compileTask -> compileTask.dependsOn(nativeLibsToJar)
     }
    
      最后还需要在dependencies添加 
     implementation fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')
    

提示 :到这里OpenCV的环境已经配置完了,下面我们来写一个简单的DEMO验证一下。

简单DEMO验证

注意 :本demo只是简单验证,6.0的运行时权限等等没有进行配置。

  • 新建MainActivity

    public class MainActivity extends AppCompatActivity implements 
     View.OnClickListener { 
      //最大
       private double max_size = 1024;
      //回调
       private int PICK_IMAGE_REQUEST = 1;
      //原图、处理后的图片
       private ImageView mImgOriginal, mImgDeals;
      //原始Bitmap、处理后的Bitmap
      private Bitmap mOriginalBitmap,mDealBitmap;
     //选择图片、处理
      private Button mBtnChoose, mBtnDeals;
      @Override
     protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_main);
      onLoadOpenCVLibrary();
      initView();
     }
    
    /**
     * 初始化
     */
     private void initView() {
    mImgDeals = findViewById(R.id.img_deals);
    mImgOriginal = findViewById(R.id.img_original);
    mBtnChoose = findViewById(R.id.btn_choose);
    mBtnDeals = findViewById(R.id.btn_deals);
    
    mBtnDeals.setOnClickListener(this);
    mBtnChoose.setOnClickListener(this);
    
     }
    
    
     @Override
    public void onClick(View view) {
    switch (view.getId()) {
        case R.id.btn_choose: {//选择
            selectImage();
            break;
        }
        case R.id.btn_deals: {//处理
            convertGray();
            break;
        }
    }
    }
    
      @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null
            && data.getData() != null) {
        Uri uri = data.getData();
        try {
            Log.e("image-tag", "start to decode selected image now...");
            InputStream input = getContentResolver().openInputStream(uri);
            BitmapFactory.Options options = new BitmapFactory.Options();
            options.inJustDecodeBounds = true;
            BitmapFactory.decodeStream(input, null, options);
            int raw_width = options.outWidth;
            int raw_height = options.outHeight;
            int max = Math.max(raw_width, raw_height);
            int newWidth = raw_width;
            int newHeight = raw_height;
            int inSampleSize = 1;
            if (max > max_size) {
                newWidth = raw_width / 2;
                newHeight = raw_height / 2;
                while ((newWidth / inSampleSize) > max_size || (newHeight / inSampleSize) > max_size) {
                    inSampleSize *= 2;
                }
            }
    
            options.inSampleSize = inSampleSize;
            options.inJustDecodeBounds = false;
            options.inPreferredConfig = Bitmap.Config.ARGB_8888;
            mOriginalBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri),
                    null, options);
            mDealBitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri),
                    null, options);
            mImgOriginal.setImageBitmap(mOriginalBitmap);
    
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    
    }
    
    /**
     * OpenCV库静态加载并初始化
     */
     private void onLoadOpenCVLibrary() {
      boolean load = OpenCVLoader.initDebug();
      if (load) {
        Log.e("CV", "Open CV Libraries loaded...");
       }
     }
    
     /**
      * 选择图片
      */
    private void selectImage() {
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "选择图像"), PICK_IMAGE_REQUEST);
     }
    
    /**
     * 转换
     */
     private void convertGray(){
    Mat src = new Mat();
    Mat temp = new Mat();
    Mat dst = new Mat();
    Utils.bitmapToMat(mDealBitmap, src);
    Imgproc.cvtColor(src, temp, Imgproc.COLOR_BGRA2BGR);
    Imgproc.cvtColor(temp, dst, Imgproc.COLOR_BGR2GRAY);
    Utils.matToBitmap(dst, mDealBitmap);
    mImgDeals.setImageBitmap(mDealBitmap);
     }
     }
    
  • 新建资源文件

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">
    
    <LinearLayout
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:orientation="horizontal">
    
      <Button
          android:id="@+id/btn_choose"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_margin="10dp"
          android:text="@string/btn_choose"
          android:textSize="16sp" />
    
      <Button
          android:id="@+id/btn_deals"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:layout_margin="10dp"
          android:text="@string/btn_deals"
          android:textSize="16sp" />
    
    </LinearLayout>
    
    <ImageView
      android:id="@+id/img_original"
      android:layout_width="200dp"
      android:layout_height="200dp"
      android:layout_gravity="center"
      android:layout_margin="16dp"
      android:scaleType="fitCenter"
      android:src="@mipmap/ic_launcher" />
    
    <ImageView
      android:id="@+id/img_deals"
      android:layout_width="200dp"
      android:layout_height="200dp"
      android:layout_gravity="center"
      android:layout_margin="16dp"
      android:scaleType="fitCenter"
      android:src="@mipmap/ic_launcher" />
    </LinearLayout>
    
  • 资源文件的效果如下图所示


    AS资源文件.png
  • 最终运行的效果如下图所示


    AS效果图.png

感言

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容