【Android App】人脸识别中借助摄像头和OpenCV实时检测人脸讲解及实战(附源码和演示 超详细)

news2024/9/24 9:24:07

需要全部代码请点赞关注收藏后评论区留言私信~~~

一、借助摄像头实时检测人脸

与Android自带的人脸检测器相比,OpenCV具备更强劲的人脸识别功能,它可以通过摄像头实时检测人脸,实时检测的预览空间是JavaCameraView 常用方法说明如下

setCvCameraViewListener:设置OpenCV的相机视图监听器。监听器需要写下列三个状态变更方法:

onCameraViewStarted:相机视图开始预览时回调。

onCameraViewStopped:相机视图停止预览时回调。

onCameraFrame:相机视图预览变更时回调。

enableView:启用OpenCV的相机视图。

 disableView:禁用OpenCV的相机视图。

接下来把JavaCameraView加入App工程,走一遍它的详细使用过程,首先修改AndroidManifest.xml补充一行相机权限配置

<uses-permission android:name="android.permission.CAMERA"/>

实时检测人脸有如下四个步骤

(1)从布局文件中获得相机视图对象后,调用它的setCvCameraViewListener方法,设置OpenCV的相机视图监听器。

(2)OpenCV初始化与资源加载完成后,调用enableView方法开启相机视图。

(3)活动类由继承AppCompatActivity改为继承CameraActivity类,并重写getCameraViewList方法,返回相机视图的单例列表。

(4)第一步重写监听器接口的onCameraFrame方法时,补充人脸识别等处理逻辑,也就是先检测人脸,再给人脸标上相框。

二、效果展示

运行测试App 会自动打开手机摄像机 然后检测摄像机内的人脸

由顶部状态栏可以看到打开了相机功能 此处用了博主小时候的照片~~~

三、代码 

部分代码如下 需要全部源码请点赞关注收藏后评论区留言~~~

package com.example.face;

import android.content.Context;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;

import com.example.face.util.DateUtil;

import org.opencv.android.CameraActivity;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.CameraBridgeViewBase;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfRect;
import org.opencv.core.Rect;
import org.opencv.core.Scalar;
import org.opencv.core.Size;
import org.opencv.imgcodecs.Imgcodecs;
import org.opencv.imgproc.Imgproc;
import org.opencv.objdetect.CascadeClassifier;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;

