Skip to content

Instantly share code, notes, and snippets.

@tcw165
Last active May 14, 2017 03:58
Show Gist options
  • Save tcw165/4930595a8cd31c136a4e163fdbac7162 to your computer and use it in GitHub Desktop.
Save tcw165/4930595a8cd31c136a4e163fdbac7162 to your computer and use it in GitHub Desktop.
extern "C" JNIEXPORT jbyteArray JNICALL
JNI_METHOD(detectFacesAndLandmarks)(JNIEnv *env,
jobject thiz,
jobject bitmap) {
if (sFaceDetector.num_detectors() == 0) {
LOGI("L%d: sFaceDetector is not initialized!", __LINE__);
throwException(env, "sFaceDetector is not initialized!");
return NULL;
}
if (sFaceLandmarksDetector.num_parts() == 0) {
LOGI("L%d: sFaceLandmarksDetector is not initialized!", __LINE__);
throwException(env, "sFaceLandmarksDetector is not initialized!");
return NULL;
}
// Profiler.
Profiler profiler;
profiler.start();
// Convert bitmap to dlib::array2d.
dlib::array2d<dlib::rgb_pixel> img;
convertBitmapToArray2d(env, bitmap, img);
double interval = profiler.stopAndGetInterval();
const float width = (float) img.nc();
const float height = (float) img.nr();
LOGI("L%d: input image (w=%f, h=%f) is read (took %.3f ms)",
__LINE__, width, height, interval);
profiler.start();
// Now tell the face detector to give us a list of bounding boxes
// around all the faces in the image.
std::vector<dlib::rectangle> dets = sFaceDetector(img);
interval = profiler.stopAndGetInterval();
LOGI("L%d: Number of faces detected: %u (took %.3f ms)",
__LINE__, (unsigned int) dets.size(), interval);
// Protobuf message.
FaceList faces;
// Now we will go ask the shape_predictor to tell us the pose of
// each face we detected.
for (unsigned long j = 0; j < dets.size(); ++j) {
profiler.start();
dlib::full_object_detection shape = sFaceLandmarksDetector(img, dets[j]);
interval = profiler.stopAndGetInterval();
LOGI("L%d: #%lu face, %lu landmarks detected (took %.3f ms)",
__LINE__, j, shape.num_parts(), interval);
profiler.start();
// To protobuf message.
Face* face = faces.add_faces();
// Transfer face boundary.
Rectangle* bound = face->mutable_bound();
bound->set_left((float) dets[j].left() / width);
bound->set_top((float) dets[j].top() / height);
bound->set_right((float) dets[j].right() / width);
bound->set_bottom((float) dets[j].bottom() / height);
// Transfer face landmarks.
for (u_long i = 0 ; i < shape.num_parts(); ++i) {
dlib::point& pt = shape.part(i);
Landmark* landmark = face->add_landmarks();
landmark->set_x((float) pt.x() / width);
landmark->set_y((float) pt.y() / height);
}
interval = profiler.stopAndGetInterval();
LOGI("L%d: Convert #%lu face to protobuf message (took %.3f ms)",
__LINE__, j, interval);
}
profiler.start();
// Prepare the return message.
int outSize = faces.ByteSize();
jbyteArray out = env->NewByteArray(outSize);
jbyte* buffer = new jbyte[outSize];
faces.SerializeToArray(buffer, outSize);
env->SetByteArrayRegion(out, 0, outSize, buffer);
delete[] buffer;
interval = profiler.stopAndGetInterval();
LOGI("L%d: Convert faces to protobuf message (took %.3f ms)",
__LINE__, interval);
return out;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment