• Android基于opencv4.6.0实现人脸识别功能


    前言

    步骤:

    1.整合opencv

    2.获取相机的SurfaceView传到native层去检测(亦或是不断的获取SurfaceView的Bitmap,传到native层)

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

    4.上传至后台(不实现)

    人脸识别实现的思路(例:人脸登录)

    1.人脸信息录入

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

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

    2.人脸特征值匹配

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

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

    一.Android Studio配置opencv

    1.opencv资源获取

    opencv官网:Home - OpenCV 

    opencv最新的版本是4.6.0于2022年06月07日发布,4.6.0网址:OpenCV 4.6.0 Is Now Available! - OpenCV

    opencv 4.6.0android sdk 下载链接https://nchc.dl.sourceforge.net/project/opencvlibrary/4.6.0/opencv-4.6.0-android-sdk.zip

    2.解压opencv-4.6.0-android-sdk.zip文件

    解压之后的文件夹:OpenCV-android-sdk

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

    sdk:所有的资源,so库,头文件,NDK自己动手写

    源码下载链接:https://github.com/opencv/opencv/archive/4.6.0.zip

    3.新建Android项目(native c++)

    C++ Standard 选择C++11

     

     在main目录下新建jni文件夹

     将OpenCV-android-sdk\sdk\native\jni下的include文件夹复制至项目中的jni文件夹下

     

     将OpenCV-android-sdk\sdk\native\libs下的armeabi-v7a文件夹复制至jni文件夹下

     

     3.1配置CMakeLists.txt

    引入头文件

     添加opencv库并设置目标属性(注意路径)

     添加目标链接库opencv-lib

     CMakeLists.txt内容:

    1. # For more information about using CMake with Android Studio, read the
    2. # documentation: https://d.android.com/studio/projects/add-native-code.html
    3. # Sets the minimum version of CMake required to build the native library.
    4. cmake_minimum_required(VERSION 3.10.2)
    5. # Declares and names the project.
    6. project("opencvtestapplication")
    7. #需要引入我们头文件,以这个配置的目录为基准
    8. include_directories(${CMAKE_SOURCE_DIR}/../jni/include)
    9. # Creates and names a library, sets it as either STATIC
    10. # or SHARED, and provides the relative paths to its source code.
    11. # You can define multiple libraries, and CMake builds them for you.
    12. # Gradle automatically packages shared libraries with your APK.
    13. add_library( # Sets the name of the library.
    14. native-lib
    15. # Sets the library as a shared library.
    16. SHARED
    17. # Provides a relative path to your source file(s).
    18. native-lib.cpp )
    19. # 添加opencv的库
    20. add_library(
    21. opencv-lib
    22. SHARED
    23. IMPORTED)
    24. set_target_properties(
    25. opencv-lib
    26. PROPERTIES IMPORTED_LOCATION
    27. ${CMAKE_SOURCE_DIR}/../jni/armeabi-v7a/libopencv_java4.so)
    28. # Searches for a specified prebuilt library and stores the path as a
    29. # variable. Because CMake includes system libraries in the search path by
    30. # default, you only need to specify the name of the public NDK library
    31. # you want to add. CMake verifies that the library exists before
    32. # completing its build.
    33. find_library( # Sets the name of the path variable.
    34. log-lib
    35. # Specifies the name of the NDK library that
    36. # you want CMake to locate.
    37. log )
    38. # Specifies libraries CMake should link to your target library. You
    39. # can link multiple libraries, such as libraries you define in this
    40. # build script, prebuilt third-party libraries, or system libraries.
    41. target_link_libraries( # Specifies the target library.
    42. native-lib opencv-lib
    43. # Links the target library to the log library
    44. # included in the NDK.
    45. ${log-lib} )

    3.2修改app下的build.gradle文件 只支持armv7

     同步运行项目至手机设备

    出现如下图所示错误:

     java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found

    解决方式如下:

    修改app下的build.gradle文件

     重新同步项目并运行项目至手机设备

    3.3新建FaceDetection类

    FaceDetection内容如下:

    1. package com.suoer.ndk.opencvtestapplication;
    2. import android.graphics.Bitmap;
    3. public class FaceDetection {
    4. // Used to load the 'native-lib' library on application startup.
    5. static {
    6. System.loadLibrary("native-lib");
    7. }
    8. /**
    9. * 检测人脸并保存人脸信息
    10. * @param faceBitmap
    11. */
    12. public native int faceDetectionSaveInfo(Bitmap faceBitmap);
    13. /**
    14. * 加载人脸识别的分类器文件
    15. * @param filePath
    16. */
    17. public native boolean loadCascade(String filePath);
    18. }

    3.4修改MainActivity类

    因为需要拍照以及保存图片,所以需要权限处理。这里使用rxpermissions

    rxpermissions的具体使用请参照github链接:GitHub - tbruyelle/RxPermissions: Android runtime permissions powered by RxJava2

    因为保存图片是耗时操作,需要开启子线程完成,所以需要处理线程问题。这里使用rxandroid

    rxandroid的具体使用请参照github链接:GitHub - ReactiveX/RxAndroid: RxJava bindings for Android

    修改app下的build.gradle文件

     app下的build.gradle文件内容:

    1. plugins {
    2. id 'com.android.application'
    3. }
    4. android {
    5. compileSdkVersion 32
    6. buildToolsVersion "32.0.0"
    7. defaultConfig {
    8. applicationId "com.suoer.ndk.opencvtestapplication"
    9. minSdkVersion 16
    10. targetSdkVersion 32
    11. versionCode 1
    12. versionName "1.0"
    13. testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    14. externalNativeBuild {
    15. cmake {
    16. cppFlags "-std=c++11 -Wno-nonportable-include-path -Wno-deprecated-register -Wno-writable-strings"
    17. //远程下载
    18. arguments "-DANDROID_STL=c++_shared"
    19. }
    20. }
    21. ndk {
    22. abiFilters("armeabi-v7a")
    23. }
    24. }
    25. buildTypes {
    26. release {
    27. minifyEnabled false
    28. proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
    29. }
    30. }
    31. externalNativeBuild {
    32. cmake {
    33. path "src/main/cpp/CMakeLists.txt"
    34. version "3.10.2"
    35. }
    36. }
    37. compileOptions {
    38. sourceCompatibility JavaVersion.VERSION_1_8
    39. targetCompatibility JavaVersion.VERSION_1_8
    40. }
    41. }
    42. dependencies {
    43. implementation 'androidx.appcompat:appcompat:1.1.0'
    44. implementation 'com.google.android.material:material:1.1.0'
    45. implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    46. testImplementation 'junit:junit:4.+'
    47. androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    48. androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    49. implementation 'com.github.tbruyelle:rxpermissions:0.12'
    50. implementation 'io.reactivex.rxjava3:rxandroid:3.0.0'
    51. }

    修改项目下的build.gradle文件

     项目下的build.gradle文件内容:

    1. // Top-level build file where you can add configuration options common to all sub-projects/modules.
    2. buildscript {
    3. repositories {
    4. google()
    5. jcenter()
    6. }
    7. dependencies {
    8. classpath "com.android.tools.build:gradle:4.1.0"
    9. // NOTE: Do not place your application dependencies here; they belong
    10. // in the individual module build.gradle files
    11. }
    12. }
    13. allprojects {
    14. repositories {
    15. google()
    16. jcenter()
    17. maven { url 'https://jitpack.io' }
    18. maven { url "https://oss.jfrog.org/libs-snapshot" }
    19. }
    20. }
    21. task clean(type: Delete) {
    22. delete rootProject.buildDir
    23. }

    修改AndroidManifest.xml添加权限

     

    1. <uses-permission android:name="android.permission.CAMERA" />
    2. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

    MainActivity类内容如下:

    1. package com.suoer.ndk.opencvtestapplication;
    2. import android.Manifest;
    3. import android.content.Context;
    4. import android.content.pm.PackageManager;
    5. import android.graphics.Bitmap;
    6. import android.os.Bundle;
    7. import android.util.Log;
    8. import android.view.SurfaceView;
    9. import android.view.View;
    10. import android.view.Window;
    11. import android.view.WindowManager;
    12. import android.widget.Button;
    13. import android.widget.ImageView;
    14. import android.widget.Toast;
    15. import com.suoer.ndk.opencvtestapplication.camerahandle.BitmapInterface;
    16. import com.suoer.ndk.opencvtestapplication.camerahandle.CameraSurfaceHolder;
    17. import com.suoer.ndk.opencvtestapplication.camerahandle.FrontCamera;
    18. import com.suoer.ndk.opencvtestapplication.camerahandle.SaveImageTask;
    19. import com.suoer.ndk.opencvtestapplication.camerahandle.SurfaceViewCallback;
    20. import com.tbruyelle.rxpermissions3.RxPermissions;
    21. import java.io.ByteArrayOutputStream;
    22. import java.io.File;
    23. import java.io.FileOutputStream;
    24. import java.io.IOException;
    25. import java.io.InputStream;
    26. import androidx.appcompat.app.AppCompatActivity;
    27. import io.reactivex.rxjava3.functions.Consumer;
    28. public class MainActivity extends AppCompatActivity {
    29. private static final String TAG = "MainActivity";
    30. private SurfaceView mSurfaceView;
    31. private ImageView faceImg;
    32. private Button faceDetectionBtn;
    33. private FaceDetection mFaceDetection;
    34. private File mCascadeFile;
    35. private CameraSurfaceHolder mCameraSurfaceHolder=new CameraSurfaceHolder();
    36. private SurfaceViewCallback mSurfaceViewCallback;
    37. private FrontCamera mFrontCamera;
    38. @Override
    39. protected void onCreate(Bundle savedInstanceState) {
    40. super.onCreate(savedInstanceState);
    41. requestWindowFeature(Window.FEATURE_NO_TITLE);
    42. getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
    43. initView();
    44. applyPermission();
    45. initFaceDetection();
    46. }
    47. private void initFaceDetection() {
    48. copyCascadeFile();
    49. mFaceDetection = new FaceDetection();
    50. if (mFaceDetection != null) {
    51. boolean load = mFaceDetection.loadCascade(mCascadeFile.getAbsolutePath());
    52. if (load) {
    53. Toast.makeText(this, "加载分类器文件成功!", Toast.LENGTH_SHORT).show();
    54. } else {
    55. Toast.makeText(this, "加载分类器文件失败!", Toast.LENGTH_SHORT).show();
    56. }
    57. }
    58. }
    59. //申请权限
    60. private void applyPermission() {
    61. if (!checkCameraHardware(this)) {
    62. return;
    63. }
    64. RxPermissions rxPermissions = new RxPermissions(this);
    65. rxPermissions.request(Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.CAMERA).subscribe(new Consumer() {
    66. @Override
    67. public void accept(Boolean aBoolean) throws Throwable {
    68. if (aBoolean) {
    69. Log.e(TAG, "accept: " + aBoolean);
    70. faceDetectionBtn.setVisibility(View.VISIBLE);
    71. mSurfaceView.setVisibility(View.VISIBLE);
    72. //权限全部获取
    73. initSurfaceViewPreView();
    74. }
    75. }
    76. });
    77. }
    78. private void initSurfaceViewPreView() {
    79. mCameraSurfaceHolder.setCameraSurfaceHolder(MainActivity.this, mSurfaceView);
    80. mSurfaceViewCallback = mCameraSurfaceHolder.mSurfaceViewCallback;
    81. if (mSurfaceViewCallback != null) {
    82. mFrontCamera = mSurfaceViewCallback.mFrontCamera;
    83. }
    84. }
    85. ;
    86. private void initView() {
    87. setContentView(R.layout.activity_main);
    88. mSurfaceView = findViewById(R.id.face_surfaceView);
    89. mSurfaceView.setVisibility(View.GONE);
    90. faceDetectionBtn = findViewById(R.id.faceDetectionBtn);
    91. faceImg = findViewById(R.id.faceImg);
    92. faceDetectionBtn.setOnClickListener(new View.OnClickListener() {
    93. @Override
    94. public void onClick(View v) {
    95. if (mFrontCamera != null) {
    96. //拍照的时候进行人脸识别
    97. mFrontCamera.takePicture(new BitmapInterface() {
    98. @Override
    99. public void setBitMap(Bitmap bitMap) {
    100. if(bitMap==null){
    101. Toast.makeText(MainActivity.this,"拍照失败!",Toast.LENGTH_SHORT).show();
    102. return;
    103. }
    104. //人脸识别
    105. int result = mFaceDetection.faceDetectionSaveInfo(bitMap);
    106. if (result != 0) {
    107. Toast.makeText(MainActivity.this, "检测人脸失败!", Toast.LENGTH_SHORT).show();
    108. return;
    109. }
    110. faceImg.setVisibility(View.VISIBLE);
    111. faceImg.setImageBitmap(bitMap);
    112. byte[]data= bitmap2byte(bitMap);
    113. //rxandroid实现开启子线程保存文件
    114. new SaveImageTask(MainActivity.this,faceImg).saveImage(data);
    115. //AsyncTask异步任务实现开启子线程保存文件
    116. //new SaveImageAsyncTask(MainActivity.this,faceImg).execute(data);
    117. }
    118. });
    119. }
    120. }
    121. });
    122. }
    123. private byte[] bitmap2byte(Bitmap photoBitmap){
    124. 创建对应的流对象
    125. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    126. photoBitmap.compress(Bitmap.CompressFormat.JPEG,100,byteArrayOutputStream);//将流对象与Bitmap对象进行关联。
    127. byte [] array=byteArrayOutputStream.toByteArray();//使用流对象,将Bitmap对象转换为byte[]数组
    128. return array;
    129. }
    130. private void copyCascadeFile() {
    131. try {
    132. // load cascade file from application resources
    133. InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
    134. File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
    135. mCascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
    136. if (mCascadeFile.exists()) return;
    137. FileOutputStream os = new FileOutputStream(mCascadeFile);
    138. byte[] buffer = new byte[4096];
    139. int bytesRead;
    140. while ((bytesRead = is.read(buffer)) != -1) {
    141. os.write(buffer, 0, bytesRead);
    142. }
    143. is.close();
    144. os.close();
    145. cascadeDir.delete();
    146. } catch (IOException e) {
    147. e.printStackTrace();
    148. Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);
    149. }
    150. }
    151. /**
    152. * 检测是否存在摄像头
    153. *
    154. * @param context
    155. * @return
    156. */
    157. private boolean checkCameraHardware(Context context) {
    158. if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
    159. return true;
    160. } else {
    161. Toast.makeText(this, "不具备摄像头硬件", Toast.LENGTH_SHORT).show();
    162. return false;
    163. }
    164. }
    165. }


    布局activity_main.xml

    1. "1.0" encoding="utf-8"?>
    2. <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    3. xmlns:app="http://schemas.android.com/apk/res-auto"
    4. xmlns:tools="http://schemas.android.com/tools"
    5. android:layout_width="match_parent"
    6. android:layout_height="match_parent"
    7. tools:context=".MainActivity">
    8. <SurfaceView
    9. app:layout_constraintTop_toTopOf="@+id/faceDetectionBtn"
    10. android:id="@+id/face_surfaceView"
    11. android:layout_width="match_parent"
    12. android:layout_height="match_parent"/>
    13. <ImageView
    14. app:layout_constraintTop_toTopOf="@+id/faceDetectionBtn"
    15. android:visibility="gone"
    16. android:id="@+id/faceImg"
    17. android:src="@drawable/face"
    18. android:layout_width="match_parent"
    19. android:layout_height="match_parent">ImageView>
    20. <Button
    21. android:visibility="gone"
    22. android:id="@+id/faceDetectionBtn"
    23. android:layout_width="match_parent"
    24. android:layout_height="wrap_content"
    25. android:text="人脸识别"
    26. app:layout_constraintBottom_toBottomOf="parent"
    27. app:layout_constraintLeft_toLeftOf="parent"
    28. app:layout_constraintRight_toRightOf="parent"
    29. />
    30. androidx.constraintlayout.widget.ConstraintLayout>

    3.5修改native-lib.cpp

    1. #include
    2. #include
    3. #include
    4. #include
    5. #include
    6. #include
    7. #define TAG "JNI_LOG"
    8. #define LOGE(...)__android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
    9. using namespace cv;
    10. CascadeClassifier cascadeClassifier;
    11. //使用命名空间
    12. void bitmap2Mat(JNIEnv *env, Mat &mat, jobject bitmap);
    13. //mat转成bitmap
    14. void mat2Bitmap(JNIEnv *env, Mat mat, jobject bitmap);
    15. //bitmap转成mat
    16. void bitmap2Mat(JNIEnv *env, Mat &mat, jobject bitmap) {
    17. //Mat里面有个type:CV_8UC4 刚好对上bitmap中的ARGB_8888 CV_8UC2 刚好匹配bitmap中的RGB_565
    18. //1.获取bitmap信息
    19. AndroidBitmapInfo info;
    20. void *pixels;
    21. AndroidBitmap_getInfo(env,bitmap,&info);
    22. //锁定bitmap画布
    23. AndroidBitmap_lockPixels(env,bitmap,&pixels);
    24. //指定mat的宽高和type BGRA
    25. mat.create(info.height,info.width,CV_8UC4);
    26. if(info.format==ANDROID_BITMAP_FORMAT_RGBA_8888){
    27. //对应的mat应该是CV_8UC4
    28. Mat temp(info.height,info.width,CV_8UC4,pixels);
    29. //把数据temp复制到mat里面
    30. temp.copyTo(mat);
    31. }else if(info.format==ANDROID_BITMAP_FORMAT_RGB_565){
    32. //对应的mat应该是CV_8UC2
    33. Mat temp(info.height,info.width,CV_8UC2,pixels);
    34. //上面mat创建的是CV_8UC4 要改为CV_8UC2 CV_8UC2数据拷贝到CV_8UC4
    35. cvtColor(temp,mat,COLOR_BGR5652BGRA);
    36. }
    37. //其他需要自己去转
    38. //解锁画布
    39. AndroidBitmap_unlockPixels(env,bitmap);
    40. }
    41. extern "C"
    42. JNIEXPORT jint JNICALL
    43. Java_com_suoer_ndk_opencvtestapplication_FaceDetection_faceDetectionSaveInfo(JNIEnv *env,
    44. jobject thiz,
    45. jobject face_bitmap) {
    46. // TODO: implement faceDetectionSaveInfo()
    47. //检测人脸 opencv有关键的类是Mat,opencv是c和c++写的,只会处理Mat,android里面是Bitmap
    48. //1.Bitmap转成opencv能操作的c++对象 Mat ,Mat是一个矩阵
    49. Mat mat;
    50. bitmap2Mat(env,mat,face_bitmap);
    51. //处理灰度opencv 处理灰度图 提高效率,一般所有的操作都会对齐进行处理
    52. Mat gray_mat;
    53. cvtColor(mat,gray_mat,COLOR_BGRA2GRAY);
    54. //再次处理直方均衡补偿
    55. Mat equalize_mat;
    56. equalizeHist(gray_mat,equalize_mat);
    57. //识别人脸 当然我们可以直接用彩色图去做,识别人脸要加载人脸分类器文件
    58. std::vector faces;
    59. cascadeClassifier.detectMultiScale(equalize_mat,faces,1.1,5);
    60. LOGE("人脸个数:%d",faces.size());
    61. if(faces.size()!=1){
    62. return -1;
    63. }
    64. Rect faceRect=faces[0];
    65. //在人脸部分画个图
    66. rectangle(mat,faceRect,Scalar(255,155,155),8);
    67. //把mat 放到bitmap中 图片展示出来
    68. //mat2Bitmap(env,mat,face_bitmap);
    69. //保存人脸信息 Mat,图片
    70. Mat face_info_mat(equalize_mat,faceRect);
    71. //保存face_info_mat
    72. mat2Bitmap(env,face_info_mat,face_bitmap);
    73. //mat2Bitmap(env,equalize_mat,face_bitmap);
    74. //保存人脸信息
    75. return 0;
    76. }
    77. void mat2Bitmap(JNIEnv *env, Mat mat, jobject bitmap) {
    78. //Mat里面有个type:CV_8UC4 刚好对上bitmap中的ARGB_8888 CV_8UC2 刚好匹配bitmap中的RGB_565
    79. //1.获取bitmap信息
    80. AndroidBitmapInfo info;
    81. void *pixels;
    82. AndroidBitmap_getInfo(env,bitmap,&info);
    83. //锁定bitmap画布
    84. AndroidBitmap_lockPixels(env,bitmap,&pixels);
    85. if(info.format==ANDROID_BITMAP_FORMAT_RGBA_8888){
    86. //对应的mat应该是CV_8UC4
    87. Mat temp(info.height,info.width,CV_8UC4,pixels);
    88. if(mat.type()==CV_8UC4){
    89. mat.copyTo(temp);
    90. }else if(mat.type()==CV_8UC2){
    91. cvtColor(mat,temp,COLOR_BGR5652BGRA);
    92. }
    93. else if(mat.type()==CV_8UC1){//灰度mat
    94. cvtColor(mat,temp,COLOR_GRAY2BGRA);
    95. }
    96. }else if(info.format==ANDROID_BITMAP_FORMAT_RGB_565){
    97. //对应的mat应该是CV_8UC2
    98. Mat temp(info.height,info.width,CV_8UC2,pixels);
    99. if(mat.type()==CV_8UC4){
    100. cvtColor(mat,temp,COLOR_BGRA2BGR565);
    101. }else if(mat.type()==CV_8UC2){
    102. mat.copyTo(temp);
    103. }
    104. else if(mat.type()==CV_8UC1){//灰度mat
    105. cvtColor(mat,temp,COLOR_GRAY2BGR565);
    106. }
    107. }
    108. //其他需要自己去转
    109. //解锁画布
    110. AndroidBitmap_unlockPixels(env,bitmap);
    111. }
    112. extern "C"
    113. JNIEXPORT jboolean JNICALL
    114. Java_com_suoer_ndk_opencvtestapplication_FaceDetection_loadCascade(JNIEnv *env, jobject thiz,
    115. jstring file_path) {
    116. // TODO: implement loadCascade()
    117. const char *filePath=env->GetStringUTFChars(file_path,0);
    118. bool load=cascadeClassifier.load(filePath);
    119. env->ReleaseStringUTFChars(file_path,filePath);
    120. return load;
    121. }

    运行app至手机设备出现如下图所示错误

    error: undefined reference to 'AndroidBitmap_getInfo'

     解决方式修改CMakeLists.txt

     

    1. target_link_libraries( # Specifies the target library.
    2. native-lib opencv-lib
    3. #加入该依赖库
    4. jnigraphics
    5. # Links the target library to the log library
    6. # included in the NDK.
    7. ${log-lib} )

    CMakeLists.txt内容如下:

    1. # For more information about using CMake with Android Studio, read the
    2. # documentation: https://d.android.com/studio/projects/add-native-code.html
    3. # Sets the minimum version of CMake required to build the native library.
    4. cmake_minimum_required(VERSION 3.10.2)
    5. # Declares and names the project.
    6. project("opencvtestapplication")
    7. #需要引入我们头文件,以这个配置的目录为基准
    8. include_directories(${CMAKE_SOURCE_DIR}/../jni/include)
    9. # Creates and names a library, sets it as either STATIC
    10. # or SHARED, and provides the relative paths to its source code.
    11. # You can define multiple libraries, and CMake builds them for you.
    12. # Gradle automatically packages shared libraries with your APK.
    13. add_library( # Sets the name of the library.
    14. native-lib
    15. # Sets the library as a shared library.
    16. SHARED
    17. # Provides a relative path to your source file(s).
    18. native-lib.cpp )
    19. # 添加opencv的库
    20. add_library(
    21. opencv-lib
    22. SHARED
    23. IMPORTED)
    24. set_target_properties(
    25. opencv-lib
    26. PROPERTIES IMPORTED_LOCATION
    27. ${CMAKE_SOURCE_DIR}/../jni/armeabi-v7a/libopencv_java4.so)
    28. # Searches for a specified prebuilt library and stores the path as a
    29. # variable. Because CMake includes system libraries in the search path by
    30. # default, you only need to specify the name of the public NDK library
    31. # you want to add. CMake verifies that the library exists before
    32. # completing its build.
    33. find_library( # Sets the name of the path variable.
    34. log-lib
    35. # Specifies the name of the NDK library that
    36. # you want CMake to locate.
    37. log )
    38. # Specifies libraries CMake should link to your target library. You
    39. # can link multiple libraries, such as libraries you define in this
    40. # build script, prebuilt third-party libraries, or system libraries.
    41. target_link_libraries( # Specifies the target library.
    42. native-lib opencv-lib
    43. #加入该依赖库
    44. jnigraphics
    45. # Links the target library to the log library
    46. # included in the NDK.
    47. ${log-lib} )

    其他详细内容可见Demo。

  • 相关阅读:
    一张图搞懂微服务架构设计
    echarts画各种形状水波图
    如何把bat脚本注册成windows service
    数据挖掘:关联规则,异常检测,挖掘的标准流程,评估指标,误差,聚类,决策树
    Android毕业设计开题报告基于Uniapp+SSM实现的公园植物介绍APP
    java多线程-对象及变量的并发访问
    2022-9-17 第七小组 学习日记 (day72)SSM架构
    Say0l的安全开发-代理扫描工具-Sayo-proxyscan【红队工具】
    文件上传漏洞简介
    探索Kotlin:从K1到K2
  • 原文地址:https://blog.csdn.net/Jushuzhan/article/details/126619177