在Android Native中使用CvSVM(openCV),“致命信号11”

时间:2013-12-13 08:42:41

标签: android c++ opencv java-native-interface native

我正在开发一个使用SVM对图像中的颜色进行分类的应用程序。我在Android中使用OpenCV Native库(JNI)执行此操作。当应用程序启动时,在加载库之后,我调用一个本机方法从文件加载SVM并将其存储在全局变量中。

如果我在加载SVM后立即使用svm.predict(data),一切都很顺利。但是,我将调用本机方法GetColor(frame)来处理从CameraBridgeViewBase获得的每个帧。当我在该方法中调用svm.predict(data)时,我得到Fatal Signal 11 (SIGSEGV) at 0x00000011(有时为0xdeadbaad)错误。

我可以正确输出数据和SVM参数,因此两个对象都不为空(并且具有正确的内容)。我的代码的简化版本如下:

CameraActivity(我的活动)中:

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;
}

原生部分:

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;
}

我在仅限C ++的程序中训练SVM,我可以毫无问题地加载文件。

以下是错误的LogCat输出:

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)

感谢。

1 个答案:

答案 0 :(得分:0)

好的,我发现了问题。这与我在网上发布的片段无关。我有一个额外的函数storeSVM( CvSVM svm),它被弃用但仍被调用(它基本上什么也没做)。一旦我删除了呼叫,我的代码就可以运行。