前言
之前一直想對(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)備條件
- openCV壓縮包下載密碼【7xkh】
- Android Studio
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
感言
- 經(jīng)過(guò)兩天的折騰,遇到了各種Bug,終于搞定的,除了這種方式添加OpenCV之外還有添加.mk文件的方式等等。這里就不多做介紹了,想了解的看官可以去自行搜索。
- 感謝gloomyfish的OpenCV On Android開(kāi)發(fā) - Android Studio上環(huán)境配置
- github目錄
- 個(gè)人博客主頁(yè)

