1.下载

首先先去官网 https://opencv.org/opencv-3-2.html 下载 Android SDK: sourceforge ,下载下来以后我们的开发方式目前有两种:一种是基于 OpenCV_3.2.0_Manager.apk 的纯 Java 代码;还有一种方式是配置好 opencv 后利用 Android NDK,使用C++开发。

解压下载好的文件夹后

image.png

apk:OpenCV_3.2.0_Manager 可以说是一个服务 apk , 网上的所有代码都是基于 OpenCV_3.2.0_Manager,也就是说你必须运行这个 apk

samples:所有的与android相关的一些事例代码,基本全部都是 java 代码,封装了很多功能(图片转成灰度,高斯模糊,边缘检测),而且都是 Eclipse 版本,网上的例子(Java例子)

sdk:所有的资源,so库,头文件,源码(GitHub https://github.com/opencv/opencv)

2. 人脸识别实现的思路 (人脸登录)

2.1 人脸信息录入

2.1.1 获取相机的 Bitmap , 检测人脸(保证人脸特征信息比较精准)人脸要足够大,当前范围内人脸只能有一张人脸,比如:正常、眨眼睛、张嘴巴 (3张人脸信息)

2.1.2 获取到人脸必须要保存人脸特征信息,然后上传给后台(后台会再次做算法优化),保存到数据库

2.2 人脸的特征值的匹配

2.2.1 获取相机的 Bitmap , 检测人脸(保证人脸特征信息比较精准)人脸要足够大,当前范围内人脸只能有一张人脸,比如:正常、眨眼睛、张嘴巴 (3张人脸信息)

2.2.2 从后台去查询用户进行登录

3. 提取特征值和匹配人脸信息

思路:

整合 opencv

获取相机的 SurfaceView 传到 native 层去检测,或者不断的获取 SurfaceView 的 Bitmap,传到 Native 层

检测人脸,保存人脸特征信息在本地

上传到后台

4.灰度图算法:java 里面把一张图片转成灰度图?

RGB: 0-255,0-255,0-255 (彩色图)

灰度:R+G+B = 255 = 0.33R+0.33G+0.33B(一般) = 0.3R + 0.59G + 0.11B(适合人的眼睛)

灰度图所含有的信息量(取值范围 0-255)不高,而彩色图的取值范围比较高 (255 * 255 * 255)

5.实现人脸识别

下载完opencv后选择并添加到项目

image.png

首先修改CmakeLists.txt

# For more information about using CMake with Android Studio, read the

# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

#判断编译器类型,如果是gcc编译器,则在编译选项中加入c++11支持

if(CMAKE_COMPILER_IS_GNUCXX)

set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")

message(STATUS "optional:-std=c++11")

endif(CMAKE_COMPILER_IS_GNUCXX)

#需要引入我们头文件,以这个配置的目录为基准

include_directories(src/main/jniLibs/include)

# 添加依赖 opencv.so 库

set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../src/main/jniLibs)

add_library(

opencv_java3

SHARED

IMPORTED)

set_target_properties(

opencv_java3

PROPERTIES IMPORTED_LOCATION

../../../../src/main/jniLibs/armeabi/libopencv_java3.so)

# Creates and names a library, sets it as either STATIC

# or SHARED, and provides the relative paths to its source code.

# You can define multiple libraries, and CMake builds them for you.

# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.

native-lib

# Sets the library as a shared library.

SHARED

# Provides a relative path to your source file(s).

src/main/cpp/native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a

# variable. Because CMake includes system libraries in the search path by

# default, you only need to specify the name of the public NDK library

# you want to add. CMake verifies that the library exists before

# completing its build.

find_library( # Sets the name of the path variable.

log-lib

# Specifies the name of the NDK library that

# you want CMake to locate.

log )

# Specifies libraries CMake should link to your target library. You

# can link multiple libraries, such as libraries you define in this

# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.

native-lib opencv_java3

#加入该依赖库

jnigraphics

# Links the target library to the log library

# included in the NDK.

${log-lib} )

新建FaceDetection人脸识别类

public class FaceDetection {

static {

System.loadLibrary("native-lib");

}

/**

* 检测人脸并保存人脸信息

* @param faceBitmap

*/

public native void faceDetectionSaveInfo(Bitmap faceBitmap);

/**

* 加载人脸识别器

* @param filePath

*/

public native void loadCascade(String filePath);

}

MainActivity的使用

public class MainActivity extends AppCompatActivity {

private ImageView mFaceImageView;

private Bitmap mFaceBitmap;

private FaceDetection mFaceDetection;

private File mCascadeFile;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

mFaceImageView = findViewById(R.id.face_image);

mFaceBitmap= BitmapFactory.decodeResource(getResources(),R.drawable.face);

mFaceImageView.setImageBitmap(mFaceBitmap);

copyCascadeFile();

mFaceDetection=new FaceDetection();

//人脸识别

mFaceDetection.loadCascade(mCascadeFile.getAbsolutePath());

}

