基本思想:因项目需要,需要在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