Using CvSVM (openCV) in Android Native, "Fatal signal 11"

0

I am developing an app that uses a SVM to classify a color in an image. I am doing this in Android using the OpenCV Native library (JNI). When the app starts, right after loading the libraries, I call a native method to load the SVM from a file and store it in a global variable.

If I use svm.predict(data) right after I loaded the SVM, all is well. However, I will call a native method GetColor(frame) to process each frame I get from the CameraBridgeViewBase. When I call svm.predict(data) in that method, I get a Fatal Signal 11 (SIGSEGV) at 0x00000011 (sometimes at 0xdeadbaad) error.

I can output the data and the SVM parameters correctly, so both objects are not null (and have the correct contents). A simplified version of my code is below:

In CameraActivity (my activity):

private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
   @Override
   public void onManagerConnected(int status) {
      switch (status) {
        case LoaderCallbackInterface.SUCCESS:
        {
            Log.i(TAG, "OpenCV loaded successfully");

            // Load native library after(!) OpenCV initialization
            System.loadLibrary("mcr2_lib");

            try{ //init native code
                String path = LoadSVMs(); //here the location of SVMs are looked up
                if( path != null) 
                    InitSVMs(path); //this is the native method call
                Log.i(TAG, "Initiation done successfully");
            }
            catch(UnsatisfiedLinkError e){
                Log.e("cAMACT ", e.getLocalizedMessage());
                e.printStackTrace();
                Log.w("stacktrace", Log.getStackTraceString(e));
                finish();
            }                   
            mOpenCvCameraView.enableView();
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
};
...
public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    mRgba = inputFrame.rgba();     
    processColor(inputFrame.rgba());
    return mRgba;
}

The native part:

JNIEXPORT void JNICALL Java_com_my_CameraActivity_InitSVMs(JNIEnv* env, jobject obj, jstring pathToRes){
    std::string path = ConvertJString(env, pathToRes);
    __android_log_print(ANDROID_LOG_INFO, "InitSVM ", "Searching in directory %s", path.c_str());

    readSVMFromFile(path.c_str(), "svm_color", svm);
    __android_log_print(ANDROID_LOG_INFO, "InitSVM", "Loaded color");

    int count = svm.get_support_vector_count();
    __android_log_print(ANDROID_LOG_DEBUG, "InitSVM", "Loading SVM successfull with %d vectors", count);

     //I can use svm.predict here
}

void readSVMFromFile(const char* filepath, const char* filename,  CvSVM& svm)
{
    std::string fileLocation(filepath);
    fileLocation.append("/");
    fileLocation.append(filename);

   __android_log_print(ANDROID_LOG_DEBUG, "CardRecogn", "Loading SVM at %s",fileLocation.c_str());

    svm.load(  fileLocation.c_str()); //openCv code
    int count = svm.get_support_vector_count();
    __android_log_print(ANDROID_LOG_DEBUG, "CardRecogn", "Loading SVM successfull at %s with %d vectors",fileLocation.c_str(), count);

    //I can use svm.predict here
}

//on process frame
Scalar recognizeColorOfCardSVM(Mat& img){
    Vec3b white = img.at<Vec3b>(0,0);//get 'white' pixel for comparison
    Scalar meanblob = mean(blob);
    __android_log_print(ANDROID_LOG_INFO, "ColorRecogn", "%f %f %f",
                meanblob[0], meanblob[1],meanblob[2]);
    float* inputs;
    inputs = new float[6];
    inputs[0] = meanblob[0];
    inputs[1] = meanblob[1];
    inputs[2] = meanblob[2];
    inputs[3] = white[0];
    inputs[4] = white[1];
    inputs[5] = white[2];
    __android_log_print(ANDROID_LOG_INFO, "ColorRecogn", "input: %.1f %.1f %.1f %.1f %.1f %.1f", inputs[0],inputs[1],inputs[2],inputs[3],inputs[4],inputs[5]);

    //predict needs a Mat instead of float[]
    Mat inMat(1,6, CV_32FC1, inputs);

    //check to see svm is inited correctly
    int count = svm.get_support_vector_count();
    __android_log_print(ANDROID_LOG_DEBUG, "ColorRecogn", "Loading SVM successfull with %d vectors", count);

    //if I do this the code works
    //std::string fileLocation = "/data/data/com.my/files/svm_color";
    //svm.load(  fileLocation.c_str());

    //params are loaded correctly
    CvSVMParams p = svm.get_params();
    //crash is here!    
    float pColor=svm.predict( inMat);
    __android_log_print(ANDROID_LOG_DEBUG, "ColorRecogn", "Color %f", pColor);

    Scalar c= (0,0,0,0);
    c[pColor] = 255.0;
    return c;
}

I trained the SVM in a C++ only programm, and I can load the files there without any problems.

Below is the LogCat output of the error:

12-13 09:17:19.532: D/CameraBridge(18125): mStretch value: 1.5625
12-13 09:17:19.532: D/FpsMeter(18125): 14,29 FPS@352x288
12-13 09:17:19.542: D/JavaCameraView(18125): Preview Frame received. Frame size: 152064
12-13 09:17:19.557: I/ColorRecogn(18125): input: 138.9 138.9 138.9 215.0 215.0 215.0
12-13 09:17:19.562: D/ColorRecogn(18125): Loading SVM successfull with 1 vectors
12-13 09:17:19.562: A/libc(18125): Fatal signal 11 (SIGSEGV) at 0x00000011 (code=1), thread 18171 (Thread-19130)

Thanks.

android
c++
opencv
java-native-interface
native
asked on Stack Overflow Dec 13, 2013 by user1800312 • edited Dec 13, 2013 by Mahm00d

1 Answer

0

Okay, I found the problem. It was unrelated to the snippets I posted online. I had an extra function storeSVM( CvSVM svm), which was deprecated but still called (it basically did nothing anymore). Once I removed the call my code works.

answered on Stack Overflow Dec 13, 2013 by user1800312

User contributions licensed under CC BY-SA 3.0