private void copyCascadeFile() {

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();

}

}

public void faceDetection(View view) {

//识别人脸,保存人脸

mFaceDetection.faceDetectionSaveInfo(mFaceBitmap);

}

}

native-lib实现功能

#include

#include

#include

#include

#include

#include

using namespace cv;

#define TAG "JNI_TAG"

#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)

extern "C" {

JNIEXPORT void JNICALL

Java_com_peakmain_ndk_FaceDetection_faceDetectionSaveInfo(JNIEnv *env, jobject instance,

jobject faceBitmap);

void bitmap2Mat(JNIEnv *pEnv, Mat &mat, jobject bitmap);

void mat2Bitmap(JNIEnv *env, Mat mat, jobject bitmap);

JNIEXPORT void JNICALL

Java_com_peakmain_ndk_FaceDetection_loadCascade(JNIEnv *env, jobject instance, jstring filePath);

}

//bitmap转成mat

void bitmap2Mat(JNIEnv *env, Mat &mat, jobject bitmap) {

//mat里面有个type CV_8UC4刚好是我们的bitmap中RGB_8888,CV_8UC2对应的是我们的bitmap中的RGB_565

//获取bitmap的信息

AndroidBitmapInfo info;

void* pixels;

AndroidBitmap_getInfo(env,bitmap,&info);

//锁定Bitmap

AndroidBitmap_lockPixels(env,bitmap,&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.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,

cvtColor(temp,mat, COLOR_BGR5652BGRA);

}

//其他的要自己去转

//解锁Bitmap画布

AndroidBitmap_unlockPixels(env,bitmap);

}

CascadeClassifier cascadeClassifier;

extern "C"

JNIEXPORT void JNICALL

Java_com_peakmain_ndk_FaceDetection_loadCascade(JNIEnv *env, jobject instance, jstring filePath_) {

const char *filePath = env->GetStringUTFChars(filePath_, 0);

cascadeClassifier.load(filePath);

LOGE("加载分类器文件成功");

env->ReleaseStringUTFChars(filePath_, filePath);

}

extern "C"

JNIEXPORT void JNICALL

Java_com_peakmain_ndk_FaceDetection_faceDetectionSaveInfo(JNIEnv *env, jobject instance,

jobject bitmap) {

//检测人脸,opencv有一个非常关键的类,opencv是c和c++写的,只处理Mat,android界面是bitmap

//1.bitmap转换成opencv能操作的c++对象Mat,mat是个矩阵

Mat mat;

bitmap2Mat(env,mat,bitmap);

//处理灰度,提高效率,一般操作都会执行

Mat gray_mat;

//转换成灰度

cvtColor(mat,gray_mat,COLOR_BGRA2GRAY);

//再次处理,直方均衡处理

Mat equalize_mat;

equalizeHist(gray_mat,equalize_mat);

//识别人脸,当然我们可以直接用彩色去做,识别人脸要加载人脸分类器文件

CV_OUT std::vector faces;

//5次识别

cascadeClassifier.detectMultiScale(equalize_mat,faces,1.1,5);

LOGE("人脸个数:%d",faces.size());

if(faces.size()==1){

Rect faceRect=faces[0];

//保存人脸信息,保存的其实就是mat,图片

// 在人脸部分画个图

rectangle(mat,faceRect,Scalar(255,155,155),8) ;

//把mat放到bitmap里面

mat2Bitmap(env,mat,bitmap);

//保存人脸的一部分

Mat face_info_mat(equalize_mat,faceRect);

//保存face_info_mat即可

}

//保存人脸信息

}

void mat2Bitmap(JNIEnv *env, Mat mat, jobject bitmap) {

// 1. 获取 bitmap 信息

AndroidBitmapInfo info;

void* pixels;

AndroidBitmap_getInfo(env,bitmap,&info);

// 锁定 Bitmap 画布

AndroidBitmap_lockPixels(env,bitmap,&pixels);

if(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888){// C4

Mat temp(info.height,info.width,CV_8UC4,pixels);

if(mat.type() == CV_8UC4){

mat.copyTo(temp);

}

else if(mat.type() == CV_8UC2){

cvtColor(mat,temp,COLOR_BGR5652BGRA);

}

else if(mat.type() == CV_8UC1){// 灰度 mat

cvtColor(mat,temp,COLOR_GRAY2BGRA);

}

} else if(info.format == ANDROID_BITMAP_FORMAT_RGB_565){// C2

Mat temp(info.height,info.width,CV_8UC2,pixels);

if(mat.type() == CV_8UC4){

cvtColor(mat,temp,COLOR_BGRA2BGR565);

}

else if(mat.type() == CV_8UC2){

mat.copyTo(temp);

}

else if(mat.type() == CV_8UC1){// 灰度 mat

cvtColor(mat,temp,COLOR_GRAY2BGR565);

}

}

// 其他要自己去转

// 解锁 Bitmap 画布

AndroidBitmap_unlockPixels(env,bitmap);

}

