最近在做一图像处理APP的时候需要用到opencv,发现从配置个方面都十分蛋疼,好在经过一番折腾,算是大概弄出来了,在这里大概说说,我用的是android studio开发环境,具体安装配置不再多说,直接从opencv开始。
opencv下载
opencv官网
先去官网下载,我在这里选择了目前的最新版4.1版,选择下载android版本的
下载好后,直接解压,不需要安装之类的步骤,进入解压后的文件夹会有四个文件
sdk是一些编译好的文件,包括.so和.a库,samples中是一些后面会用到的项目文件
然后打开android studio,新建项目,项目建好后,点击File,然后选择NEW,再选择Import Moudle…
(这里不知道为什么电脑抽筋了,没办法截图凑合看吧)
然后是如下界面
然后选择目录,选择opencv文件夹下的sdk,然后选择sdk中的java文件夹,确定即可,这里是我的目录,我之前吧opencv解压后的默认文件夹名称改了,所以按照你的电脑上的文件夹名称就可以了
之后他会让你写module名称
起好后next,会看到如下界面,这里默认就好,finish
这一步结束后,模块基本上导入成功了,但是有些文件还是需要该一下
吧你的项目app文件夹下的build.gradle文件直接拷贝到项目根目录下之前导入模板的文件夹中,文件夹名称就是你刚刚起的那个
例如我刚刚Module name起的是opencv,那我就去项目目录下找opencv文件夹,这个文件夹中原本就有一个build.gradle文件,直接覆盖替换掉就好了,当然也可以直接吧app文件夹里build.gradle的内容直接写道module的build.gradle中,吧module中原本build.gradle文件的内容全部清掉,我在这里用了第二种办法,可以直接在android studio里改,如图(绿色是module的build.gradle,红色是app的build.gradle)
其实这里怎么操作无所谓,只要保证两个build.gradle文件中的版本信息一样就行了
然后,把moudle中的build.gradle中的部分内容稍微改一下
先把apply plugin: 'com.android.application’改成apply plugin: ‘com.android.library’(app的build.gradle文件原样不动)
然后,把applicationId "com.example.mplog"这一句去掉
如图,上面是app的build.gradle,下面是module的build.gradle
之后直接在app的build.gradle文件中的dependencies 中加上implementation project(":你的module名称")
把
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'com.android.support:design:28.0.0'
}
改成
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation project(":opencv")
implementation 'com.android.support:design:28.0.0'
}
改后就把opencv的moudle导入进了你的项目
之后就是最麻烦,也是之前让我纠结很长时间的东西,怎么调用Opencv函数,上面几步做完你会发现你还是不能直接调用opencv函数,不然你的APP可能会在手机上出现闪退或者其它问题,按照官方说法,应该是要在手机里安装对应的opencv Manager.apk才能运行,而在做开发的时候不可能指望用户为了用你的APP就让用户去下载一堆莫名其妙的APP,所以下面就来想办法免去Manager也能运行
我之前也看了很多博客但是多少有点问题,最后发现一个最直接的办法,那就是直接用opencv官方的代码,先到之前opencv解压后的目录下,找到samples文件夹,到./samples/image-manipulations/src/org/opencv/samples/imagemanipulations/这个目录下去,寻找一个叫做ImageManipulationsActivity.java的文件,没错这就是我们要用的文件,把要显示摄像头捕捉到的画面的Activity的java文件换成这个内容,当然这个文件中有一些内容也是我们用不到的,我在这里吧我改后的代码粘贴出来,可以直接把我的这个代码复制到你的项目需要调用摄像头画面的activity的java文件中,包名类名之类的,根据自己的具体情况改一下
package com.example.mplog;
//这里的mplog是我的项目包名,注意
import java.util.Arrays;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.*;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
import org.opencv.imgproc.Imgproc;
import org.opencv.imgproc.*;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
import android.view.*;
import android.view.WindowManager;
public class Main2Activity extends Activity implements CvCameraViewListener2 {
private static final String TAG = "OCVSample::Activity";
private CameraBridgeViewBase mOpenCvCameraView;
private Mat mIntermediateMat;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS:
{
Log.i(TAG, "OpenCV loaded successfully");
mOpenCvCameraView.enableView();
} break;
default:
{
super.onManagerConnected(status);
} break;
}
}
};
public Main2Activity() {
Log.i(TAG, "Instantiated new " + this.getClass());
}
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
Log.i(TAG, "called onCreate");
super.onCreate(savedInstanceState);
//getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
setContentView(R.layout.image_manipulations_surface_view);
mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.cjv);
//这里的cjv也是我的项目中JavaCameraView的id,自己改一下
mOpenCvCameraView.setCvCameraViewListener(this);
}
@Overri
public void onPause()
{
super.onPause();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
@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_3_0_0, this, mLoaderCallback);
} else {
Log.d(TAG, "OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
public void onDestroy() {
super.onDestroy();
if (mOpenCvCameraView != null)
mOpenCvCameraView.disableView();
}
public void onCameraViewStarted(int width, int height) {
}
public void onCameraViewStopped() {
// Explicitly deallocate Mats
if (mIntermediateMat != null)
mIntermediateMat.release();
mIntermediateMat = null;
}
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
Mat rgba = inputFrame.rgba();
Size sizeRgba = rgba.size();
return rgba;
}
}
按照自己的实际情况改一下,不用到那个目录下去复制,直接用我这个,一般来说也是可以的
到此为止还没有完,你会发现你的layout文件夹下并没有setContentView(R.layout.image_manipulations_surface_view);
代码中的image_manipulations_surface_view.xml布局文件,这里我也简单的把我的xml文件分享一下,可以直接粘贴,也可以到opencv的解压目录的samples文件夹下找到,具体路径(opencv解压目录下):./samples/image-manipulations/res,这个目录下的layout文件夹下就有你需要的image_manipulations_surface_view.xml
不过这个布局文件中也只是只有一个JavaCameraView而已,而且可能会出现黑屏的情况,
如果黑屏,试着吧JavaCameraView的background背景的透明度改为0就没问题了
下面是我写的的xml布局文件,这里我已经把JavaCameraView的background背景改为透明了,直接调用就好
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/di"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#FAFFFFFF"
android:orientation="vertical">
<org.opencv.android.JavaCameraView
android:id="@+id/cjv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#00090808" />
</LinearLayout>
就只有一个JavaCameraView很简单,这里我给他的id是cjv
然后在去Manifests.xml文件中吧Main2Activity写进去,我也直接贴我的代码,可以直接复制粘贴
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.mplog">
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-feature
android:name="android.hardware.camera"
android:required="true" />
<uses-feature
android:name="android.hardware.camera.autofocus"
android:required="true" />
<uses-feature
android:name="android.hardware.camera.front"
android:required="true" />
<uses-feature
android:name="android.hardware.camera.front.autofocus"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".Main2Activity"></activity>
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
这里记得吧android:icon="@mipmap/ic"这个APP的图标换成自己的就行了,这个IC是我的项目里的图标
另外记得申请摄像头权限,因为要调用摄像头