当前位置:   article > 正文

Android OpenCV 实现人脸检测(手把手,一步步实现)_android studio opencv 人脸识别

android studio opencv 人脸识别

1.下载OpenCV

OpenCV 网址:OpenCV 

选择一个版本下载,这里以4.5.3版本为例,下载Android版本

 下载后解压后得到4个文件,如下所示:

 2.创建Android项目

打开Android studio ,新建一个工程,创建后点击Android studio左上角的File下的New菜单下的Import Module如下所示:

 找到刚下载好解压后的OpenCV目录,选择sdk作为module导入,如下所示:

可以修改module的名称

 导入后,需要修改openCV module下的build.gradle,修改的信息与你app下的build.gradle的版本信息一直即可

 需要注意的是,openCV4.5.3有使用到kotlin,所以你用Java开发的话,还需要在你项目下的build.gradle的文件下添加kotlin的支持,如下所示:

 之后,将module依赖到你的项目中,在app的build.gradle添加OpenCV modulde的依赖,如下所示:

 至此,OpenCV的环境搭建完毕,接下来,实现人脸检测

3.实现人脸检测

1.添加布局:

        新建一个布局,作为界面的展示,代码如下所示:

  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:id="@+id/di"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent"
  6. android:background="#FAFFFFFF"
  7. android:orientation="vertical">
  8. <org.opencv.android.JavaCameraView
  9. android:id="@+id/cjv"
  10. android:layout_width="match_parent"
  11. android:layout_height="match_parent"
  12. android:background="#00090808" />
  13. </LinearLayout>

opencv里自带相机预览控件,我们这里直接使用。