//OpenCV的实时扫描页面必须继承CameraActivity
public class DetectRealtimeActivity extends CameraActivity implements CameraBridgeViewBase.CvCameraViewListener2 {
    private static final String TAG = "DetectRealtimeActivity";
    private static final Scalar FACE_RECT_COLOR = new Scalar(0, 255, 0, 255);
    private Mat mRgba, mGray; // 全彩矩阵,灰度矩阵
    private CascadeClassifier mJavaDetector; // OpenCV的人脸检测器
    private int mAbsoluteFaceSize = 0; // 绝对人脸大小
    // OpenCV默认横屏扫描,需要旋转90度改成竖屏预览,详细改动见CameraBridgeViewBase.java的deliverAndDrawFrame方法
    private CameraBridgeViewBase jcv_detect; // 声明一个OpenCV的相机视图对象

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_detect_realtime);
        findViewById(R.id.iv_back).setOnClickListener(v -> finish());
        TextView tv_title = findViewById(R.id.tv_title);
        tv_title.setText("实时检测人脸");
        jcv_detect = findViewById(R.id.jcv_detect);
        jcv_detect.setVisibility(CameraBridgeViewBase.VISIBLE);
        jcv_detect.setCvCameraViewListener(this); // 设置OpenCV的相机视图监听器
    }

    @Override
    public void onPause() {
        super.onPause();
        if (jcv_detect != null) {
            jcv_detect.disableView(); // 禁用OpenCV的相机视图
        }
    }

    @Override
    public void onResume() {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }

    @Override
    protected List<? extends CameraBridgeViewBase> getCameraViewList() {
        return Collections.singletonList(jcv_detect);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        jcv_detect.disableView(); // 禁用OpenCV的相机视图
    }

    @Override
    public void onCameraViewStarted(int width, int height) {
        mGray = new Mat();
        mRgba = new Mat();
    }

    @Override
    public void onCameraViewStopped() {
        mGray.release();
        mRgba.release();
    }

    // 相机预览回调
    @Override
    public Mat onCameraFrame(CameraBridgeViewBase.CvCameraViewFrame inputFrame) {
        mRgba = inputFrame.rgba();
        mGray = inputFrame.gray();
        Core.rotate(mRgba, mRgba, Core.ROTATE_90_CLOCKWISE); // 适配竖屏,顺时针旋转90度
        Core.rotate(mGray, mGray, Core.ROTATE_90_CLOCKWISE); // 适配竖屏,顺时针旋转90度
        if (mAbsoluteFaceSize == 0) {
            Log.d(TAG, "width="+mGray.width()+", height="+mGray.height()+", cols="+mGray.cols()+", rows="+mGray.rows());
            int height = mGray.rows();
            if (Math.round(height * 0.2f) > 0) {
                mAbsoluteFaceSize = Math.round(height * 0.2f);
            }
//            String filePath = String.format("%s/%s.jpg",
//                    getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS).toString(),
//                    DateUtil.getNowDateTime());
//            Imgcodecs.imwrite(filePath, mRgba);
//            Log.d(TAG, "filePath="+filePath);
        }
        MatOfRect faces = new MatOfRect();
        if (mJavaDetector != null) { // 检测器开始识别人脸
            mJavaDetector.detectMultiScale(mGray, faces, 1.1, 2, 2,
                    new Size(mAbsoluteFaceSize, mAbsoluteFaceSize), new Size());
        }
        Rect[] faceArray = faces.toArray();
        for (Rect rect : faceArray) { // 给找到的人脸标上相框
            Imgproc.rectangle(mRgba, rect.tl(), rect.br(), FACE_RECT_COLOR, 3);
            Log.d(TAG, rect.toString());
        }
        Core.rotate(mRgba, mRgba, Core.ROTATE_90_COUNTERCLOCKWISE); // 恢复原状,逆时针旋转90度
        return mRgba;
    }

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            if (status == LoaderCallbackInterface.SUCCESS) {
                Log.d(TAG, "OpenCV loaded successfully");
                // 在OpenCV初始化完成后加载so库
                System.loadLibrary("detection_based_tracker");
                File cascadeDir = getDir("cascade", Context.MODE_PRIVATE);
                File cascadeFile = new File(cascadeDir, "lbpcascade_frontalface.xml");
                // 从应用程序资源加载级联文件
                try (InputStream is = getResources().openRawResource(R.raw.lbpcascade_frontalface);
                     FileOutputStream os = new FileOutputStream(cascadeFile)) {
                    byte[] buffer = new byte[4096];
                    int bytesRead;
                    while ((bytesRead = is.read(buffer)) != -1) {
                        os.write(buffer, 0, bytesRead);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 根据级联文件创建OpenCV的人脸检测器
                mJavaDetector = new CascadeClassifier(cascadeFile.getAbsolutePath());
                if (mJavaDetector.empty()) {
                    Log.d(TAG, "Failed to load cascade classifier");
                    mJavaDetector = null;
                } else {
                    Log.d(TAG, "Loaded cascade classifier from " + cascadeFile.getAbsolutePath());
                }
                cascadeDir.delete();
                jcv_detect.enableView(); // 启用OpenCV的相机视图
            } else {
                super.onManagerConnected(status);
            }
        }
    };

}

创作不易  觉得有帮助请点赞关注收藏~~~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/57012.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

舵机应该如果选择?讲讲模拟舵机,数字舵机和总线舵机的区别

