OpenCV On Android環境配置最新&最全指南(Eclipse篇)

來源:互聯網
上載者:User

標籤:pen   搭建   strip   資料擷取   注意   3.0   安裝   -668   line   

簡介

本教程是經過本人多次踩坑,並參考網上眾多OpenCV On Android的配置教程總結而來,盡希望能協助學習移動影像處理的朋友們少走彎路。
這也是本人第一次在簡書上發布文章,如有不足,希望各位dalao能夠指正,我也將及時修改。配置上如果遇到問題,也可以在評論裡留言,我將儘力協助解決。
如有轉載,請標明出處http://www.jianshu.com/p/b260ebb1c180
如果您使用的是android studio,請參考下一章OpenCV On Android環境配置最新&最全指南(Android studio篇)。

環境

電腦:Windows10
Java:jdk1.8.0_131
Eclipse:Neon.3 Release (4.6.3)
ADT:ADT-23.0.7
NDK:Android Studio2.3內建的最新NDK
OpenCV:V3.2.0
SDK:25.2.5 (單獨下載,請不要與Android Studio同用,否則你將不能在eclipse上正確建立Android項目)

註:以上配置基本上為最新版本

一、建立OpenCV Demo

這裡只需建立普通Eclipse Android項目工程,沒什麼重要的地方可說的,如果這都不會,建議先把Android基礎學好。這裡我建立的是名為OpenCVDemo的項目,包名為com.demo.opencv

二、選擇您所需要的環境

1、如果你只想用在應用程式層編寫程式的話,請直接閱讀下面OpenCV Java庫使用指南
2、如果只想在原生層快速進行影像處理的話,請直接跳到下面OpenCV NDK庫使用指南
3、如果想同時使用OpenCV Java庫和Native庫的話,請參考OpenCV 混合使用指南
接下來我簡要介紹兩者的區別與優缺點。

1、使用OpenCV Java庫和NDK庫的區別

簡而言之,如果使用OpenCV Java庫,你只需在應用程式層使用Java語言編寫代碼,由OpenCV Java庫通過AIDL串連OpenCV Manager進行影像處理。
如果你使用的OpenCV NDK庫,就能在原生層使用C/C++編寫代碼,此時就涉及到JNI。
雖然兩者使用的程式設計語言不同,但最終結果都是在原生層實現影像處理功能,因為OpenCV Java庫只是將原生代碼(C/C++)用Java封裝(JNI)好,並打包成so檔案,存入OpenCV Manager裡,外部應用通過AIDL進行調用,這就是為什麼使用Java庫時必須要額外安裝OpenCV Manager的原因了。不過我將會在OpenCV Java庫使用指南中介紹一個不需要安裝OpenCV Manager的方法,彌補其不足,同時OpenCV 混合使用指南則提供一個更為簡便的方法。

2、使用OpenCV Java庫和NDK庫的優缺點

Java庫的缺點:
如果使用Java庫的話,手機上除了安裝你編寫的應用外,還需要額外安裝OpenCV Manager檔案,其位於OpenCV Android SDK/apk/目錄下,請根據你編寫的apk架構(如果你僅使用Java開發,則可以不用考慮apk架構)和你手機cup架構選擇對應的apk檔案,一般這兩個選擇armeabi架構便能相容絕大多數的手機。
Java庫的優點:
1、不需要C/C++的功底便能輕鬆實現在Android用戶端的影像處理,非常適合只會Java語言的編程人員。
2、因為有兩個應用(自己編寫的程式和OpenCV Manager),你將獲得更多的記憶體處理空間(一個Android應用預設分配記憶體上限為24M)。
3、Java庫封裝了幾個網路攝影機顯示控制項,如:JavaCameraView,NativeCameraView(目前OpenCV3.2裡該控制項已經被取消),我們使用少量代碼就能實現網路攝影機資料擷取->處理->顯示等一系列操作。
NDK庫的優點:
1、如果使用Native庫的話,你可以完全拋棄OpenCV Manager的安裝,同時由於在底層進行影像處理,其處理速度會增加(但由於Android高版本的最佳化,加上OpenCV Java庫其實也是在調用其原始層的庫,所以這種差距並不明顯)。
2、使用NDK庫的話,需採用C\C++進行編程,此方法更便於從Visual Studio進行程式移植。
NDK庫的缺點:
需要一定的C\C++功底,如果涉及到調用網路攝影機,需自行編寫緩衝架構,避免資料幀堵塞。同時必須熟悉JNI的函數操作,何時釋放記憶體和引用等等。如果你想在底層進行OpenGL ES渲染映像,還需對Android底層和OpenGL ES有一定瞭解(但前者並不是必須的)。

