在Android原生C++中使用Facemark opencv contrib

Using Facemark opencv contrib in android native C++

本文关键字:Facemark opencv contrib Android 原生 C++      更新时间:2023-10-16

我是opencv的新手,我正在尝试在我的Android原生C++应用程序中的opencv contrib模块中使用Facemark。但是,我收到错误

A/libc:致命信号 11 (SIGSEGV(,代码 1,TID 中的故障地址0x1788 21567(my_app(

使用 创建面标实例时

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

获取级联方法

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

任何知道我做错了什么或更好的方法在安卓原生的opencv contrib模块中使用Facemark的人

到目前为止,我看到的每个教程都以不同的方式实现了此方法,为了解决这个问题,我将介绍适合我的方法。

首先声明facemark,以下方法返回SIGSEGV错误:

Ptr<Facemark> facemark = FacemarkLBF::create();

而是使用:

Ptr<Facemark> facemark = createFacemarkLBF();

其次,我看到很多教程使用:

facemark->load(filename);

但正确的语法是:

facemark->loadModel(filename);

如果您仍然遇到相同的问题,请点击此链接并下载链接,并使用 contrib 获取最新的 SDK:

https://pullrequest.opencv.org/buildbot/export/opencv_releases/