我正在开发一个使用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)
感谢。
答案 0 :(得分:0)
好的,我发现了问题。这与我在网上发布的片段无关。我有一个额外的函数storeSVM( CvSVM svm)
,它被弃用但仍被调用(它基本上什么也没做)。一旦我删除了呼叫,我的代码就可以运行。