Opencv ANN_MLP training in Android

北城以北 提交于 2019-12-23 02:36:57

问题


I have implemented an ANN character classifier in opencv C++. I have created a model:

        cv::Mat layers(3,1,CV_32S);
        layers.at<int>(0,0) = ATTRIBUTES;//400
        layers.at<int>(1,0)=25;//hidden layer
        layers.at<int>(2,0) =CLASSES;// eg. 10

        CvANN_MLP nnetwork(layers, CvANN_MLP::SIGMOID_SYM,0.6,1);

        CvANN_MLP_TrainParams params(
           cvTermCriteria(CV_TERMCRIT_ITER+CV_TERMCRIT_EPS, 1000, 0.000001),
                                        CvANN_MLP_TrainParams::BACKPROP,
                                        0.1, 0.1);
        int iterations = nnetwork.train(training_set, training_set_classifications,cv::Mat(),cv::Mat(),params);
        CvFileStorage* storage = cvOpenFileStorage( "C:\\example\\myModel.xml", 0, CV_STORAGE_WRITE );
        nnetwork.write(storage,"OCR");
        cvReleaseFileStorage(&storage);

Now, my model is stored in C:/example/myModel.xml When I want to use ANN classifier, I use the following codes in C++:

CvANN_MLP nnetwork;

CvFileStorage* storage = cvOpenFileStorage("C:\\example\\myModel.xml", 0, CV_STORAGE_READ );
CvFileNode *n = cvGetFileNodeByName(storage,0,"OCR");
nnetwork.read(storage,n);
cvReleaseFileStorage(&storage);

Now I can use nnetwork.predict() and classify my characters. My question is here, I want to have the same classifier in Android. However, I don't know how to load the model in myModel.xml in Android. I am using opencv 3.0.0 and I cant find the Java conterpart of CvFileStorage in Android opencv. I don't know how to use FileStorage in Java. Please help me with that.


回答1:


I found that there is no

CvFileStorage

support in opencv4android. However, you can do whatever you want if you leap through jni. I'm using Android Studio and I had a tough time to find the solution.

There is a nearly complicated procedure to link jni with opencv to android. I discuss the whole procedure as below:

Step 1. Create a new class in your android project. Call it linkToNative. add the native method which reads a string from jni.

package com.example.yourname.yourproject;

public class linkToNative {

    public native String compare(long src,long dest);

    static {
        System.loadLibrary("compare");
    }

}

One more thing, introduce your native module to the glradle.build in your app folder. Therefore, your gradle defaultConfig scope would be like this:

defaultConfig {
        applicationId "com.example.yourname.yourproject"
        minSdkVersion 10
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"

        ndk{
            moduleName 'compare'
                   }
    }

Step 2. Build your project

Step 3. Use javah to create your headers. To do so, in your terminal, navigate to [Your project root directory]/app/src/main and type:

javah -d jni -classpath [Your Android sdk root directory]/platforms/android-19/android.jar;../../build/intermediates/classes/debug com.example.yourname.yourproject.linkToNative
  • Note that if you import other packages to myClass.java, you will be required to add the corresponding java or jar file to the classpath search area. In the case of using opencv wrappers see THIS.

Step 4. In jni folder created by javah, you should make your cpp[I strongly recommend cpp] file. I create a simple one as below:

#include <com.example.yourname.yourproject.linkToNative.h>

JNIEXPORT jstring JNICALL Java_com_example_yourname_yourproject_linkToNative_compare
(JNIEnv *env, jobject obj, jlong src, jlong dest){
return env->NewStringUTF("hello, I'm jni");
}

Go to the newly-created jni folder and create two files called Android.mk and Application.mk as below:

Android.mk

LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)


    OPENCVROOT:= [PATH/TO/Your/Opencv4android/Directory]
    OPENCV_CAMERA_MODULES:=off
    OPENCV_INSTALL_MODULES:=on
    OPENCV_LIB_TYPE:=SHARED
    LOCAL_C_INCLUDE := ${OPENCVROOT}/sdk/native/jni/include/
    include ${OPENCVROOT}/sdk/native/jni/OpenCV.mk
    LOCAL_LDLIBS += -llog -lstdc++ -lz
    LOCAL_MODULE    := compare
    LOCAL_SRC_FILES := compare.cpp
    include $(BUILD_SHARED_LIBRARY)

Application.mk

APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-19

Now you can cross-compile your native code using ndk-build. You should have downloaded NDK and extracted it beforehand. Then, go to your terminal, navigate to app folder and write down below code:

[YOUR NDK FOLDER]\ndk-build.cmd NDK_PROJECT_PATH=build/intermediates/ndk NDK_LIBS_OUT=src/main/jniLibs APP_BUILD_SCRIPT=src/main/jni/Android.mk  NDK_APPLICATION_MK=src/main/jni/Application.mk

Note that if you are on linux or mac platforms, drop .cmd out of the above command. Wait for the code to compile and run your project. Now, you can run the code in java. Every time you change your cpp file, you should compile the jni codes as mentioned above. If you want to get rid of this, as gradle to do that by defining a task within it. A good tutorial to do that is provided HERE.

Calling StatModel in opencv3

StatModel is changed a bit in opencv3. This is the code that loads the model and predicts a class according to testClass. Beforehand, include the following libraries in your cpp file.

#include <opencv/cv.h>
#include "opencv2/opencv.hpp"
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/objdetect/objdetect.hpp"
#include <opencv2/ml/ml.hpp>

Now, this is the rest of the code.

#define CLASSES 10
using namespace cv;
using namespace cv::ml;

JNIEXPORT jstring JNICALL Java_com_example_yourname_yourproject_linkToNative_compare
  (JNIEnv *env, jobject obj, jlong addrGray , jlong dest){
  Mat* srcMat = (Mat*) src;
  Mat* destMat = (Mat*) dest;
  Mat ref = pMatYr->clone();
  Ptr<ANN_MLP> model=StatModel::load<ANN_MLP>("/storage/emulated/0/ALPR/param.xml");
  cv::Mat outputArray(1,CLASSES,CV_8U);
  //
  Your code that creates testClass according to srcMat 
  .
  .
  //
  model->predict(testClass,outputArray)

  return env->NewStringUTF("YOUR MSG!");
  }

For more information about STatModel, read documentation page.



来源:https://stackoverflow.com/questions/34246265/opencv-ann-mlp-training-in-android

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!