Android 利用OpenCV制作人脸检测APP

目录
  • 前言
  • 第一步:下载并安装Android studio
  • 第二步:下载SDK tools
  • 第三步:新建一个Android APP项目
  • 第四步:下载Opencv
  • 第五步:导入OpenCV
  • 第六步:添加代码
  • 第七步:连接手机运行程序

前言

本篇文章手把手教大家使用OpenCV来实现一个能在安卓手机上运行的人脸检测APP。其实不仅仅是能检测人脸,还能检测鼻子,嘴巴,眼睛和耳朵。花了不少精力写这篇文章,希望点赞收藏关注。

无图无真相,先把APP运行的结果给大家看看。

如上图所示,APP运行后,点击“选择图片”,从手机中选择一张图片,然后点击“处理”,APP会将人脸用矩形给框起来,同时把鼻子也给检测出来了。由于目的是给大家做演示,所以APP设计得很简单,而且也只实现了检测人脸和鼻子,没有实现对其他五官的检测。而且这个APP也只能检测很简单的图片,如果图片中背景太复杂就无法检测出人脸。

下面我将一步一步教大家如何实现上面的APP!

第一步:下载并安装Android studio

为了保证大家能下载到和我相同版本的Android Studio,我把安装包上传了到微云。下载地址

下载后,一路点击下一步就安装好了。当然,安装过程中要联网,所以可能会中途失败,如果失败了,重试几次,如果还是有问题,那么可能要开启VPN。

第二步:下载SDK tools

打开Android studio后,点击“File”->“Settings”

点击“Appearance & Behavior”->“System Settings”->“Android SDK”->“SDK Tools”。

然后选中“NDK”和“CMake”,点击“OK”。下载这两个工具可能要花一点时间,如果失败了请重试或开启VPN。

第三步:新建一个Android APP项目

点击“File”->“New”->“New Project”

选中“Empty Activity”,点击“Next”

“Language”选择“Java”,Minimum SDK选择“API 21”。点击“Finish”

第四步:下载Opencv

下载地址

下载后解压。

第五步:导入OpenCV

将opencv-4.5.4-android-sdk\OpenCV-android-sdk下面的sdk复制到你在第三步创建的Android项目下面。就是第三步图中的D:\programming\MyApplication下面。然后将sdk文件夹改名为openCVsdk。

选择“Project”->“settings.gradle”。在文件中添加include ‘:openCVsdk'

选择“Project”->“openCVsdk”->“build.gradle”。

将apply plugin: 'kotlin-android'改为//apply plugin: ‘kotlin-android'

将compileSdkVersion和minSdkVersion,targetSdkVersion改为31,21,31。

点击“File”->“Project Structure”

点击“Dependencies”->“app”->“+”->“Module Dependency”

选中“openCVsdk”,点击“OK”,以及母窗口的“OK”

在Android项目文件夹的app\src里面创建一个新文件夹jniLibs,然后把openCV文件夹的opencv-4.5.4-android-sdk\OpenCV-android-sdk\sdk\native\staticlibs里面的东西都copy到jniLibs文件夹中。

下载分类器。解压后,将下图中的文件都复制到项目文件夹的app\src\main\res\raw文件夹下。

第六步:添加代码

双击“Project”->“app”-》“main”-》“res”下面的“activity_main.xml”。然后点击右上角的“code”。

然后将里面的代码都换成下面的代码

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity"
    android:orientation="vertical"
    >

    <Button
        android:id="@+id/select_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="选择图片" />
    <Button
        android:id="@+id/process_btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="处理" />

    <ImageView
        android:id="@+id/imageView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>

双击“Project”->“app”-》“main”-》“java”-》“com.example…”下面的“MainActivity”。然后把里面的代码都换成下面的代码(保留原文件里的第一行代码)

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;

import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Point;
import org.opencv.imgproc.Imgproc;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.objdetect.CascadeClassifier;

import android.content.Context;

public class MainActivity extends AppCompatActivity {

    private double max_size = 1024;
    private int PICK_IMAGE_REQUEST = 1;
    private ImageView myImageView;
    private Bitmap selectbp;

    private static final String    TAG                 = "OCVSample::Activity";
    private static final Scalar    FACE_RECT_COLOR     = new Scalar(0, 255, 0, 255);
    public static final int        JAVA_DETECTOR       = 0;
    public static final int        NATIVE_DETECTOR     = 1;

    private Mat                    mGray;
    private File                   mCascadeFile;
    private CascadeClassifier      mJavaDetector,mNoseDetector;

    private int                    mDetectorType       = JAVA_DETECTOR;

