【发布时间】:2018-10-18 09:37:00
【问题描述】:
我是 opencv 新手,我正在尝试在我的 android 本机 C++ 应用程序的 opencv contrib 模块中使用 Facemark。但是,我得到了错误
A/libc:致命信号 11 (SIGSEGV),代码 1,tid 中的故障地址 0x1788 21567(my_app)
使用创建 Facemark 实例时
Ptr<Facemark> facemark = FacemarkLBF::create();
我正在使用https://github.com/chaoyangnz/opencv3-android-sdk-with-contrib opencv 库
这是我的实现
c++
void
Java_com_makeover_makeover_1opencv_MainActivity_nativeDetectFaceLandmarks(
JNIEnv *env,
jobject , jlong srcAddr, jlong retAddr,
jstring faceCascadePath, jstring faceYamlPath)
{
const char *faceCascadeFile = env->GetStringUTFChars(faceCascadePath,NULL);
const char *yamlFile = env->GetStringUTFChars(faceYamlPath,NULL);
LOGI("nativeDetectFace called");
string cascadePath(faceCascadeFile);
LOGI("nativeDetectFace called");
string yamlPath(yamlFile);
Mat& colorMat = *(Mat*)srcAddr;
Mat& retValMat = *(Mat*)retAddr;
Mat gray;
// Load Face Detector
CascadeClassifier faceDetector(cascadePath);
LOGI("cascade file loaded");
// Create an instance of Facemark
Ptr<Facemark> facemark = FacemarkLBF::create();
LOGI("face instance created");
// Load landmark detector
facemark->loadModel(yamlPath);
LOGI("yalm model loaded");
// Find face
vector<Rect> faces;
// Convert frame to grayscale because
// faceDetector requires grayscale image.
cvtColor(colorMat, gray, COLOR_BGR2GRAY);
// Detect faces
faceDetector.detectMultiScale(gray, faces);
// Variable for landmarks.
// Landmarks for one face is a vector of points
// There can be more than one face in the image. Hence, we
// use a vector of vector of points.
vector< vector<Point2f> > landmarks;
// Run landmark detector
bool success = facemark->fit(colorMat,faces,landmarks);
if(success)
{
// If successful, render the landmarks on the face
for(int i = 0; i < landmarks.size(); i++)
{
drawLandmarks(colorMat, landmarks[i]);
}
}
}
java实现
drawFaces.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Mat colorMat,grayMat;
colorMat = new Mat();
grayMat = new Mat();
Utils.bitmapToMat(bmp,colorMat);
nativeDetectFaceLandmarks(colorMat.getNativeObjAddr(), grayMat.getNativeObjAddr(),
getCascade("face"),getCascade("yaml"));
Bitmap new_bmp2 = Bitmap.createBitmap(bmp);
Utils.matToBitmap(colorMat,new_bmp2);
img_face.setImageBitmap(new_bmp2);
}
});
getCascade 方法
public String getCascade(String cascadeType){
String fileName;
File mCascadeFile;
final InputStream is;
FileOutputStream os;
switch (cascadeType){
case "mouth":
fileName="haarcascade_mcs_mouth.xml";
break;
case "face":
fileName = "haarcascade_frontalface_alt2.xml";
break;
case "right_eye":
fileName = "haarcascade_mcs_righteye.xml";
break;
case "yaml":
fileName = "lbfmodel.yaml";
break;
case "left_eye":
fileName = "haarcascade_mcs_lefteye.xml";
break;
default:
fileName = null;
}
if(fileName==null) {
return null;
}
try {
is = getResources().getAssets().open(fileName);
File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir,fileName);
os = new FileOutputStream(mCascadeFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
is.close();
os.close();
Log.i("TAG", "getCascade: face cascade found");
return mCascadeFile.getAbsolutePath();
} catch (IOException e) {
Log.e("TAG", "face cascade not found", e);
return null;
}
}
任何知道我做错了什么或在android native的opencv contrib模块中使用Facemark的更好方法的人
【问题讨论】:
-
崩溃后的堆栈跟踪是什么? source.android.com/devices/tech/debug
-
link 这是我的堆栈跟踪
-
从堆栈跟踪中,
SIGSEGV发生在je_free()中。你几乎可以肯定在某处破坏了你的堆。您是否在检查每个 JNI 调用的返回值?你怎么知道srcAddr和retAddr中的地址是正确的? -
可能不相关,但在从输入流读取时尝试传递数组大小:
while ((bytesRead = is.read(buffer, 4096)) != -1)否则您可能会溢出数组
标签: android c++ opencv java-native-interface