Android studio+opencv-4.1.0 开发环境搭建(一)

最近在做一图像处理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是我的项目里的图标
另外记得申请摄像头权限,因为要调用摄像头

发布了13 篇原创文章 · 获赞 28 · 访问量 8480

猜你喜欢

转载自blog.csdn.net/weixin_43815930/article/details/90516455