    private float                  mRelativeFaceSize   = 0.2f;
    private int                    mAbsoluteFaceSize   = 0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        staticLoadCVLibraries();
        myImageView = (ImageView)findViewById(R.id.imageView);
        myImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
        Button selectImageBtn = (Button)findViewById(R.id.select_btn);
        selectImageBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // makeText(MainActivity.this.getApplicationContext(), "start to browser image", Toast.LENGTH_SHORT).show();
                selectImage();
            }

            private void selectImage() {
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,"选择图像..."), PICK_IMAGE_REQUEST);
            }
        });

        Button processBtn = (Button)findViewById(R.id.process_btn);
        processBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // makeText(MainActivity.this.getApplicationContext(), "hello, image process", Toast.LENGTH_SHORT).show();
                convertGray();
            }
        });

    }

    private void staticLoadCVLibraries() {
        boolean load = OpenCVLoader.initDebug();
        if(load) {
            Log.i("CV", "Open CV Libraries loaded...");
        }

    }

    private void convertGray() {
        Mat src = new Mat();
        Mat temp = new Mat();
        Mat dst = new Mat();
        Utils.bitmapToMat(selectbp, src);
        Imgproc.cvtColor(src, temp, Imgproc.COLOR_BGRA2BGR);
        Log.i("CV", "image type:" + (temp.type() == CvType.CV_8UC3));
        Imgproc.cvtColor(temp, dst, Imgproc.COLOR_BGR2GRAY);
        Utils.matToBitmap(dst, selectbp);
        myImageView.setImageBitmap(selectbp);

        mGray = dst;
        mJavaDetector = loadDetector(R.raw.lbpcascade_frontalface,"lbpcascade_frontalface.xml");
        mNoseDetector = loadDetector(R.raw.haarcascade_mcs_nose,"haarcascade_mcs_nose.xml");

        if (mAbsoluteFaceSize == 0) {
            int height = mGray.rows();
            if (Math.round(height * mRelativeFaceSize) > 0) {
                mAbsoluteFaceSize = Math.round(height * mRelativeFaceSize);
            }
        }

        MatOfRect faces = new MatOfRect();

        if (mJavaDetector != null) {
            mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2, // TODO: objdetect.CV_HAAR_SCALE_IMAGE
                        new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());

        }

        Rect[] facesArray = faces.toArray();
        for (int i = 0; i < facesArray.length; i++) {

            Log.e(TAG, "start to detect nose!");

            Mat faceROI = mGray.submat(facesArray[i]);

            MatOfRect noses = new MatOfRect();
            mNoseDetector.detectMultiScale(faceROI, noses, 1.1, 2, 2,
                    new Size(30, 30));

            Rect[] nosesArray = noses.toArray();
            Imgproc.rectangle(src,
                    new Point(facesArray[i].tl().x + nosesArray[0].tl().x, facesArray[i].tl().y + nosesArray[0].tl().y) ,
                    new Point(facesArray[i].tl().x + nosesArray[0].br().x, facesArray[i].tl().y + nosesArray[0].br().y) ,
                    FACE_RECT_COLOR, 3);

            Imgproc.rectangle(src, facesArray[i].tl(), facesArray[i].br(), FACE_RECT_COLOR, 3);
        }

        Utils.matToBitmap(src, selectbp);
        myImageView.setImageBitmap(selectbp);

    }

    private CascadeClassifier loadDetector(int rawID,String fileName) {
        CascadeClassifier classifier = null;
        try {

            // load cascade file from application resources
            InputStream is = getResources().openRawResource(rawID);
            File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
            mCascadeFile = new File(cascadeDir, fileName);
            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();

            Log.e(TAG, "start to load file:  " + mCascadeFile.getAbsolutePath());
            classifier = new CascadeClassifier(mCascadeFile.getAbsolutePath());

            if (classifier.empty()) {
                Log.e(TAG, "Failed to load cascade classifier");
                classifier = null;
            } else
                Log.i(TAG, "Loaded cascade classifier from " + mCascadeFile.getAbsolutePath());

            cascadeDir.delete();

        } catch (IOException e) {
            e.printStackTrace();
            Log.e(TAG, "Failed to load cascade. Exception thrown: " + e);
        }
        return classifier;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
            Uri uri = data.getData();
            try {
                Log.d("image-tag", "start to decode selected image now...");
                InputStream input = getContentResolver().openInputStream(uri);
                BitmapFactory.Options options = new BitmapFactory.Options();
                options.inJustDecodeBounds = true;
                BitmapFactory.decodeStream(input, null, options);
                int raw_width = options.outWidth;
                int raw_height = options.outHeight;
                int max = Math.max(raw_width, raw_height);
                int newWidth = raw_width;
                int newHeight = raw_height;
                int inSampleSize = 1;
                if (max > max_size) {
                    newWidth = raw_width / 2;
                    newHeight = raw_height / 2;
                    while ((newWidth / inSampleSize) > max_size || (newHeight / inSampleSize) > max_size) {
                        inSampleSize *= 2;
                    }
                }

                options.inSampleSize = inSampleSize;
                options.inJustDecodeBounds = false;
                options.inPreferredConfig = Bitmap.Config.ARGB_8888;
                selectbp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);

                myImageView.setImageBitmap(selectbp);

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

第七步:连接手机运行程序

首先要打开安卓手机的开发者模式,每个手机品牌的打开方式不一样,你自行百度一下就知道了。例如在百度中搜索“小米手机如何开启开发者模式”。

然后用数据线将手机和电脑连接起来。成功后,Android studio里面会显示你的手机型号。如下图中显示的是“Xiaomi MI 8 UD”,本例中的开发手机是小米手机。

点击上图中的“Run”-》“Run ‘app'”就可以将APP运行到手机上面了,注意手机屏幕要处于打开状态。你自拍的图片可以检测不成功,可以下载我的测试图片试试。

到此这篇关于Android 利用OpenCV制作人脸检测APP的文章就介绍到这了,更多相关Android OpenCV 人脸检测APP内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 基于Android studio3.6的JNI教程之ncnn人脸检测mtcnn功能

    代码链接: https://github.com/watersink/mtcnn-linux-as 本代码可以在模拟器下进行跑. 环境: windows10 Android studio 3.6 Sdk:android10 api 29 Ndk:r15c Ncnn:20200226 Linux下的代码测试: cd mtcnn_linux/build cmake .. make ./mtcnn 如果可以跑通,输出正确结果,证明mtcnn代码的准确性. 实际操作的时候,首先基于linux把c++代码

  • Android FaceDetector实现人脸检测功能

    关于人脸检测被折磨了半个月,前2周开需求会时需要要做一个"人脸认证上传功能,具体是打开前置摄像头,识别出用户的脸并且脸在一个指定的圆圈内然后自动保存这个状态的图像待用户是否确定上传".听到这个需求我第一时间想到比较专业的图形处理库OpenCV.去github上面搜了一下关于openCV识别人脸的demo,样例确实有点多,也确实是可以实现 但是OpenCV库实在是有点大8M,用这个库估计会被构架师说死.然后我还搜过其它的第三方库(虹软,face++,阿里云人脸检测)这几款都不是省油的灯一

  • Android 中使用 dlib+opencv 实现动态人脸检测功能

    1 概述 完成 Android 相机预览功能以后,在此基础上我使用 dlib 与 opencv 库做了一个关于人脸检测的 demo.该 demo 在相机预览过程中对人脸进行实时检测,并将检测到的人脸用矩形框描绘出来.具体实现原理如下: 采用双层 View,底层的 TextureView 用于预览,程序从 TextureView 中获取预览帧数据,然后调用 dlib 库对帧数据进行处理,最后将检测结果绘制在顶层的 SurfaceView 中. 2 项目配置 由于项目中用到了 dlib 与 open

  • Android动态人脸检测的示例代码(脸数可调)

    人脸检测 这里的人脸检测并非人脸识别,但是却可以识别出是否有人,当有人时候,你可以将帧图进行人脸识别(这里推荐Face++的sdk),当然我写的demo中没有加入人脸识别,有兴趣的朋友可以追加.face++ android自带的人脸检测 这里我们用到了人脸检测类为 FaceDetector.这个类提供了强大的人脸检测功能,可以方便我们进行人脸的侦测,因此我们使用他来进行动态的人脸检测,实现原理,其实也挺简单,主要是通过Carmen的回调PreviewCallback 在其中对帧图进行操作,并通过

  • Android中的人脸检测的示例代码(静态和动态)

    (1)背景. Google 于2006年8月收购Neven Vision 公司 (该公司拥有10多项应用于移动设备领域的图像识别的专利),以此获得了图像识别的技术,并加入到android中.Android 中的人脸识别技术,用到的底层库:android/external/neven/,framework 层:frameworks/base/media/java/android/media/FaceDetector.java. Java 层接口的限制:A,只能接受Bitmap 格式的数据:B,只能

  • Android 利用OpenCV制作人脸检测APP

    目录 前言 第一步:下载并安装Android studio 第二步:下载SDK tools 第三步:新建一个Android APP项目 第四步:下载Opencv 第五步:导入OpenCV 第六步:添加代码 第七步:连接手机运行程序 前言 本篇文章手把手教大家使用OpenCV来实现一个能在安卓手机上运行的人脸检测APP.其实不仅仅是能检测人脸,还能检测鼻子,嘴巴,眼睛和耳朵.花了不少精力写这篇文章,希望点赞收藏关注. 无图无真相,先把APP运行的结果给大家看看. 如上图所示,APP运行后,点击"选

  • Android 利用OpenCV制作人脸检测APP

    目录 前言 第一步:下载并安装Android studio 第二步:下载SDK tools 第三步:新建一个Android APP项目 第四步:下载Opencv 第五步:导入OpenCV 第六步:添加代码 第七步:连接手机运行程序 前言 本篇文章手把手教大家使用OpenCV来实现一个能在安卓手机上运行的人脸检测APP.其实不仅仅是能检测人脸,还能检测鼻子,嘴巴,眼睛和耳朵.花了不少精力写这篇文章,希望点赞收藏关注. 无图无真相,先把APP运行的结果给大家看看. 如上图所示,APP运行后,点击"选

  • C++利用opencv实现人脸检测

    小编所有的帖子都是基于unbuntu系统的,当然稍作修改同样试用于windows的,经过小编的绞尽脑汁,把刚刚发的那篇python 实现人脸和眼睛的检测的程序用C++ 实现了,当然,也参考了不少大神的博客,下面我们就一起来看看: Linux系统下安装opencv我就再啰嗦一次,防止有些人没有安装没调试出来喷小编的程序是个坑, sudo apt-get install libcv-dev sudo apt-get install libopencv-dev 看看你的usr/share/opencv

  • 基于openCV实现人脸检测

    openCV的人脸识别主要通过Haar分类器实现,当然,这是在已有训练数据的基础上.openCV安装在 opencv/opencv/sources/data/haarcascades_cuda(或haarcascades)中存在预先训练好的物体检测器(xml格式),包括正脸.侧脸.眼睛.微笑.上半身.下半身.全身等. openCV的的Haar分类器是一个监督分类器,首先对图像进行直方图均衡化并归一化到同样大小,然后标记里面是否包含要监测的物体.它首先由Paul Viola和Michael Jon

  • OpenCV实现人脸检测

    前段日子,写了个人脸检测的小程序,可以检测标记图片.视频.摄像头中的人脸.效果还行吧,用的是opencv提供人脸库.至于具体的人脸检测原理,找资料去啃吧. 环境:VS2013+OPENCV2.4.10+Win8.1 一.基于对话框的MFC 首先,新建一个基于对话框的MFC应用程序,命名为myFaceDetect(取消"安全开发周期(SDL)检查"勾选,我自己习惯取消这个). 放置Button,设置Button的ID和Caption. 图片按钮--ID:IDC_FACEDETECT 视频

  • python利用Opencv实现人脸识别功能

    本文实例为大家分享了python利用Opencv实现人脸识别功能的具体代码,供大家参考,具体内容如下 首先:需要在在自己本地安装opencv具体步骤可以问度娘 如果从事于开发中的话建议用第三方的人脸识别(推荐阿里) 1.视频流中进行人脸识别 # -*- coding: utf-8 -*- import cv2 import sys from PIL import Image def CatchUsbVideo(window_name, camera_idx): cv2.namedWindow(w

  • 手把手教你利用opencv实现人脸识别功能(附源码+文档)

    目录 一.环境 二.使用Haar级联进行人脸检测 三.Haar级联结合摄像头 四.使用SSD的人脸检测 五. SSD结合摄像头人脸检测 六.结语 一.环境 pip install opencv-python python3.9 pycharm2020 人狠话不多,直接上代码,注释在代码里面,不说废话. 二.使用Haar级联进行人脸检测 测试案例: 代码:(记得自己到下载地址下载对应的xml) # coding=gbk """ 作者:川川 @时间 : 2021/9/5 16:3

  • Java+OpenCV实现人脸检测并自动拍照

    java+opencv实现人脸检测,调用笔记本摄像头实时抓拍,人脸会用红色边框标识出来,并且将抓拍的目录存放在src下,图片名称是时间戳. 环境配置:win7 64位,jdk1.8 CameraBasic.java package com.njupt.zhb.test; import java.awt.EventQueue; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; im

  • Python基于OpenCV实现人脸检测并保存

    本文实例为大家分享了Python基于OpenCV实现人脸检测,并保存的具体代码,供大家参考,具体内容如下 安装opencv 如果安装了pip的话,Opencv的在windows的安装可以直接通过cmd命令pip install opencv-python(只需要主要模块),也可以输入命令pip install opencv-contrib-python(如果需要main模块和contrib模块) 详情可以点击此处 导入opencv import cv2 所有包都包含haarcascade文件.这

  • Python下应用opencv 实现人脸检测功能

    使用OpenCV's Haar cascades作为人脸检测,因为他做好了库,我们只管使用. 代码简单,除去注释,总共有效代码只有10多行. 所谓库就是一个检测人脸的xml 文件,可以网上查找,下面是一个地址: https://github.com/opencv/opencv/blob/master/data/haarcascades/haarcascade_frontalface_default.xml 如何构造这个库,学习完本文后可以参考: http://note.sonots.com/Sc

随机推荐