SHARED
hxgopencv-lib.cpp)
find_library( # Sets the name of the path variable.
log-lib
log)
target_link_libraries( # Specifies the target library.
hxgopencv-lib
opencv_java3
#加入该依赖库 undefined reference to `AndroidBitmap_getInfo’
jnigraphics
${log-lib})
/**
*/
private void copyCaseCadeFile() {
try {
// load cascade file from application resources
InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
File cascadeDir = getDir(“cascade”, Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir, “lbpcascade_frontalface.xml”);
if (mCascadeFile.exists()) return;
FileOutputStream 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();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
加载人脸识别的分类器文件
@param filePath
*/
public native void loadCascade(String filePath);
#include
#include
#include “opencv2/opencv.hpp”
#include “android/bitmap.h”
#include “android/log.h”
//使用命名空间
using namespace cv;
using namespace dnn;
/**
*/
CascadeClassifier cascadeClassifier;
extern “C”
JNIEXPORT void JNICALL
Java_com_hxg_ndkface_FaceDetection_loadCascade(JNIEnv *env, jobject instance, jstring file_path) {
const char *filePath = env->GetStringUTFChars(file_path, 0);
cascadeClassifier.load(filePath);
__android_log_print(ANDROID_LOG_INFO, “TTTTT”, “%s”, “分类器文件加载成功”);
env->ReleaseStringUTFChars(file_path, filePath);
}
/**
*/
extern “C”
JNIEXPORT jboolean JNICALL
Java_com_hxg_ndkface_FaceDetection_faceDetection(JNIEnv *env, jobject thiz, jobject bitmap) {
//检测人脸,opencv 有个关键类 是Mat open只会处理Mat android里面是Bitmap
//1.Bitmap转成opencv能操作的C++对象Mat
Mat mat;
bitmap2Mat(env, mat, bitmap);
//处理灰度图,提高效率
Mat gray_mat;
__android_log_print(ANDROID_LOG_INFO, “TTTTT”, “%s”, “处理灰度图”);
cvtColor(mat, gray_mat, COLOR_BGRA2GRAY);
__android_log_print(ANDROID_LOG_INFO, “TTTTT”, “%s”, “再次处理 直方均衡补偿”);
//再次处理 直方均衡补偿
Mat equalize_mat;
equalizeHist(gray_mat, equalize_mat);
//识别人脸,要加载人脸分类器文件
std::vector faces;
cascadeClassifier.detectMultiScale(equalize_mat, faces, 1.1, 3, CV_HAAR_SCALE_IMAGE,
Size(30, 30));
__android_log_print(ANDROID_LOG_INFO, “TTTTT”, “人脸个数:%d”, faces.size());
if (faces.size() == 1) {
return true;
}
return false;
}
/**
*/
extern “C”
JNIEXPORT jint JNICALL
Java_com_hxg_ndkface_FaceDetection_faceDetectionSaveInfo(JNIEnv *env, jobject instance,
jstring name,
jobject bitmap) {
const char *filePath = env->GetStringUTFChars(name, 0);
//检测人脸,opencv 有个关键类 是Mat open只会处理Mat android里面是Bitmap
//1.Bitmap转成opencv能操作的C++对象Mat
Mat mat;
bitmap2Mat(env, mat, bitmap);
//处理灰度图,提高效率
Mat gray_mat;
cvtColor(mat, gray_mat, COLOR_BGRA2GRAY);
//再次处理 直方均衡补偿
Mat equalize_mat;
equalizeHist(gray_mat, equalize_mat);
//识别人脸,要加载人脸分类器文件
std::vector faces;
cascadeClassifier.detectMultiScale(equalize_mat, faces, 1.1, 5, 0 | CV_HAAR_SCALE_IMAGE,
Size(160, 160));
__android_log_print(ANDROID_LOG_INFO, “TTTTT”, “人脸个数:%d”, faces.size());
if (faces.size() == 1) {
Rect faceRect = faces[0];
//在人脸部分画个图
rectangle(mat, faceRect, Scalar(255, 0, 0), 3);
__android_log_print(ANDROID_LOG_ERROR, “TTTTT”, “人脸个数:%s”, “在人脸部分画个图”);
//把mat我们又放到bitmap中
mat2Bitmap(env, mat, bitmap);
//保存人脸信息Mat,图片jpg
Mat saveMat = Mat(equalize_mat, faceRect);
//保存face_info_mat
imwrite(filePath, equalize_mat);
return 1;
}
env->ReleaseStringUTFChars(name, filePath);
return 0;
}
/**
*人脸对比
*/
extern “C”
JNIEXPORT jdouble JNICALL
Java_com_hxg_ndkface_FaceDetection_histogramMatch(JNIEnv *env, jobject instance, jobject bitmap1,
jobject bitmap2) {
//1.Bitmap转成opencv能操作的C++对象Mat
Mat mat, mat1;
bitmap2Mat(env, mat, bitmap1);
bitmap2Mat(env, mat1, bitmap2);
// 转灰度矩阵
cvtColor(mat, mat, COLOR_BGR2HSV);
cvtColor(mat1, mat1, COLOR_BGR2HSV);
int channels[] = {0, 1};
int histsize[] = {180, 255};
float r1[] = {0, 180};
float r2[] = {0, 255};
const float *ranges[] = {r1, r2};
Mat hist1, hist2;
calcHist(&mat, 3, channels, Mat(), hist1, 2, histsize, ranges, true);
//https://www.cnblogs.com/bjxqmy/p/12292421.html
normalize(hist1, hist1, 1, 0, NORM_L1);
calcHist(&mat1, 3, channels, Mat(), hist2, 2, histsize, ranges, true);
normalize(hist2, hist2, 1, 0, NORM_L1);
double similarity = compareHist(hist1, hist2, HISTCMP_CORREL);
__android_log_print(ANDROID_LOG_ERROR, “TTTTT”, “相识度:%f”, similarity);
return similarity;
}
private void copyCaseCadeFilePbtxt() {
InputStream is = null;
FileOutputStream os = null;
try {
// load cascade file from application resources
is = getResources().openRawResource(R.raw.opencv_face_detector);
File cascadeDir = getDir(“cascade”, Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir, “opencv_face_detector.pbtxt”);
if (mCascadeFile.exists()) return;
os = new FileOutputStream(mCascadeFile);
byte[] buffer = new byte[1024 * 1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void copyCaseCadeFileUint8() {
InputStream is = null;
FileOutputStream os = null;
try {
// load cascade file from application resources
is = getResources().openRawResource(R.raw.opencv_face_detector_uint8);
File cascadeDir = getDir(“cascade”, Context.MODE_PRIVATE);
mCascadeFile = new File(cascadeDir, “opencv_face_detector_uint8.pb”);
if (mCascadeFile.exists()) return;
os = new FileOutputStream(mCascadeFile);
byte[] buffer = new byte[1024 * 1024];
int bytesRead;
while ((bytesRead = is.read(buffer)) != -1) {
os.write(buffer, 0, bytesRead);
}
is.close();
os.close();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (is != null) {
is.close();
}
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
*Dnn模式的人脸识别,并抠图
*/
extern “C”
JNIEXPORT jboolean JNICALL
Java_com_hxg_ndkface_FaceDetection_faceDnnDetection(JNIEnv *env, jobject instance,
jstring model_binary,
jstring model_desc,
jstring checkPath,
jstring resultPath) {
const char *model_binary_path = env->GetStringUTFChars(model_binary, 0);
const char *model_desc_path = env->GetStringUTFChars(model_desc, 0);
const char *check_path = env->GetStringUTFChars(checkPath, 0);
const char *result_path = env->GetStringUTFChars(resultPath, 0);
Net net = readNetFromTensorflow(model_binary_path, model_desc_path);
net.setPreferableBackend(DNN_BACKEND_OPENCV);
net.setPreferableTarget(DNN_TARGET_CPU);
if (net.empty()) {
__android_log_print(ANDROID_LOG_ERROR, “TTTTT”, “%s”, “could not load net…”);
return false;
}
Mat frame = imread(check_path); //读入检测文件
__android_log_print(ANDROID_LOG_ERROR, “TTTTT”, “%s”, “输入数据调整”);
// 输入数据调整
Mat inputBlob = blobFromImage(frame, 1.0,
Size(300, 300), Scalar(104.0, 177.0, 123.0), false, false);
net.setInput(inputBlob, “data”);
// 人脸检测
Mat detection = net.forward(“detection_out”);
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr());
Mat face_area;
for (int i = 0; i < detectionMat.rows; i++) {
// 置信度 0~1之间
float confidence = detectionMat.at(i, 2);
if (confidence > 0.7) {
//count++;
int xLeftBottom = static_cast(detectionMat.at(i, 3) * frame.cols);
int yLeftBottom = static_cast(detectionMat.at(i, 4) * frame.rows);
int xRightTop = static_cast(detectionMat.at(i, 5) * frame.cols);
int yRightTop = static_cast(detectionMat.at(i, 6) * frame.rows);
Rect object((int) xLeftBottom, (int) yLeftBottom,
(int) (xRightTop - xLeftBottom),
(int) (yRightTop - yLeftBottom));
face_area = frame(object); //扣出图片
rectangle(frame, object, Scalar(0, 255, 0)); //画框
}
}
imwrite(result_path, face_area); //写出文件
env->ReleaseStringUTFChars(model_binary, model_binary_path);
env->ReleaseStringUTFChars(model_desc, model_desc_path);
env->ReleaseStringUTFChars(checkPath, check_path);
env->ReleaseStringUTFChars(resultPath, result_path);
return true;
}
/**
Bitmap转成opencv能操作的C++对象Mat
@param env
@param mat
@param bitmap
*/
void bitmap2Mat(JNIEnv *env, Mat &mat, jobject bitmap) {
//Mat 里面有个type :CV_8UC4刚好对上我们的Bitmap中的ARGB_8888 , CV_8UC2对应Bitmap中的RGB_555
//获取 bitmap 信息
AndroidBitmapInfo info;
void *pixels;
try {
// AndroidBitmap_getInfo(env, bitmap, &info);
//锁定Bitmap画布
// AndroidBitmap_lockPixels(env, bitmap, &pixels);
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
//指定mat的宽高type BGRA
mat.create(info.height, info.width, CV_8UC4);
if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
//对应mat应该是CV_8UC4
Mat temp(info.height, info.width, CV_8UC4, pixels);
//把数据temp复制到mat里面
temp.copyTo(mat);
} else if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
//对应mat应该是CV_8UC2
Mat temp(info.height, info.width, CV_8UC2, pixels);
//mat 是CV_8UC4 ,CV_8UC2 > CV_8UC4
cvtColor(temp, mat, COLOR_BGR5652BGRA);
}
//解锁Bitmap画布
AndroidBitmap_unlockPixels(env, bitmap);
return;
} catch (Exception &e) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass(“java/lang/Exception”);
env->ThrowNew(je, e.what());
return;
} catch (…) {
AndroidBitmap_unlockPixels(env, bitmap);
jclass je = env->FindClass(“java/lang/Exception”);
env->ThrowNew(je, “Unknown exception in JNI code {nBitmapToMat}”);
return;
}
}
/**
把mat转成bitmap
@param env
@param mat
@param bitmap
*/
void mat2Bitmap(JNIEnv *env, Mat mat, jobject bitmap) {
//Mat 里面有个type :CV_8UC4刚好对上我们的Bitmap中的ARGB_8888 , CV_8UC2对应Bitmap中的RGB_555
//获取 bitmap 信息
AndroidBitmapInfo info;
void *pixels;
try {
// AndroidBitmap_getInfo(env, bitmap, &info);
由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记做整理一份资料。
需要的朋友可以**私信【学习】**我分享给你,希望里面的资料可以给你们一个更好的学习参考。
或者直接点击下面链接免费获取
Android学习PDF+架构视频+面试文档+源码笔记
Android学习的系统对应视频
Android进阶的系统对应学习资料
好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。
的RGB_555
//获取 bitmap 信息
AndroidBitmapInfo info;
void *pixels;
try {
// AndroidBitmap_getInfo(env, bitmap, &info);
由于篇幅问题,我呢也将自己当前所在技术领域的各项知识点、工具、框架等汇总成一份技术路线图,还有一些架构进阶视频、全套学习PDF文件、面试文档、源码笔记做整理一份资料。
需要的朋友可以**私信【学习】**我分享给你,希望里面的资料可以给你们一个更好的学习参考。
或者直接点击下面链接免费获取
Android学习PDF+架构视频+面试文档+源码笔记
[外链图片转存中…(img-jjgGZNOZ-1646381432128)]
[外链图片转存中…(img-IwjYnWOo-1646381432128)]
Android学习的系统对应视频
Android进阶的系统对应学习资料
[外链图片转存中…(img-ppNPN04X-1646381432129)]
[外链图片转存中…(img-PkOCIoCt-1646381432129)]
好了,以上便是今天的分享,希望为各位朋友后续的学习提供方便。觉得内容不错,也欢迎多多分享给身边的朋友哈。