build.gradle中defautConfig需要添加如下代码

externalNativeBuild {

cmake {

cppFlags ""

//只生成aremabi

abiFilters "armeabi"

}

}

效果图

效果图.png

android ndk人脸识别,NDK开发-实现支付宝人脸识别功能相关推荐

  1. 人脸识别技术开发解决方案,人脸识别智慧校园应用开发

    自2010年信息化"十二五"规划开始正式提出了"智慧校园"的建设愿景,智慧校园建设也成为了教育信息化2.0规划中的重要工作之一. 截至目前,智慧校园建设已经进行 ...

  2. NDK开发前奏 - 实现支付宝人脸识别功能

    1. 基于 Android Studio 的 opencv 配置与使用 先推荐一本书<计算机视觉 - 算法与应用>,相信用过 OpenCV 的哥们都知道这是用来干啥的,这里我就不再啰嗦.只 ...

  3. android NDK 在Ubuntu10.04开发环境的搭建

    2019独角兽企业重金招聘Python工程师标准>>> 最近可能要用到调用jni,我对NDK和Jni了解非常的少,今天根据网络上的一些博客搭建了一下NDK的开发环境,但是继续往下编译 ...

  4. android人脸识别demo_C#开发实录:基于免费SDK实现人脸识别应用开发

    随着人脸识别技术应用范围不断扩展,如何在Windows C#上基于免费SDK实现人脸识别应用开发,正成为开发者们关心的话题之一. 对于该需求,我推荐虹软视觉开放平台的ArcFace 3.0,免费.离线 ...

  5. Android Studio 4.0.+NDK项目开发详细教学

    JNI开发系列目录 JNI开发必学C++基础 JNI开发必学C++使用实践 Android Studio 4.0.+NDK项目开发详细教学 Android NDK与JNI的区别有何不同? Androi ...

  6. 【Android NDK 开发】在 C 代码中获取 Android 系统信息 ( NDK 项目创建 | NDK 配置 | 获取 Android 系统版本号 )

    文章目录 I . 创建 NDK 项目 II . NDK 项目 相关配置 III . NDK 中获取 Android 版本号 IV . 使用 __system_property_get 可获取的参数 I ...

  7. 在android studio中配置ndk开发环境

    环境:android studio 1.5 android-ndk-r10b 1.下载android-ndk-r10b,解压. 2.android studio创建新项目, 配置ndk环境 打开fil ...

  8. Android开发之虹软人脸识别活体检测基本步骤

    首先,我简单说下虹软的人脸识别基本步骤: 1.你的设置好设置视频模式方向用于人脸检测 有如下几个可设置方向 //设置视频模式全方向人脸检测ConfigUtil.setFtOrient(this, Fa ...

  9. 记录过程: Android Studio4.2通过NDK调用TNN(预编译的tnn so库)

    目录 0. 准备 1. 创建android ndk工程 2. 分析默认生成的工程 3. 写好java native接口 4. 实现这些java native方法(jni) 5. 修改cpp/CMake ...

最新文章

  1. 深度学习之Pytorch基础教程!
  2. exe已停止工作_win7系统提示com surrogate已停止工作的解决方法【介绍】
  3. 山东省2021年普通高考成绩录取去向查询,2018年山东高考录取去向查询时间及入口...
  4. 关于“大数据”的15条干货思考
  5. 电信设备产品简介材料收集
  6. Windows PatchGuard学习
  7. 结构张量用于区分平坦、边缘、角点区域
  8. 关于IDEA代码的整理以及函数
  9. openlayers入门开发系列之热力图篇
  10. ext.net 开发学习之复杂模板板块 (叁)
  11. AD放置过孔按TAB键使过孔大小为设置值0.6/0.3
  12. Javascript特效:封装元素动画函数
  13. ElasticSearch 2 (30) - 信息聚合系列之条形图
  14. 翻译:Swift中的Operations和OperationQueues入门
  15. 点云配准(一) 线性代数基础
  16. CAD注册机注册码不能正常使用,解决方案
  17. AI cs5序列号 注册机
  18. 缓存篇(二)- JetCache
  19. 关于EI计算机视觉投稿
  20. 【cf】Codeforces Round #784(Div 4)

热门文章

  1. list转set遇坑:TypeError: unhashable type: ‘list‘
  2. 支持linux自动关机的ups,Linux如何使用普通的UPS做到断电自动关机
  3. 字符串匹配算法之哈希匹配算法
  4. 从意思准度和重叠性角度看待中文、…
  5. Android开发之取两个色值的中间色
  6. 多旋翼飞行器技术_YY硕
  7. EasyCaptcha-Plus
  8. 不同笔记本连接投影仪快捷键汇总
  9. 台式计算机材质,台式电脑显示器购买的时候主要看哪些参数?
  10. Python中空格的转义字符