最近在接触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总结。