推荐视频&#xff1a;模拟舵机&#xff0c;数字舵机和总线舵机科普 &#xff1b;舵机从入门到放弃&#xff1b; 很多时候&#xff0c;我们购买舵机就只知道考虑扭矩以及控制方式。对舵机的分类有所耳闻&#xff0c;但是不清楚其中的区别。接下来我将详细说明模拟舵机&#xff0…

【机器学习】基于机器学习的反弹shell命令识别

引言 本文介绍一个基于机器学习识别反弹shell的项目。 在主机安全检测中&#xff0c;一般是采用基于原理的方式识别反弹shell, 通过判断socket通信相关特征&#xff0c;可以准确地识别到主机中的反弹shell。 但是在容器场景下&#xff0c;检测反弹shell 的能力&#xff0c;可能…

[附源码]计算机毕业设计springboot疫情物资管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

2022年第十一届认证杯数学中国数学建模国际赛小美赛:C 题 对人类活动进行分类 建模方案及代码实现

2022年第十一届认证杯数学中国数学建模国际赛小美赛&#xff1a;C 题 对人类活动进行分类 建模方案及代码实现 1 题目 人类行为理解的一个重要方面是对日常活动的识别和监控。可穿戴活动识别系统可以在许多关键领域提高生活质量&#xff0c;如门诊监测、居家康复、跌倒检测等。…

[附源码]Python计算机毕业设计Django茂名特产销售商城网站

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

[Java安全]—再探Filter内存马

前言 关于tomcat反序列化注入回显内存马问题中&#xff0c;就是通过filter内存马进行反序列化动态注册的&#xff0c;但filter内存马由于当时学的时候就没有学的很明白&#xff0c;所以打算重新回顾一下。 前置知识 Tomcat 与 Servlet 的关系 Tomcat中有四种类型的Servlet容…

[Python私活案例]24行代码,轻松赚取400元,运用Selenium爬取39万条数据

今天分享一单来自金主爸爸的私单&#xff0c;运用简单的爬虫技巧&#xff0c;可以有效的规避反爬机制&#xff0c;正所谓“你有张良计&#xff0c;我有过云梯”。这个案例也很好的体现了python语音的优势&#xff0c;规避了非常复杂的底层逻辑&#xff0c;所见即所得&#xff0…

你真的看懂扩散模型(diffusion model)了吗?(从DALL·E 2讲起,GAN、VAE、MAE都有)

本文全网原创于CSDN&#xff1a;落难Coder &#xff0c;未经允许&#xff0c;不得转载&#xff01; 扩散模型简单介绍 我们来讲一下什么是扩散模型&#xff0c;如果你不了解一些工作&#xff0c;你可能不清楚它究竟是什么。那么我举两个例子说一下&#xff1a;AI作画&#xff…

分布滞后线性和非线性模型(DLNM)分析空气污染(臭氧)、温度对死亡率时间序列数据的影响...

全文下载链接 http://tecdat.cn/?p23947 分布滞后非线性模型&#xff08;DLNM&#xff09;表示一个建模框架&#xff0c;可以灵活地描述在时间序列数据中显示潜在非线性和滞后影响的关联。该方法论基于交叉基的定义&#xff0c;交叉基是由两组基础函数的组合表示的二维函数空间…

为什么要让img浮动:

为什么要浮动&#xff1a; 图片不浮动的话&#xff0c;图片和文字是像下面这样排版的&#xff1a; 代码&#xff1a; <img src"https://static.maizuo.com/pc/v5/usr/movie/1f25dd6943762288dfd84b961c98f478.jpg" /> <div><div>红发歌姬</d…

OpenAI发布ChatGPT:程序员瞬间不淡定了

OpenAI发布ChatGPT&#xff1a;程序员瞬间不淡定了 12月1日&#xff0c;OpenAI发布了针对对话场景优化的语言大模型ChatGPT。ChatGPT是InstructGPT的兄弟模型&#xff0c;可以以对话的形式与用户交互&#xff0c;这使得ChatGPT能够回答问题、承认错误、质疑假设、拒绝不当问题…

