Android studio导入opencv开发简单的Demo

   突然接了一个需要接入opencv的需求,作为一个零基础opencv的编程人员,心里怂的一逼。然后各种百度,接着就发现了,网上的资料真的是一大堆的坑,缺这缺那的,没有一个是真正可以让项目跑的起来的。心态爆炸,好在自己去看了一下opencv的文档,总算整出来一个可以正常跑起来的项目,分享开大家,让大家少走的弯路。废话不多说了开始吧:

   首先我们需要去opencv的官网获取我们的SDK,网址:https://opencv.org/

   鉴于opencv官网在没有搭梯子的情况下,下载速度慢,且容易连接失败,博主这里已经有个资源,大家可以去下载就好:https://download.csdn.net/download/weixin_40600325/13985088

   目前博主的opencv的版本是4.5.1的,下载完后我们解压到指定的文件夹后打开这个路径

   

这里面的SDK就是我们需要的东西,想必各位对怎么接入SDK应该已经非常熟悉了吧,但是!请大家先不要着急,我们还要做一件事件,不然后面就都是坑。

首先我们可以先去百度百科搜索opencv,然后我们会看到这样的介绍:

看到了吗?,Opencv是由一系列c函数和少量C++类构成的,这一句话大家想到了什么?我们Android和C、C++交互需要做什么?没错,需要我们的NDK开发,而做NDK开发,就需要安装几个插件,我们先把插件安装好。如果有安装过的同学可以忽略该步骤,那么我们需要安装的插件如下:

NDK和CMake,有的同学可以能还需要LLDB,由于博主的Android studio是最新的版本的,所以只需要Android这两个插件。

安装完后,我们先创建一个项目,名字随意,但是必须是要支持C、C++的项目。如下:

新版的Android studio创建C项目选择的是图中的Native C++这个项,旧版的博主记得是可以直接勾选的支持C++的,都一样,反正就是创建这样一个项目,这个超级重要,避免后面很多的坑。接着我们打开我们创建的项目后,找到下图的文件夹,然后拷贝下来。

一定要把,这个CPP文件夹拷贝下来,或者你也可以直接在该项目做你接入opencv的项目,但是如果你是想加入旧项目中的话,这个文件夹就要拷贝下来。

接着就是重头戏了,我们现在可以关闭这个支持C的项目,又或者你可以用这个项目来做接入Opencv,如下步骤都是适合的。

打开需要接入opencv的项目。

引入我们的解压后得到的Opencv文件夹下的的sdk文件夹下的名为Java的项目作为新的Module,有点绕口,路径是类似这样的:D:\androidProject\OpenCV-android-sdk\sdk\java。

引入后,我们把我们之前拷贝的CPP文件夹放到我们这个项目里,也是在Main文件夹下。

接着我们去我们解压后得到的Opencv文件下找到native的路径:E:\androidProject\OpenCV-android-sdk\sdk\native\libs

然后我们把这个文件夹下面的文件都复制到我们项目的libs文件夹下:

复制到这里来:

同时把我们刚才复制的CPP文件也拷贝到该项目下的main的文件夹下:

最后,我们在App的gradle文件夹下加上这三段代码:

至此,我们最最重要的步骤完成了,只要你是跟着我步骤走的,你就可以避免网络上绝大多数的坑,列如:需要安装OpenCV Manager这样的坑,还有缺失C++_shared的坑。

到这里我们就可以把解压后的Opencv文件下的Java文件导入到我们的项目里面了,路径如下:

E:\androidProject\OpenCV-android-sdk\sdk\java

然后把导入后的JavaModule文件下的gradle改成如下的代码:

这样你就可以避免你的报错,比如:applicationId不能在library情况下设置,导入的module是项目之类的错误。

接着最好确认一下你的setting文件是不是这样的:

都没有问题后,我们就可以好好的使用我们的opencv写一下简单的代码了,因为我们已经接入好opencv了。

在写入代码之前,记得要引入一下我们的C++库,在我们的类里面写入这几行代码:

因为博主的是opencv4的版本,所以引入的是opencv_java4,如果是3点几的版本就引入opencv_java3。

接下来就是博主Demo的代码,就贴出来给大家参考一下:

首先是XML的:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical">

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:id="@+id/img"
        android:layout_marginTop="100dp"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="导入图片"
        android:layout_gravity="center"
        android:layout_marginTop="20dp"
        android:id="@+id/Import_img"/>
    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="50sp"
        android:layout_gravity="center"
        android:text="灰度化图片"
        android:id="@+id/Change_img"/>

</LinearLayout>

然后是main类的代码:


import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import java.io.FileNotFoundException;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("opencv_java4");
        System.loadLibrary("native-lib");
    }

    private Button Import_img;
    private  Button Change_img;
    private ImageView img;
    private Bitmap bitmap;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Import_img = findViewById(R.id.Import_img);
        img= findViewById(R.id.img);
        Change_img=findViewById(R.id.Change_img);
        Import_img.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                //intent可以应用于广播和发起意图,其中属性有:ComponentName,action,data等
                Intent intent=new Intent();
                intent.setType("image/*");
                //action表示intent的类型,可以是查看、删除、发布或其他情况;我们选择ACTION_GET_CONTENT,系统可以根据Type类型来调用系统程序选择Type
                //类型的内容给你选择
                intent.setAction(Intent.ACTION_GET_CONTENT);
                //如果第二个参数大于或等于0,那么当用户操作完成后会返回到本程序的onActivityResult方法
                startActivityForResult(intent, 1);
            }
        });
        Change_img.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                Bitmap bit = bitmap.copy(Bitmap.Config.ARGB_8888, false);
                Mat src = new Mat(bit.getHeight(), bit.getWidth(), CvType.CV_8UC(3));
                Utils.bitmapToMat(bit, src);
                Imgproc.cvtColor(src, src, Imgproc.COLOR_BGR2GRAY);
                Utils.matToBitmap(src, bitmap);
                Message message=new Message();
                message.what=1;
                handler.sendMessage(message);
            }
        });

    }
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        //用户操作完成,结果码返回是-1,即RESULT_OK
        if(resultCode==RESULT_OK){
            //获取选中文件的定位符
            Uri uri = data.getData();
            Log.e("uri", uri.toString());
            //使用content的接口
            ContentResolver cr = this.getContentResolver();
            try {
                //获取图片
                bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
                img.setImageBitmap(bitmap);
            } catch (FileNotFoundException e) {
                Log.e("Exception", e.getMessage(),e);
            }
        }else{
            //操作错误或没有选择图片
            Log.i("MainActivtiy", "operation error");
        }
        super.onActivityResult(requestCode, resultCode, data);
    }
    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
//            Log.d("test", "Internal OpenCV library not found. Using OpenCV Manager for initialization");
//            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, mLoaderCallback);
        } else {
//            Log.d("test", "OpenCV library found inside package. Using it!");
//            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }
    Handler handler=new Handler(){

        @Override
        public void handleMessage(@NonNull Message msg) {
            super.handleMessage(msg);

            switch (msg.what)
            {
                case 1:img.setImageBitmap(bitmap);break;
            }
        }
    };

    //openCV4Android 需要加载用到
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS: {
                    Log.i("test", "OpenCV loaded successfully");
//                    mOpenCvCameraView.enableView();
//                    mOpenCvCameraView.setOnTouchListener(ColorBlobDetectionActivity.this);
                }
                break;
                default: {
                    super.onManagerConnected(status);
                }
                break;
            }
        }
    };
}

最后,如果有什么问题欢迎留言一起探讨,谢谢各位。

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值