【源码分析】Opencv-免装OpenCV Manager

来源:互联网 发布:数据库int长度 编辑:程序博客网 时间:2024/06/16 06:51

最近在接触opencv做图像处理的时候,发现直接使用OpenCV-2.4.10-android-sdk【在opencv自带的face-demo里可以看到怎么使用】在运行的时候需要安装一个OpenCV Manager,究竟是什么情况呢,下面通过源码分析一下:

在opencv源码里面的sample-face-demo的MainActivity的onResume函数会执行以下命令

    @Override    public void onResume() {        super.onResume();        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10,         MainActivity.this, mLoaderCallback)} }

opencv源码

    /**     * Loads and initializes OpenCV library using OpenCV Engine service.     * @param Version OpenCV library version.     * @param AppContext application context for connecting to the service.     * @param Callback object, that implements LoaderCallbackInterface for handling the connection status.     * @return Returns true if initialization of OpenCV is successful.     */    public static boolean initAsync(String Version, Context AppContext,            LoaderCallbackInterface Callback)    {        return AsyncServiceHelper.initOpenCV(Version, AppContext, Callback);    }

这个函数会去加载并初始化opencv库,使用opencv引擎服务

接着进去
AsyncServiceHelper.initOpenCV

   public static boolean initOpenCV(String Version, final Context AppContext,            final LoaderCallbackInterface Callback)    {        AsyncServiceHelper helper = new AsyncServiceHelper(Version, AppContext, Callback);        //绑定服务        //helper.mServiceConnection是回调接口        if (AppContext.bindService(new Intent("org.opencv.engine.BIND"),                helper.mServiceConnection, Context.BIND_AUTO_CREATE))        {            return true;        }        else        {            AppContext.unbindService(helper.mServiceConnection);            InstallService(AppContext, Callback);            return false;        }    }

在这个函数里面可以看到会去绑定相关的opencv引擎服务

绑定就需要用到OpenCV Manager的帮助了

helper.mServiceConnection是回调接口
这里写图片描述

那么onServiceConnected函数究竟做了什么?我们一探究竟

public void onServiceConnected(ComponentName className, IBinder service){Log.d(TAG, "Service connection created");mEngineService = OpenCVEngineInterface.Stub.asInterface(service);if (null == mEngineService){//注意,这里就去执行安装OpenCV Manager  Log.d(TAG, "OpenCV Manager Service connection fails. May be service was not installed?");  InstallService(mAppContext, mUserAppCallback);}else{  mServiceInstallationProgress = false;  ................  //省略了一部分代码 }}

一旦判断引擎服务为空,也就是连接失败的时候,就会执行

 InstallService(mAppContext, mUserAppCallback);

进去可以看到

 protected static void InstallService(final Context AppContext, final LoaderCallbackInterface Callback)    {        if (!mServiceInstallationProgress)        {                Log.d(TAG, "Request new service installation");                InstallCallbackInterface InstallQuery = new InstallCallbackInterface() {                private LoaderCallbackInterface mUserAppCallback = Callback;                public String getPackageName()                {                    return "OpenCV Manager";                }                public void install() {                    Log.d(TAG, "Trying to install OpenCV Manager via Google Play");                    //这里会从Google Play 去下载OpenCV Manager 来安装                    //安装成功返回true                    boolean result = InstallServiceQuiet(AppContext);                    if (result)                    {                        mServiceInstallationProgress = true;                        Log.d(TAG, "Package installation started");                    }                    else                    {                        Log.d(TAG, "OpenCV package was not installed!");                        int Status = LoaderCallbackInterface.MARKET_ERROR;                        Log.d(TAG, "Init finished with status " + Status);                        Log.d(TAG, "Unbind from service");                        Log.d(TAG, "Calling using callback");                        mUserAppCallback.onManagerConnected(Status);                    }                public void cancel(){                    Log.d(TAG, "OpenCV library installation was canceled");                    int Status = LoaderCallbackInterface.INSTALL_CANCELED;                    Log.d(TAG, "Init finished with status " + Status);                    Log.d(TAG, "Calling using callback");                    mUserAppCallback.onManagerConnected(Status);                }                public void wait_install()                {                    Log.e(TAG, "Instalation was not started! Nothing to wait!");                }             }          }      }

InstallServiceQuiet(AppContext);

    protected static final String TAG = "OpenCVManager/Helper";    protected static boolean InstallServiceQuiet(Context context)    {        boolean result = true;        try        {            //执行安装            Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(OPEN_CV_SERVICE_URL));            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);            context.startActivity(intent);        }        catch(Exception e)        {            result = false;        }        return result;    }

拨开层层迷雾,终于可以看到执行安装Opnecv Manager的代码了,可以看到是通过Uri去下载
OPEN_CV_SERVICE_URL

    /**     *  URL of OpenCV Manager page on Google Play Market.     */    protected static final String OPEN_CV_SERVICE_URL = "market://details?id=org.opencv.engine";

安装完成就通过LoaderCallbackInterface回调处理相关逻辑

那么问题来了,可不可以绕过安装Opencv Manager,直接就能运行程序呢?答案是有的


在Opencv 3.30安装包里面也有Face-detection的Demo,里面的FdActivity的onResume函数改成以下:

 @Override  public void onResume() {       super.onResume();       if (!OpenCVLoader.initDebug()) {           Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");           OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_10, MainActivity.this, mLoaderCallback);       } else {           Log.d(TAG, "OpenCV library found inside package. Using it!");           mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);       }   }

加了这个就可以实现不安装Opencv Manager 也能运行opencv的程序了


好,那它究竟是怎么工作的呢?
直接进入函数看

    /**     * Loads and initializes OpenCV library from current application package. Roughly, it's an analog of system.loadLibrary("opencv_java").     * @return Returns true is initialization of OpenCV was successful.     */    public static boolean initDebug()    {        return StaticHelper.initOpenCV(false);    }

看它的注释就可以知道
只要加载opencv的libs里面的libopencv_java.so就可以了
因此只需要把opencv3.30的开发包里面的libopencv_java.so导入到工程就可以了
具体步骤:

导入动态库
这里写图片描述

我这里只用了armeabi的架构,所以要去配置build_gradle
defaultConfig里面添加
这里写图片描述

android配置libs路径,我这里使用默认路径,所以要配置
这里写图片描述

最后在CMakeLists.txt 简单 配置
这里写图片描述

最后 Sync 一下项目就可以了

2017/10/26学习Opencv总结。

原创粉丝点击