36、Android配置opencv4.4及调用opencv4.4的附加模块(java/c++)darkenetyolo4.0模型检测

基本思想:因项目需要,需要在Android Studio上测试一下最新的的darknet yolo4的的识别效果;在此,记录一下配置环境和开发过程;在博客最后提供了两个百度链接,分别是纯android 使用java调用opencv DNN的yolo4模型和android使用c++调用opencv DNN的yolo4模型;

一、创建一个可用的Android Studio工程,其配置基本如下;

然后进行环境编译工具的配置,我的环境工具配置工具如下:

在Android 手机显示为:(在期间遇到的其它问题,请自行解决)

 二、去opencv 官网 下载opencv对应的Android代码

axel -n 100 https://jaist.dl.sourceforge.net/project/opencvlibrary/4.4.0/opencv-4.4.0-android-sdk.zip

解压的目录结构为:

ubuntu@ubuntu:OpenCV-android-sdk$ tree -L 2
.
├── LICENSE
├── README.android
├── samples
│   ├── 15-puzzle
│   ├── build.gradle
│   ├── camera-calibration
│   ├── color-blob-detection
│   ├── face-detection
│   ├── gradle
│   ├── gradle.properties
│   ├── gradlew
│   ├── gradlew.bat
│   ├── image-manipulations
│   ├── settings.gradle
│   ├── tutorial-1-camerapreview
│   ├── tutorial-2-mixedprocessing
│   └── tutorial-3-cameracontrol
└── sdk
    ├── build.gradle
    ├── etc
    ├── java
    ├── libcxx_helper
    └── native

15 directories, 8 files

然后在Android Studio --->file--->new--->import Module开始导入opencv4.4.0模块

然后设置一下对应的工程对应包;

Android Studio 中的opencv4.4调用yolo4的配置文件下载地址为:https://github.com/opencv/opencv_extra/blob/4.4.0/testdata/dnn

模型去yolo官网下载即可;

其中 Android Sudio 的代码文件为:\app\src\main\java\com\example\testyolo4\MainActivity.java

package com.example.androidyolo;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.dnn.Dnn;
import org.opencv.dnn.Net;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import java.io.File;

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("opencv_java4");
    }
    private String sdPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        boolean load = OpenCVLoader.initDebug();
        if (load) {
            Log.i("MainActivity", "Open CV Libraries loaded...");
        } else {
            Log.i("MainActivity", "Open CV Libraries not loaded...");
        }
//
        String image_file = sdPath + File.separator + "1.png";//IMG_9452.JPG
        Mat im = Imgcodecs.imread(image_file, Imgcodecs.IMREAD_COLOR);
        // get a new Frame
        // Mat im = inputFrame.rgba();
        String[] names = new String[]{
                "aeroplane","bicycle","bird","boat","bottle",
                "bus","car","cat","chair","cow",
                "diningtable","dog","horse","motorbike","person",
                "pottedplant","sheep","sofa","train","tvmonitor"
        };
           ///\\storage\\sdcard0\\360\\yolov4-tiny.cfg
        String cfg_path= sdPath + File.separator + "yolov4.cfg";
        String model_path= sdPath + File.separator + "yolov4.weights";
        Net net = Dnn.readNetFromDarknet(cfg_path, model_path);
        if ( net.empty() ) {
            System.out.println("Reading Net error");
        }

        if( im.empty() ) {
            System.out.println("Reading Image error");
        }

        Mat frame = new Mat();
        Size sz1 = new Size(im.cols(),im.rows());
        Imgproc.resize(im, frame, sz1);
        Mat resized = new Mat();
        Size sz = new Size(416,416);
        Imgproc.resize(im, resized, sz);
        float scale = 1.0F / 255.0F;
        Mat inputBlob = Dnn.blobFromImage(im, scale, sz, new Scalar(0), false, false);
        net.setInput(inputBlob, "data");//
        Mat detectionMat = net.forward();//Mat detectionMat = net.forward("detection_out");
        if( detectionMat.empty() ) {
            System.out.println("No result");
        }

        for (int i = 0; i < detectionMat.rows(); i++)
        {
            int probability_index = 5;
            int size = (int) (detectionMat.cols() * detectionMat.channels());
            float[] data = new float[size];
            detectionMat.get(i, 0, data);
            float confidence = -1;
            int objectClass = -1;
            for (int j=0; j < detectionMat.cols();j++)
            {
                if (j>=probability_index && confidence<data[j])
                {
                    confidence = data[j];
                    objectClass = j-probability_index;
                }
            }

            if (confidence > 0.3)
            {
                System.out.println("Result Object: "+i);
                for (int j=0; j < detectionMat.cols();j++)
                    System.out.print(" "+j+":"+ data[j]);
                System.out.println("");
                float x = data[0];
                float y = data[1];
                float width = data[2];
                float height = data[3];
                float xLeftBottom = (x - width / 2) * frame.cols();
                float yLeftBottom = (y - height / 2) * frame.rows();
                float xRightTop = (x + width / 2) * frame.cols();
                float yRightTop = (y + height / 2) * frame.rows();
                System.out.println("Class: "+ names[objectClass]);
                System.out.println("Confidence: "+confidence);
                System.out.println("ROI: "+xLeftBottom+" "+yLeftBottom+" "+xRightTop+" "+yRightTop+"\n");

                Imgproc.rectangle(frame, new Point(xLeftBottom, yLeftBottom),
                        new Point(xRightTop,yRightTop),new Scalar(0, 255, 0),3);
            }
        }

        Imgcodecs.imwrite(sdPath + File.separator +"out.jpg", frame );

        ///

    }
}

输出图片

提供一个打好包的Android Studio &Opencv4.4.0的工程

链接:https://pan.baidu.com/s/1iEvY9yYJzXn3ZcBFD4n40A 
提取码:uyx1

补充:如果希望在Android 的c++ 模块中使用opencv4.4.0仅需要完成以下几步设置即可,没必要导入opencv4.4.0的整个sdk,只需导入libs包和对应的include头文件即可(注还需要配置一下对应的Android中cmakefile.txt和对应的gradle):

将对应的文件复制到对应的目录下,没有的文件夹,请自行创建;

对应的其它文件修改及其配置为:

CMakefile.txt文件的修改内容为;

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

# 添加opencv的头文件目录
include_directories(${CMAKE_SOURCE_DIR}/include)

# 导入opencv的so
add_library(libopencv_java4 SHARED IMPORTED)
set_target_properties(libopencv_java4 PROPERTIES IMPORTED_LOCATION
        ${CMAKE_SOURCE_DIR}/../jniLibs/libs/${ANDROID_ABI}/libopencv_java4.so)

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.

find_library( # Sets the name of the path variable.
              log-lib

              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib
                        jnigraphics
                        libopencv_java4 # 链接opencv的so
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

对应的gradle文件修改;

        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
                arguments '-DANDROID=c++_shared'
                abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'

            }
        }
    }
    sourceSets{
        main{
            jniLibs.srcDirs=["src/main/jniLibs/libs"]
        }
    }

然后就可以在Android的c++模款中调用opencv;

这里提供一个android 使用opencv4.4.0调用c++的的yolo4例子:(代码中提供了在c++ 中使用list 数据结构封装好传递给Android的list结构中代码逻辑,可以参考哦~~)

链接:https://pan.baidu.com/s/1PDHyaCGTwq-LE95vv4yAxg 
提取码:k2yn

猜你喜欢

转载自blog.csdn.net/sxj731533730/article/details/108380540
4.4