android dlib 人脸检测使用
一、编译阶段
1、在cmakelist.txt中加入:
include(src/main/cpp/dlib/cmake)
然后再链接dlib库就可以了:
target_link_libraries( # Specifies the target library.
native-lib
dlib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
2、可能出现的错误
Android NDK 编译器默认不支持 C++ 异常控制导致。
Error:(124, 17) error: cannot use 'throw' with exceptions disabled
Error:(119, 21) error: cannot use typeid with -fno-rtti
在build.gradle中加入cpp编译选项:
cppFlags "-fexceptions"
cppFlags "-frtti"
最后build文件如下:
compileSdkVersion 24
buildToolsVersion "24.0.1"
defaultConfig {
applicationId "image.imageapp"
minSdkVersion 19
targetSdkVersion 24
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags "-std=c++11"
cppFlags "-fexceptions"
cppFlags "-frtti"
}
}
}
4、找不到opencv.cmake
SET(OpenCV_INCLUDE_DIRS "/usr/include")
SET(OpenCV_LIB_DIR "/usr/lib")
INCLUDE_DIRECTORIES(${OpenCV_INCLUDE_DIRS})
二、NDK使用、Dlib调用
1、dlib接口调用
#include <jni.h>
#include <string>
#include <vector>
#include <iostream>
#include "face_detection/dlib/image_io.h"
#include "face_detection/dlib/image_processing.h"
#include "face_detection/dlib/image_processing/frontal_face_detector.h"
#include <ctime>
dlib::frontal_face_detector m_facedetector=dlib::get_frontal_face_detector();
//获取人脸框
std::vector<int > getfacerect(const std::vector<int>img,int height,int width)
{
dlib::array2d<unsigned char>image;
image.set_size(height,width);
for (int i = 0; i < height; i++)
{
for(int j=0;j<width;j++)
{
int clr = img[i*width+j];
int red = (clr & 0x00ff0000) >> 16; // 取高两位
int green = (clr & 0x0000ff00) >> 8; // 取中两位
int blue = clr & 0x000000ff; // 取低两位
unsigned char gray=red*0.299+green*0.587+blue*0.114;
//dlib::rgb_pixel pt(red,green,blue);
image[i][j]=gray;
}
}
clock_t begin = clock();
std::vector<dlib::rectangle> dets= m_facedetector(image);
std::vector<int >rect;
if (!dets.empty())
{
rect.push_back(dets[0].left());
rect.push_back(dets[0].top());
rect.push_back(dets[0].width());
rect.push_back(dets[0].height());
}
return rect;
}
extern "C" jintArray Java_image_imageapp_MainActivity_stringFromJNI(JNIEnv *env, jobject /* this */
,jintArray image_data,jint image_height,jint image_widht)
{
//const char* cha = env->GetStringUTFChars(imagepath, nullptr);
// char* 转 string
// std::string image_str(cha);
// if(cha == NULL) {
//return NULL;
// }
//jstring rtstr = env->NewStringUTF(image_str.c_str());//env->NewStringUTF(hello.c_str());
// return rtstr;
std::vector<int>image_datacpp(image_height*image_widht);
jsize len = env->GetArrayLength(image_data);
jint *body = env->GetIntArrayElements(image_data, 0);
for (jsize i=0;i<len;i++){
image_datacpp[i]=(int)body[i];
}
std::vector<int>rect=getfacerect(image_datacpp,image_height,image_widht);
jintArray result =env->NewIntArray(4);
env->SetIntArrayRegion(result, 0, 4, &rect[0]);
return result;
}
2、MainActivity.JAVA中调用库函数:
private int[] face_detection(Bitmap origin_image){
float scale = 240.f/ Math.max(origin_image.getHeight(), origin_image.getWidth());
int width = (int)(origin_image.getWidth()*scale);
int height = (int)(origin_image.getHeight()*scale);
Bitmap resize_image=Bitmap.createScaledBitmap(origin_image,width,height , false);
// 保存所有的像素的数组,图片宽×高
int[] pixels = new int[width * height];
resize_image.getPixels(pixels, 0, width, 0, 0, width, height);
int[] rect=stringFromJNI(pixels,height,width);
int[] result_rect=new int[4];
result_rect[0]=(int)(rect[0]/scale);
result_rect[1]=(int)(rect[1]/scale);
result_rect[2]=(int)(rect[2]/scale);
result_rect[3]=(int)(rect[3]/scale);
result_rect[2]=result_rect[2]+result_rect[0];
result_rect[3]=result_rect[3]+result_rect[1];
return result_rect;
}
3、显示绘制结果
int[] rect=face_detection(scaled);
Canvas canvas=new Canvas(scaled);
Paint p=new Paint();
p.setColor(Color.RED);
p.setStrokeWidth(3.0f);
canvas.drawLine(rect[0], rect[1], rect[2], rect[1], p);//up
canvas.drawLine(rect[0], rect[1], rect[0], rect[3], p);//left
canvas.drawLine(rect[0], rect[3], rect[2], rect[3], p);//down
canvas.drawLine(rect[2], rect[1], rect[2], rect[3], p);
//cnvs.drawRect(rectangle,paint);
imageView.setImageBitmap(scaled);