activity代码如下:

  1. import org.opencv.android.BaseLoaderCallback;
  2. import org.opencv.android.CameraBridgeViewBase.CvCameraViewFrame;
  3. import org.opencv.android.LoaderCallbackInterface;
  4. import org.opencv.android.OpenCVLoader;
  5. import org.opencv.core.*;
  6. import org.opencv.android.CameraBridgeViewBase;
  7. import org.opencv.android.CameraBridgeViewBase.CvCameraViewListener2;
  8. import org.opencv.imgproc.Imgproc;
  9. import org.opencv.objdetect.CascadeClassifier;
  10. import android.Manifest;
  11. import android.annotation.SuppressLint;
  12. import android.content.Context;
  13. import android.os.Bundle;
  14. import android.util.Log;
  15. import android.widget.Toast;
  16. import androidx.appcompat.app.AppCompatActivity;
  17. import com.tbruyelle.rxpermissions2.RxPermissions;
  18. import java.io.File;
  19. import java.io.FileOutputStream;
  20. import java.io.InputStream;
  21. public class OpenCVActivity extends AppCompatActivity implements CvCameraViewListener2 {
  22. private static final String TAG = "OCVSample::Activity";
  23. private CameraBridgeViewBase mOpenCvCameraView;
  24. private Mat mIntermediateMat;
  25. private CascadeClassifier classifier;
  26. private Mat mGray;
  27. private Mat mRgba;
  28. private int mAbsoluteFaceSize = 0;
  29. private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
  30. @Override
  31. public void onManagerConnected(int status) {
  32. switch (status) {
  33. case LoaderCallbackInterface.SUCCESS: {
  34. Log.i(TAG, "OpenCV loaded successfully");
  35. getPermission();
  36. mOpenCvCameraView.enableView();
  37. }
  38. break;
  39. default: {
  40. super.onManagerConnected(status);
  41. }
  42. break;
  43. }
  44. }
  45. };
  46. public OpenCVActivity() {
  47. Log.i(TAG, "Instantiated new " + this.getClass());
  48. }
  49. /**
  50. * Called when the activity is first created.
  51. */
  52. @Override
  53. public void onCreate(Bundle savedInstanceState) {
  54. Log.i(TAG, "called onCreate");
  55. super.onCreate(savedInstanceState);
  56. setContentView(R.layout.image_manipulations_surface_view);
  57. mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.cjv);
  58. //这里的cjv也是我的项目中JavaCameraView的id,自己改一下
  59. mOpenCvCameraView.setCvCameraViewListener(this);
  60. }
  61. @Override
  62. public void onPause() {
  63. super.onPause();
  64. if (mOpenCvCameraView != null)
  65. mOpenCvCameraView.disableView();
  66. }
  67. @Override
  68. public void onResume() {
  69. super.onResume();
  70. if (!OpenCVLoader.initDebug()) {
  71. Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
  72. OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, mLoaderCallback);
  73. } else {
  74. Log.d(TAG, "OpenCV library found inside package. Using it!");
  75. mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
  76. }
  77. }
  78. public void onDestroy() {
  79. super.onDestroy();
  80. if (mOpenCvCameraView != null)
  81. mOpenCvCameraView.disableView();
  82. }
  83. public void onCameraViewStarted(int width, int height) {
  84. mGray = new Mat();
  85. mRgba = new Mat();
  86. }
  87. public void onCameraViewStopped() {
  88. // Explicitly deallocate Mats
  89. if (mIntermediateMat != null)
  90. mIntermediateMat.release();
  91. mIntermediateMat = null;
  92. mGray.release();
  93. mRgba.release();
  94. }
  95. public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
  96. // Mat rgba = inputFrame.rgba();
  97. // return rgba;
  98. mRgba = inputFrame.rgba();
  99. mGray = inputFrame.gray();
  100. float mRelativeFaceSize = 0.2f;
  101. if (mAbsoluteFaceSize == 0) {
  102. int height = mGray.rows();
  103. if (Math.round(height * mRelativeFaceSize) > 0) {
  104. mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
  105. }
  106. }
  107. MatOfRect faces = new MatOfRect();
  108. if (classifier != null)
  109. classifier.detectMultiScale(mGray, faces, 1.1, 2, 2,
  110. new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
  111. Rect[] facesArray = faces.toArray();
  112. Scalar faceRectColor = new Scalar(0, 255, 0, 255);
  113. for (Rect faceRect : facesArray)
  114. Imgproc.rectangle(mRgba, faceRect.tl(), faceRect.br(), faceRectColor, 1);
  115. return mRgba;
  116. }
  117. // 初始化人脸级联分类器,必须先初始化
  118. private void initClassifier() {
  119. try {
  120. InputStream is = getResources()
  121. .openRawResource(R.raw.lbpcascade_frontalface);
  122. File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
  123. File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
  124. FileOutputStream os = new FileOutputStream(cascadeFile);
  125. byte[] buffer = new byte[4096];
  126. int bytesRead;
  127. while ((bytesRead = is.read(buffer)) != -1) {
  128. os.write(buffer, 0, bytesRead);
  129. }
  130. is.close();
  131. os.close();
  132. classifier = new CascadeClassifier(cascadeFile.getAbsolutePath());
  133. } catch (Exception e) {
  134. e.printStackTrace();
  135. }
  136. }
  137. @SuppressLint("CheckResult")
  138. private void getPermission(){
  139. RxPermissions rxPermissions = new RxPermissions(OpenCVActivity.this);
  140. rxPermissions.request(Manifest.permission.CAMERA).subscribe(aBoolean -> {
  141. if (aBoolean) {
  142. initClassifier();
  143. mOpenCvCameraView.setCameraPermissionGranted();
  144. } else {
  145. Toast.makeText(OpenCVActivity.this, "您还没有开启相机权限,请前往设置->应用管理->开启", Toast.LENGTH_SHORT).show();
  146. }
  147. });
  148. }
  149. }

代码中的 lbpcascade_frontalface文件可以在openCV module下etc/lbpcascades/lbpcascade_frontalface.xml获取到,

将其复制搭app下的raw目录下,没有raw则自行创建。

此外,需要注意我们这里有使用到相机,相机在android6.0以上除了需要在AndroidManifest.xml里添加权限,还需要动态申请,否则无法打开相机。AndroidManifest.xml权限如下所示:

  1. <uses-permission android:name="android.permission.CAMERA" />
  2. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
  3. <uses-feature
  4. android:name="android.hardware.camera"
  5. android:required="true" />
  6. <uses-feature
  7. android:name="android.hardware.camera.autofocus"
  8. android:required="true" />
  9. <uses-feature
  10. android:name="android.hardware.camera.front"
  11. android:required="true" />
  12. <uses-feature
  13. android:name="android.hardware.camera.front.autofocus"
  14. android:required="true" />

4.运行效果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/566827
推荐阅读
相关标签
  

闽ICP备14008679号