三、OpenCV Java庫使用指南環境配置

第一步:Eclipse菜單->File->Import->Android->Existing Android Code Into Workspace(如果沒此選項,請確保你的eclipse 上ADT是否配置正確),然後匯入OpenCV Android SDK\ sdk\java這個項目。


1.png

為了防止誤操作OpenCV庫,建議勾選Copy project into workspace,將該庫copy到你的工作資料夾。然後Finish,如果匯入後出現報錯,請將Project build Target設定為Android5.0以上(因為一般是Camera2報錯,Camera2隻存在於Android5.0+),具體方法是項目滑鼠右鍵,選擇Properties,然後點擊Android,選擇Android5.0以上的版本即可,然後OK,這裡我選擇的是6.0。


2.png

第二步:在你的項目右鍵也進入的頁面,Library選擇Add,添加OpenCV庫(如),OK後,你的項目將可以使用OpenCV Java函數了。


3.pngDemo編寫

建立一個Java影像處理類OpenCV_Java .java(請忽略我的命名)
OpenCV_Java .java內容:

public class OpenCV_Java extends BaseLoaderCallback {    private boolean isInit = false;    private Context context;    public OpenCV_Java(Context context){        super(context);        this.context = context;    }    @Override    public void onManagerConnected(int status) {           switch (status) {             case LoaderCallbackInterface.SUCCESS:                 isInit = true;              break;             default:                 isInit = false;                 super.onManagerConnected(status);              break;         }    }    public void toGary(Bitmap bitmap){        if(isInit){            Mat mat = new Mat();            Utils.bitmapToMat(bitmap, mat);            Imgproc.cvtColor(mat, mat,Imgproc.COLOR_RGBA2GRAY );            Utils.matToBitmap(mat, bitmap);        }else{            Toast.makeText(context, "OpenCV init error", Toast.LENGTH_LONG).show();        }    }}

MainActivity.java內容:

