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.
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.
User contributions licensed under CC BY-SA 3.0