博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android实战技巧之三十:人脸检测-静态
阅读量:3724 次
发布时间:2019-05-22

本文共 4279 字,大约阅读时间需要 14 分钟。

最近微软的how-old.net把人脸识别技术又大大的火了一把。通过大数据和复杂的算法,能够神奇的预测出照片中人物的性别和年龄。虽然错误率也不低,但是大家都抱着玩一玩乐一乐的心态把照片传上去让机器来鉴定一下自己的颜龄。 
 
人脸识别算法是高深复杂的,面对着计算机视觉的种种数学公式,我就已经投降了。先来简单的玩玩人脸检测吧。Android早已提供了FaceDetector类,今天就来看看如何使用这个类人脸检测吧。

流程: 
1.打开文件夹选择照片 
2.将照片加载到bitmap中并缩放到设置的宽高 
3.用FaceDetector来检测人脸,得到Face类数组(多人脸检测) 
4.在照片bitmap检测到的人脸上面画上方框和年龄

一、选择照片

将Intent设置Type和Action,启动activity选择照片并得到照片的uri。

        Intent intent = new Intent();        intent.setType("image/*");        intent.setAction(Intent.ACTION_GET_CONTENT);        startActivityForResult(intent, OPEN_PHOTO_FOLDER_REQUEST_CODE);
  • 1
  • 2
  • 3
  • 4

二、加载照片到bitmap并缩放

新建一个类FDView继承自View,就像上一篇文章一样,对bitmap的修改用到了canvas的知识。 
有两种办法将照片加载到bitmap中: 
1.通过uri用stream的方式

    public void initBitmap(Uri uri,int width,int height) {        try {            ContentResolver resolver = mContext.getContentResolver();            BitmapFactory.Options options = new BitmapFactory.Options();            options.inPreferredConfig = Bitmap.Config.RGB_565;//need this config            Bitmap bitmap = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);            mBitmap = ThumbnailUtils.extractThumbnail(bitmap, width, height);//scale the bitmap            detectFace();        } catch (Exception ex) {            Log.e(TAG,"exception: "+ex.getMessage());        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

2.用照片的真实路径加载 
获得真实路径:

    private void initFRViewWithPath(Uri uri) {        String[] projection = {MediaStore.Images.Media.DATA};//        Cursor cursor = managedQuery(uri, projection, null, null, null);//deprecated        CursorLoader cursorLoader = new CursorLoader(this,uri,projection,null,null,null);        Cursor cursor = cursorLoader.loadInBackground();        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);        cursor.moveToFirst();        String path = cursor.getString(column_index);        Log.e(TAG,"real path: "+path);        mFRView.initBitmap(path,mFRView.getWidth(),mFRView.getHeight());    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

decodeFile:

    public void initBitmap(String path,int width,int height) {        BitmapFactory.Options options = new BitmapFactory.Options();        options.inPreferredConfig = Bitmap.Config.RGB_565;        mBitmap = BitmapFactory.decodeFile(path, options);        mBitmap = ThumbnailUtils.extractThumbnail(mBitmap,width,height);//scale the bitmap        detectFace();    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

三、人脸检测

    private void detectFace() {        if(mBitmap != null) {            mImageWidth = mBitmap.getWidth();            mImageHeight = mBitmap.getHeight();            mFaces = new FaceDetector.Face[NUMBER_OF_FACES];            mFaceDetector = new FaceDetector(mImageWidth, mImageHeight, NUMBER_OF_FACES);            mNumberOfFaceDetected = mFaceDetector.findFaces(mBitmap, mFaces);            invalidate();        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

四、人脸上画框

在onDraw中用canvas将检测到的人脸画上框并写上年龄。

    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        if(mBitmap != null) {            canvas.drawBitmap(mBitmap, 0, 0, null);            Paint paint = new Paint();            paint.setColor(Color.WHITE);            paint.setStyle(Paint.Style.STROKE);            paint.setStrokeWidth(2);            paint.setTextSize(50);            for(int i=0; i < mNumberOfFaceDetected; i++){                FaceDetector.Face face = mFaces[i];                PointF pointF = new PointF();                face.getMidPoint(pointF);                mEyesDistance = face.eyesDistance();                canvas.drawRect(                        (int)(pointF.x - mEyesDistance),                        (int)(pointF.y - mEyesDistance/2),                        (int)(pointF.x + mEyesDistance),                        (int)(pointF.y + mEyesDistance*3/2),                        paint);                canvas.drawText("28",pointF.x,pointF.y - mEyesDistance/2-5,paint);            }        }    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

最终效果图: 

源码请参考我的开源demo:

你可能感兴趣的文章
开发MFC爬取图片工具二(实现爬取图片功能)
查看>>
开发MFC界面爬取图片工具三(结合MFC界面时遇到的问题及解决方法)
查看>>
开发MFC爬取图片工具四(建立MFC应用程序)
查看>>
MFC界面爬取图片工具五(效果展示)
查看>>
opencv学习笔记九(膨胀与腐蚀及trackbar滑动条)
查看>>
OpenCV学习笔记八(图像模糊)
查看>>
opencv学习笔记10(形态学操作)
查看>>
opencv学习笔记11(形态学操作应用)
查看>>
opencv学习笔记12(图像金字塔)
查看>>
opencv学习笔记13(基本阈值操作)
查看>>
opencv学习笔记14(自定义线性滤波)
查看>>
数据动态排名工具(使用方式)
查看>>
数据动态排名工具(所有源码)
查看>>
html网页转pdf工具一(引言及使用效果)
查看>>
html网页转pdf工具二(所有源码)
查看>>
web版python软件授权注册机
查看>>
Win10下安装wireshark不能正常使用,cmd管理员身份调用net start npf命令显示无法启动该服务
查看>>
2020-11-04关于出现tomcat启动失败的一种原因
查看>>
2020-11-09
查看>>
数据挖掘课程实验(8个实验报告)
查看>>