public class MainActivity extends Activity implements OnClickListener {    private ImageView imageView;    private Bitmap bitmap;    private Button showBtn, processBtn;    private OpenCV_Java javaUtil = new OpenCV_Java(this);    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = (ImageView) findViewById(R.id.imageView);        showBtn = (Button) findViewById(R.id.show);        showBtn.setOnClickListener(this);        processBtn = (Button) findViewById(R.id.process);        processBtn.setOnClickListener(this);    }    @Override    public void onResume() {        super.onResume();        if (!OpenCVLoader.initDebug()) {            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_2_0, this, javaUtil);        } else {            javaUtil.onManagerConnected(LoaderCallbackInterface.SUCCESS);        }    }    @Override    public void onClick(View v) {        if (v == showBtn) {            bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);            imageView.setImageBitmap(bitmap);        } else {            if (bitmap != null) {//避免二次處理                javaUtil.toGary(bitmap);                imageView.setImageBitmap(bitmap);                bitmap = null;            }        }    }}

布局內容:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent" >    <ImageView        android:id="@+id/imageView"        android:layout_width="match_parent"        android:layout_height="match_parent" />    <LinearLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:orientation="horizontal" >        <Button            android:id="@+id/show"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"             android:text="show"/>        <Button            android:id="@+id/process"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:layout_weight="1"             android:text="process"/>    </LinearLayout></RelativeLayout>
安裝OpenCV Manager

其位置位於OpenCV-android-sdk\apk目錄下,選擇合適的apk程式,一般選擇OpenCV_3.2.0_Manager_3.20_armeabi.apk即可。

運行Demo

將項目編譯打包成apk,安裝到手機,運行,點擊按鈕show後,其效果:


4.png

點擊按鈕process,將其轉化為灰階圖,如下所示:


5.png
  • 注意:如果出現OpenCV was not initialised correctly.Application will be shut down,可能是你的OpenCV Manager程式與你的cpu架構不同,選擇合適的apk即可。如果是手機版本比較高,有可能手機會阻止你的應用去調用OpenCV Manager,其目的是防止惡意軟體相互喚醒(比如百度全家桶),解決方案自行百度(因為沒有統一的方法)。拋棄OpenCV Manager:安裝一個額外的apk對使用者來說非常不友好,但使用C/C++編程,對一些Java程式員又提高了實現難度,故我們應該想一個兩全其美的方法,即協助開發人員使用java快速開發,又給使用者一良好體驗。
    思路:
    Java庫實際上只是對NDK庫進行java封裝,將so檔案放在OpenCV Manager內,通過AIDL進行資料交流,並實現影像處理。
    解決辦法:
    如果我們將OpenCV Manager裡面的NDK庫放到我們的應用裡,不就能拋棄OpenCV Manager並實現影像處理了嗎?答案是YES,我們將OpenCV-android-sdk\sdk\native\libs\[架構]目錄下(這裡選擇合適的架構,一般用armeabi即可)的libopencv_java3.so放在你的項目libs\[架構]目錄(需自己手動建立)下,項目結構

6.png

然後在你的MainActivity.java裡面靜態載入這個so庫

public class MainActivity extends Activity implements OnClickListener {    private ImageView imageView;    private Bitmap bitmap;    private Button showBtn, processBtn;    private OpenCV_Java javaUtil = new OpenCV_Java(this);    static{        System.loadLibrary("opencv_java3");    }    @Override    protected void onCreate(Bundle savedInstanceState) {    ......下面內容不變

編譯並安裝,這時候,你就可以將你的OpenCV Manager卸載掉了。運行結果與之前的無異。
此方法並不是完美的,因為在這個程式裡,你只實現了彩色映像變灰階映像,但你卻安裝了這個原生庫,apk足足有4.39M,相比之前的194k來說,接近增長了20倍。但如果你的應用比較大,而這個so檔案的大小是固定的,此時採用此方法將是一個不錯的選擇。

四、OpenCV NDK庫使用指南環境配置

第一步:配置NDK環境
進入菜單->Window->Preferences->Android->NDK,設定NDK Location路徑,註:請確保該路徑下存在ndk-build.cmd檔案。如:


7.png

第二步:配置JNI環境
這裡我將使用簡便方法快速配置:
1、在你的項目右鍵Android Tools->Add native support->輸入合適的名稱->確定,這裡我就直接使用預設的"OpenCVDemo"
2、本地建立一個xml檔案,將下面內容copy進去,修改其中的路徑。

<?xml version="1.0" encoding="UTF-8"?><cdtprojectproperties><section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.IncludePaths"><language name="c,cpp"><includepath>D:/Android/android-sdk/ndk-bundle/platforms/android-9/arch-arm/usr/include</includepath><includepath>D:/Android/android-sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/include</includepath><includepath>D:/Android/android-sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi/include</includepath><includepath>D:/Android/android-sdk/ndk-bundle/sources/cxx-stl/gnu-libstdc++/4.9/libs/armeabi-v7a/include</includepath><includepath>D:/Android/android-sdk/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/include</includepath><includepath>D:/OpenCV/OpenCV-android-sdk/sdk/native/jni/include</includepath></language></section><section name="org.eclipse.cdt.internal.ui.wizards.settingswizards.Macros"><language name="c,cpp"></language></section></cdtprojectproperties>

3、項目右鍵選擇最後一個Properties,然後選擇C/C++ General -> Path and Symbols,:


8.png

點擊Import Settings->Browse,在電腦本地選擇上面的xml檔案,點擊Finish,環境就匯入成功了。
接下來查看環境是否正確。
1、查看路徑是否存在:按照,將編譯器切換到C/C++編輯器模式:


9.png


展開項目,查看Include目錄下路徑是否為灰色(如),並且都能展開,如果都滿足,表示路徑都存在。


10.png


2、查看環境是否正常。進入jni目錄,開啟OpenCVDemo.cpp,在#include<jni.h>這句代碼上使用Ctrl+滑鼠左鍵,如果eclipse能開啟jni.h這個檔案,說明你的JNI環境就搭建成功了。
第二步:配置OpenCV NDK環境
1、將下面內容copy進Android.mk檔案,其中OPENCV_ANDROID_SDK 請設定為正確路徑,同時請注意我在資訊清單檔裡的注釋

LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)# ############################################################這裡改成你的路徑,分割線內其餘內容不變OPENCV_ANDROID_SDK := D:/OpenCV/opencv_android_sdk#OPENCV_BULID_TYPE := NDK #預設NDK環境,不會自動匯入openCV_java3.so,故不支援OpenCV Java庫OPENCV_BULID_TYPE := JAVA_AND_NDK #將自動匯入openCV_java3.so,來支援Java庫(無需安裝OpenCV Manager)ifeq ($(OPENCV_BULID_TYPE), JAVA_AND_NDK)     OPENCV_LIB_TYPE := SHARED    OPENCV_INSTALL_MODULES := onelse    OPENCV_LIB_TYPE := STATICendif ifdef OPENCV_ANDROID_SDK  ifneq ("","$(wildcard $(OPENCV_ANDROID_SDK)/OpenCV.mk)")    include ${OPENCV_ANDROID_SDK}/OpenCV.mk  else    include ${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk  endifelse  include ../../sdk/native/jni/OpenCV.mkendif# ############################################################動態連結日誌庫LOCAL_LDLIBS += -llog -ljnigraphicsLOCAL_MODULE    := OpenCVDemoLOCAL_SRC_FILES := OpenCVDemo.cppinclude $(BUILD_SHARED_LIBRARY)

2、在jni目錄下增加Application.mk檔案
其內容如下:

APP_STL := gnustl_staticAPP_CPPFLAGS := -frtti -fexceptionsAPP_ABI := armeabiAPP_PLATFORM := android-8APP_OPTIM := debug

到此為止,NDK環境配置完畢。

Demo編寫

布局檔案與上面的Java Demo無異,MainActivity.java內容如下:

public class MainActivity extends Activity implements OnClickListener {    private ImageView imageView;    private Bitmap bitmap;    private Button showBtn, processBtn;    private OpenCV_NDK nativeUtil = new OpenCV_NDK();    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        imageView = (ImageView) findViewById(R.id.imageView);        showBtn = (Button) findViewById(R.id.show);        showBtn.setOnClickListener(this);        processBtn = (Button) findViewById(R.id.process);        processBtn.setOnClickListener(this);    }    @Override    public void onClick(View v) {        if (v == showBtn) {            bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);            imageView.setImageBitmap(bitmap);        } else {            if (bitmap != null) {                nativeUtil.toGary(bitmap);                imageView.setImageBitmap(bitmap);                bitmap = null;            }        }    }}

這裡可以看出並無太大的改變。其中OpenCV_NDK.java內容如下:

public class OpenCV_NDK {    static{        System.loadLibrary("OpenCVDemo");    }    native void toGary(Object bitmap);}

是不是特別簡單^_^。然後在控制台使用javah命令將其產生jni標頭檔,此處我用的一鍵產生(參考了《Android C進階編程 使用NDK》),Eclipse配置如下:
菜單Run->External Tools->External Tools Configurations,雙擊Program,右側將產生新介面。配置如下:

Main選項卡裡
Name:Generate C and C++ HeaderFile
Location:${system_path:javah}
Working Directory:${project_loc}/jni
Arguments:-classpath "${project_classpath};
${env_var:ANDROID_SDK_HOME}/platforms/android-14/android.jar" ${java_type_name}

切換到Refresh選項卡:
選中Refresh resource up completion,並在列表裡選擇The project containing the selected resource

切換到Common選項卡,勾選上External Tools。

配置完成(上面的配置按照實際情況修改,本人建議還是使用javah命令產生標頭檔)
其中ANDROID_SDK_HOME是我在電腦環境配置裡建立的一個變數,指向的是sdk路徑。

然後將你的滑鼠點中OpenCV_NDK.java,然後點擊位置:


11.png

幾秒後,將產生com_demo_opencv_OpenCV_NDK.h標頭檔(這個檔案名稱跟你包名和類名有關)。
將OpenCVDemo.cpp修改為如下內容:

#include "com_demo_opencv_OpenCV_NDK.h"#include <opencv2/opencv.hpp>#include <android/bitmap.h>using namespace cv;JNIEXPORT void JNICALL Java_com_demo_opencv_OpenCV_1NDK_toGary  (JNIEnv *env, jobject thiz, jobject bitmap){    AndroidBitmapInfo bitmapInfo;    void* bitmapPixels;    int width, height, ret;    //解析bitmap    if ((ret = AndroidBitmap_getInfo(env, bitmap, &bitmapInfo)) < 0) {        return;    }    if (bitmapInfo.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {        return ;    }    if ((ret = AndroidBitmap_lockPixels(env, bitmap, &bitmapPixels)) < 0) {        return;    }    width = bitmapInfo.width;    height = bitmapInfo.height;    Mat bgra(height, width, CV_8UC4, bitmapPixels);    Mat gary;    cvtColor(bgra,gary,COLOR_RGBA2GRAY);    cvtColor(gary,bgra,COLOR_GRAY2BGRA);    AndroidBitmap_unlockPixels(env, bitmap);}

然後編譯運行,結果與Java運行結果無異,無需安裝OpenCV Manager,此方法編譯的安裝包只有951kb,影像處理時間本人並沒有計算,應該相差無幾。

五、OpenCV 混合使用指南

假設你已經看了前兩種配置,習慣於Java開發,但又覺得OpenCV Java庫提供的方法不夠,希望使用混合開發,那恭喜你,這一部分就是你所需要的。這部分內容很少,總結起來就兩部分:
1、匯入OpenCV Java庫並關聯你的應用,參考OpenCV Java庫使用指南(記得寫靜態載入so庫的內容,但so檔案不需要你手動匯入)。
2、配置JNI環境與NDK環境,參考OpenCV NDK庫使用指南
3、修改Android.mk檔案內容:OPENCV_BULID_TYPE := NDKOPENCV_BULID_TYPE := JAVA_AND_NDK
然後編譯,這時候Android.mk會打包你的原生代碼成libOpenCVDemo.so檔案,並將其與libopencv_java3.so同時放入你的libs目錄。


12.png


這樣就輕易實現免安裝OpenCV Manager,進行java和c++混合處理映像,同時免於手動匯入libopencv_java3.so,注意:靜態匯入so的代碼必須有

六、總結

本教程致力於協助OpenCV新人快速配置,可能有不足之處,接受大家的建議與批評,後續將進行補充和改進。同時歡迎大家一起探討Android影像處理的知識,共同進步。

OpenCV On Android環境配置最新&最全指南(Eclipse篇)

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.