时尚品牌Gucci 的Web3元宇宙营销进行时ing

Gucci 宣布在 The Sandbox 中推出 “Gucci Vault Land” 古驰藏宝阁 —— 元宇宙中心 &#xff0c;成为第一个在 The Sandbox 虚拟世界中拥有专门用于 Web3 产品的主流时尚品牌。Gucci 美学概念空间开放日&#xff1a;10月27日-11月 9 日 2022 年 Gucci Vault Land建立虚拟世界…

数据结构薄弱知识点

数据结构串KMP算法树二叉树二叉树的基本概念二叉树的遍历&#xff08;&#xff01;非递归实现&#xff09;先序遍历中序遍历后序遍历&#xff08;&#x1f538;非递归实现&#xff09;&#x1f536;线索二叉树找先序遍历的前驱节点&#xff08;&#x1f538;&#xff09;和后继…

Spring学习:二、Bean的管理

4. Bean的管理 ​ Spring的基本Bean管理包括Bean配置&#xff0c;Bean实例化和Bean的依赖注入。这些管理可以通过手工编码的方式把每个Bean注册到容器中&#xff0c;也可以通过properties文件和xml文件配置Bean和Bean之间的依赖关系。通常我们的配置方式是XML作为配置文件。 …

基于纳芯微产品的尾灯方案介绍

文章目录1.前言2.方案简介2.1 概述2.2 功能介绍2.3 DEMO资料3.主要器件介绍3.1 LED Driver3.2 LDO3.3 CAN\LIN收发器4.演示视频5.推荐阅读1.前言 最近拜访一些做尾灯模组的客户了解到&#xff0c;目前LED Driver依然紧缺&#xff0c;特别是TPS929120&#xff0c;BD18331这些差…

网络编程,UDP通信程序,TCP通信程序

一、网络编程 网络编程概述 网络编程 : 在网络[通信协议]下&#xff0c;不同计算机上运行的程序&#xff0c;可以进行[数据传输] 思考&#xff1a; A电脑中的QQ&#xff0c;发送消息给B电脑中的QQ。那么需要知道[哪些条件]才能发送&#xff1f; 在这个故事场景下&…

GitHub 的基本使用

文章目录一、使用前工作二、GitHub 的基本使用一、使用前工作 下载 uu 加速器&#xff0c;用于访问 GitHub 网站&#xff08;有魔法工具的小伙伴请忽略&#xff09;&#xff1b;uu 加速器下载安装完毕后搜索框搜索学术资源并点击加速&#xff08;如图1.2.1&#xff09;&#xf…

【Android App】人脸识别中使用Opencv比较两张人脸相似程度实战(附源码和演示 超详细)

需要全部代码请点赞关注收藏后评论区留言私信~~~ 一、比较两张人脸的相似程度 直方图由一排纵向的竖条或者竖线组成&#xff0c;横轴代表数据类型&#xff0c;纵轴代表数据多少。 图像直方图经常应用于特征提取、图像匹配等方面。 假设有两幅图像&#xff0c;它们的直方图很相…

Vue项目devServer.proxy代理配置详解

Vue项目devServer.proxy代理配置详解目录概述需求&#xff1a;设计思路实现思路分析1..config.js文件中&#xff0c;引入依赖项2.devServer.proxy 可以是一个指向开发环境 API 服务器的字符串3.更多控制行为参考资料和推荐阅读Survive by day and develop by night. talk for i…

语言模型也会“地域黑”?实验表明ALBERT最能黑,BART最友善

文 | ZenMoore前言今天我们来谈论一个不那么硬核的问题&#xff1a;预训练语言模型中的歧视与偏见(bias)。这个问题虽然不像技术问题那样核心&#xff0c;但仍然非常重要。想象一下&#xff1a;你接到了一笔外交级别的订单&#xff0c;要做一个生成语言模型&#xff0c;先不论效…