Android+openCV 动态人脸检测
动态人脸检测前提是需要打开摄像头。
网上看了很多教程,我知道的有两种方式打开摄像头:
JavaCameraView mCameraView = new JavaCameraView(this, -1);
setContentView(mCameraView);
mCameraView.setCvCameraViewListener(this); mCameraView.enableView();
第2种:在布局文件中添加 CameraBridgeViewBase
mCameraView = (CameraBridgeViewBase) findViewById(R.id.java_surface_view);
mCameraView.setCvCameraViewListener(this);
mCameraView.enableView();
以上两种获取摄像头实时视频流方式需要 implements CameraBridgeViewBase.CvCameraViewListener
public class FaceTrackingActivity extends AppCompatActivity implements CameraBridgeViewBase.CvCameraViewListener {
@Overrid
protected void onCreate(Bundle savedInstanceState) {
...
} @Override
public void onCameraViewStarted(int width, int height) { } @Override
public void onCameraViewStopped() { } @Override
public Mat onCameraFrame(Mat inputFrame) {
return null;
}
}
onCameraFrame 函数中将捕获视频每一帧。
这样我在预览视频的时候,发现很难控制大小,以及摄像头的方向。
后来我直接采用以往的camera类去操作视频流。
以上参考:http://blog.csdn.net/tobacco5648/article/details/51615632
实时处理摄像头预览帧视频参考:http://blog.csdn.net/yanzi1225627/article/details/8605061
定义 SurfaceView
<SurfaceView
android:id="@+id/java_surface_view"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
mSurfaceView = (SurfaceView) findViewById(R.id.java_surface_view);
mSurfaceHolder = mSurfaceView.getHolder(); // mSurfaceView 不需要自己的缓冲区
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
// mSurfaceView添加回调
mSurfaceHolder.addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder holder) { //SurfaceView创建
try {
cameraManager = new CameraManager(FaceTrackingActivity.this, mObjectDetects, cimbt, mSurfaceHolder);
cameraManager.openDriver();
cameraManager.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
} @Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { } @Override
public void surfaceDestroyed(SurfaceHolder holder) { //SurfaceView销毁
holder.removeCallback(this); // Camera is being used after Camera.release() was called
cameraManager.stopPreview();
cameraManager.closeDriver(); }
});
我这里独立出来了一个 CameraManager 类,本来我想把检测的代码写在 CameraManager 类之外,然而并没有实现:
CameraManager 类中 implements Camera.PreviewCallback 可以实现 onPreviewFrame 对实时数据处理:
@Override
public void onPreviewFrame(byte[] bytes, Camera camera) {
Camera.Size previewSize = camera.getParameters().getPreviewSize(); Bitmap bitmap = ByteToBitmap(bytes, previewSize);
//Bitmap bitmap = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);//将data byte型数组转换成bitmap文件 final Matrix matrix = new Matrix();//转换成矩阵旋转90度
if (cameraPosition == 1) {
matrix.setRotate(90);
} else {
matrix.setRotate(-90);
}
bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(), matrix, true);//旋转图片 Mat grayscaleImage = new Mat(previewSize.height, previewSize.width, CvType.CV_8UC4);
int absoluteFaceSize = (int) (previewSize.height * 0.2); if (bitmap != null) {
Mat inputFrame = new Mat();
Utils.bitmapToMat(bitmap, inputFrame); if (!bitmap.isRecycled()) {
bitmap.recycle();
} // Create a grayscale image
Imgproc.cvtColor(inputFrame, grayscaleImage, Imgproc.COLOR_RGBA2RGB); MatOfRect mRect = new MatOfRect(); int maxRectArea = 0 * 0;
Rect maxRect = null; int facenum = 0; for (ObjectDetector detector : mObjectDetects) {
// 检测目标
Rect[] object = detector.detectObjectImage(inputFrame, mRect);
Log.e(TAG, object.length + ""); for (Rect rect : object) {
++facenum;
// 找出最大的面积
int tmp = rect.width * rect.height;
if (tmp >= maxRectArea) {
maxRectArea = tmp;
maxRect = rect;
}
}
} Bitmap rectBitmap = null;
if (facenum != 0) {
// 剪切最大的头像
//Log.e("剪切的长宽", String.format("高:%s,宽:%s", maxRect.width, maxRect.height));
Rect rect = new Rect(maxRect.x, maxRect.y, maxRect.width, maxRect.height);
Mat rectMat = new Mat(inputFrame, rect); // 从原始图像拿
rectBitmap = Bitmap.createBitmap(rectMat.cols(), rectMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(rectMat, rectBitmap); Bitmap resizeBmp = cimbt.resizeBitmap(rectBitmap, cimbt.getWidth(), cimbt.getHeight());
cimbt.setBitmap(resizeBmp);
} else {
cimbt.clearnImage();
cimbt.setText("没有检测到人脸");
}
} }
补充:在初始化相机时激活onPreviewFrame
camera.setPreviewCallback(this);
//camera.setOneShotPreviewCallback(this); // 激活 onPreviewFrame 执行一次
整个人脸静态动态检测源代码: https://github.com/haoxr/faceDetection
动态检测截图:
Android+openCV 动态人脸检测的更多相关文章
- python中使用Opencv进行人脸检测
这两天学习了人脸识别,看了学长写的代码,边看边码边理解搞完了一边,再又是自己靠着理解和记忆硬码了一边,感觉还是很生疏,就只能来写个随笔加深一下印象了. 关于人脸识别,首先需要了解的是级联分类器Casc ...
- 【转载】opencv实现人脸检测
全文转载自CSDN的博客(不知道怎么将CSDN的博客转到博客园,应该没这功能吧,所以直接复制全文了),转载地址如下 http://blog.csdn.net/lsq2902101015/article ...
- OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现
# OpenCV学习系列(一) Mac下OpenCV + xcode人脸检测实现 [-= 博客目录 =-] 1-学习目标 1.1-本章介绍 1.2-实践内容 1.3-相关说明 2-学习过程 2.1-环 ...
- OpenCV实现人脸检测
OpenCV实现人脸检测(转载) 原文链接:https://www.cnblogs.com/mengdd/archive/2012/08/01/2619043.html 本文介绍最基本的用OpenC ...
- Android 中使用 dlib+opencv 实现动态人脸检测
1 概述 完成 Android 相机预览功能以后,在此基础上我使用 dlib 与 opencv 库做了一个关于人脸检测的 demo.该 demo 在相机预览过程中对人脸进行实时检测,并将检测到的人脸用 ...
- 利用html5、websocket和opencv实现人脸检测
最近学习人脸识别相关的东西,在MFC下使用OpenCV做了一个简单的应用.训练需要较多的数据,windows应用程序终究还是不方便,于是想着做成CS模式:检测识别都放在服务器端,视频获取和显示都放在网 ...
- 基于OpenCv的人脸检测、识别系统学习制作笔记之三
1.在windows下编写人脸检测.识别系统.目前已完成:可利用摄像头提取图像,并将人脸检测出来,未进行识别. 2.在linux下进行编译在windows环境下已经能运行的代码. 为此进行了linux ...
- 基于OpenCv的人脸检测、识别系统学习制作笔记之一
基于OpenCv从视频文件到摄像头的人脸检测 在OpenCv中读取视频文件和读取摄像头的的视频流然后在放在一个窗口中显示结果其实是类似的一个实现过程. 先创建一个指向CvCapture结构的指针 Cv ...
- Python学习--使用dlib、opencv进行人脸检测标注
参考自https://www.pyimagesearch.com/2017/04/03/facial-landmarks-dlib-opencv-python/ 在原有基础上有一部分的修改(image ...
随机推荐
- 【CQOI2017】【BZOJ4813】小Q的棋盘 DFS
题目描述 有一棵树,你要从\(0\)号点开始走,你可以走\(m\)步,问你最多能经过多少个不同的点. \(n\leq 100\) 题解 出题人的做法是DP(一个简单的树形DP),但是可以直接通过一次D ...
- Java【第二篇】基本语法之--进制、运算符
进制 对于整数,有四种表示方式: 二进制:0,1 ,满 2 进 1.以 0b 或 0B 开头. 十进制:0-9 ,满 10 进 1. 八进制:0-7 ,满 8 进1. 以数字 0 开头表示. 十六进制 ...
- php+mysql+nginx+liunx 服务搭建
安装php7相应的yum源 CentOS 7.x: # rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7 ...
- Redmine简易安装与系统优化
安装版本为bitnami-redmine-2.6.5-0 ,用的Bitnami的一键安装包 . 下载地址https://bitnami.com/stack/redmine/installer 简要安装 ...
- 如果固定电脑ip地址
打开网络和共享中心 点击详细信息,即可看到IP地址.子网掩码.默认网关.DNS服务器信息 点击本WLAN状态->属性 找到Internet 协议版本 4(TCP/IPv4) 用鼠标左键单击两下 ...
- 计算机基础理论知识梳理篇(一):数据类型长度、内存页、IPC
字长与数据类型长度 字长指CPU在同一时间能够处理二进制数据的位数,是由其外接数据总线(地址总线决定了CPU的寻址空间,如16位微型机的地址总线为20位,其可寻址空间为220 = 1MB)的条数决定的 ...
- centos中编译安装nginx+mysql +php(未完)
参考地址:http://www.cnblogs.com/htian/p/5728599.html 去官网找到PCRE,并下载http://www.pcre.org/wget ftp://ftp.csx ...
- Linux性能优化实战:到底应该怎样理解平均负载(02)
一.平均负载与CPU使用率并没有直接关系 1.平均负载 单位时间内,系统处于可运行状态和不可终端状态的平均进程数也就是平均活跃进程数,它和cpu使用率并没有直接关系, 可运行状态: 正在使用的cpu或 ...
- 第六节: EF高级属性(二) 之延迟加载、立即加载、显示加载(含导航属性)
一. 简介 上一个章节中,也介绍了立即加载和延迟加载,但上一个章节是针对单表而言的,不含外键,立即也好,延迟也好,都是指单表中的数据.但本章节重点介绍的三种加载方式均是针对含(导航属性.外键)的情况下 ...
- [物理学与PDEs]第1章习题3 常场强下电势的定解问题
在一场强为 ${\bf E}_0$ (${\bf E}_0$ 为常向量) 的电场中, 置入一个半径为 $R$ 的导电球体, 试导出球外电势所满足的方程及相应的定解条件. 解答: 设导电球体为 $B_R ...