Hi, I've created a new function in the jni_face_detect that takes the camera preview as raw bytes, the face box coordinates computed with Android API and I just need to detect the landmarks of one single face with dlib (I want to skip the face detection phase).
The raw bytes are converted from YUV to grayscale and then rotated, scaled and flipped according to my UI TextureView size.
The landmarks are identified in a very little time but once displayed on the device screen they're very flickery even if the face is still and the face box coordinates remain the same, there's always a "micro" variation in the landmarks coordinates. This doesn't happen using the function jniBitmapDetect provided with the original .cpp file, that uses, instead, bitmaps. In that case, the landmarks are always very stable. I guess I'm messing something up during the conversions or maybe I'm not passing the right pointers...
JNIEXPORT jobject JNICALL DLIB_FACE_JNI_METHOD(jniNewLandmarksDetection)(JNIEnv* env, jobject thiz, jbyteArray rawBytes, jfloatArray rect, jint width, jint height, jint widthB, jint heightB, jint rotation, jint scale) {
jobject jDetRet = JNI_VisionDetRet::createJObject(env);
g_pJNI_VisionDetRet->setLabel(env, jDetRet, "face");
jbyte* b_data = (env)->GetByteArrayElements(rawBytes, 0);
cv::Mat yuvMat = cv::Mat(height+height/2, width, CV_8UC1, (unsigned char*)b_data);
cv::Mat grayMat = cv::Mat(height, width, CV_8UC1);
cv::cvtColor(yuvMat, grayMat, CV_YUV2GRAY_NV21);
cv::Mat scaledGrayscale;
cv::resize(grayMat, scaledGrayscale, Size(heightB/scale,widthB/scale), 0, 0, INTER_LINEAR);
cv::flip(scaledGrayscale,scaledGrayscale,0);
jfloat* r = env->GetFloatArrayElements(rect,0);
dlib::rectangle rec(r[3], r[0], r[1], r[2]);
g_pJNI_VisionDetRet->setRect(env, jDetRet, r[3], r[0], r[1], r[2]);
DetectorPtr detPtr = getDetectorPtr(env, thiz);
dlib::cv_image<unsigned char> img(scaledGrayscale);
dlib::full_object_detection shape = detPtr->msp(img, rec);
for (int k=0; k<shape.num_parts(); k++) {
int x = shape.part(k).x();
int y = shape.part(k).y();
g_pJNI_VisionDetRet->addLandmark(env, jDetRet, x, y);
}
//Test, these two pics look good and they're identical
dlib::save_bmp(img,"/mnt/sdcard/DCIM/input.bmp");
cv::imwrite("/mnt/sdcard/DCIM/det.jpg", scaledGrayscale);
return jDetRet;
}`