Android studio 3.0配置OpenCV初探

前言

之前一直想對(duì)OpenCV進(jìn)行學(xué)習(xí)和使用,一直沒(méi)有實(shí)踐。這次痛下決心,一定要搞定。經(jīng)過(guò)兩天的折騰,遇到各種bug終于搞定了,希望能幫助到初學(xué)者,如果里面有那些寫的不對(duì)的地方,還希望各位看官指正。

簡(jiǎn)介

  • 準(zhǔn)備條件
  • Android Studio NDK環(huán)境搭建
  • Android Studio OpenCV使用
  • 常見(jiàn)問(wèn)題

準(zhǔn)備條件

NDK環(huán)境搭建

   首先,在Android Studio中打開(kāi)File->setting->Android SDK->SDK Tools
選擇CMake和NDK然后點(diǎn)擊Apply等待下載完成即可。
Android Studio Ndk配置.png
  • 首先

       OpenCV是一個(gè)基于BSD許可(開(kāi)源)發(fā)行的跨平臺(tái)計(jì)算機(jī)視覺(jué)庫(kù),可以
     運(yùn)行在Linux、Windows、Android和Mac OS操作系統(tǒng)上。它輕量級(jí)而且
     高效——由一系列 C 函數(shù)和少量 C++ 類,同時(shí)提供了Python、Ruby、
     MATLAB等語(yǔ)言的接口,實(shí)現(xiàn)了圖像處理和計(jì)算機(jī)視覺(jué)方面的很多通用算法。
     OpenCV用C++語(yǔ)言編寫,它的主要接口也是C++語(yǔ)言,但是依然保留了大量的C語(yǔ)言接口。
     該庫(kù)也有大量的Python、Java and MATLAB/OCTAVE(版本2.5)的接口。
     這些語(yǔ)言的API接口函數(shù)可以通過(guò)在線文檔獲得。如今也提供對(duì)于C#、Ch、Ruby的支持。
    
  • 其次

        在Android Studio中新建Project,選中Include c++ support,之后一直默認(rèn)選擇,
    在C++版本選中c++11,然后finish完成創(chuàng)建,如下圖所示。
    
Android Studio創(chuàng)建工程.png
  • 然后

       導(dǎo)入OpenCV中的Java庫(kù),這個(gè)庫(kù)是OpenCV-android-sdk --->sdk--->java,選擇java之后直接導(dǎo)入。
    之后點(diǎn)擊Android Studio中的Project Structure,或者直接按ctrl+alt+shift+s打開(kāi)庫(kù)依賴面板,
    選擇moudle Dependency,選擇OpenCVLibrary330添加即可,如下圖所示。
    
Android Studio 依賴項(xiàng)目.png
  • 再次

    在AS中打開(kāi)CMakeLists.txt設(shè)置OpenCV的路徑(此路徑為你本地的路徑)
    # ##################### OpenCV 環(huán)境 
    
    #設(shè)置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下面的文件復(fù)制到AS中l(wèi)ibs路徑下。
     然后在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的環(huán)境已經(jīng)配置完了,下面我們來(lái)寫一個(gè)簡(jiǎn)單的DEMO驗(yàn)證一下。

簡(jiǎn)單DEMO驗(yàn)證

注意 :本demo只是簡(jiǎn)單驗(yàn)證,6.0的運(yùn)行時(shí)權(quán)限等等沒(méi)有進(jìn)行配置。

  • 新建MainActivity

    public class MainActivity extends AppCompatActivity implements 
     View.OnClickListener { 
      //最大
       private double max_size = 1024;
      //回調(diào)
       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庫(kù)靜態(tài)加載并初始化
     */
     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);
     }
    
    /**
     * 轉(zhuǎn)換
     */
     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
  • 最終運(yùn)行的效果如下圖所示


    AS效果圖.png

感言

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容