Last active
May 14, 2017 03:58
-
-
Save tcw165/4930595a8cd31c136a4e163fdbac7162 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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