android人脸识别——HowOld测测你的年龄和性别

引言

这段时间微软的HowOldRobot 测试年龄的网站非常火,访问量已经爆棚了!不过,这个测试也有很多比较坑爹的地方。比如:。。。。。

再比如。。。

好了 言归正传!今天我们就来看看android中怎么利用人脸识别功能来实现我们自己的HowOld APP

(PS:本人也是借鉴了网上大神的视频和资料 然后自己加以改进)

Face++ API

想要使用人脸识别功能,我们需要调用Face++中的一些API来完成工作。Face++的官网地址是:http://www.faceplusplus.com.cn/

使用Face++有几个步骤:

1.注册账号

2.创建应用

3.复制 Key 和 Sercret

4.下载SDK

5.将SDK放入我们的工程lib目录中

好了 准备工作做完了,接下来就开始编写我们的程序了。

布局

首先是布局文件。下面是我们的界面视图。很简单的布局,上边一张图片 ,下边一个TextView加三个按钮 。没有太多好说的。

MainActivity.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F89921"
    android:orientation="vertical"
    tools:context="com.game.howold.MainActivity" >

    <ImageView
        android:id="@+id/face_image"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="80dp"
        android:layout_weight="3"
        android:scaleType="fitXY"
        android:src="@drawable/level1" />

    <LinearLayout
        android:minHeight="80dp"
        android:id="@+id/bottom_layout"
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        android:layout_gravity="center_horizontal"
        android:layout_weight="1"
        android:orientation="horizontal"
        android:gravity="center_horizontal|bottom"
        android:padding="10dp" >
    <TextView
            android:id="@+id/tip"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:text="有2只脸"
            android:textColor="#55000000"
            android:textSize="20sp"
            android:textStyle="bold" />
       <ImageButton
            android:id="@+id/detect"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:background="@drawable/detect" />
        <ImageButton
            android:id="@+id/open_photo"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:background="@drawable/photo" />

        <ImageButton
            android:id="@+id/open_camera"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:background="@drawable/camera" />

    </LinearLayout>

</LinearLayout>

人脸识别工具类

接下来, 我们需要编写一个人脸识别工具类,根据我们传入的图片来进行识别并返回数据。其中Constact是我们的常量工具类,存放我们应用的Key和Secret.

FaceRecognize.class

public class FaceRecognize
{
    // 回调接口
    public interface CallBack
    {
        // 识别成功
        void success(JSONObject result);

        // 识别失败
        void error(FaceppParseException e);
    }

    // 开始识别
    public static void detect(final Bitmap bitmap, final CallBack callback)
    {
        new Thread(new Runnable()
        {
            @Override
            public void run()
            {
                HttpRequests request = new HttpRequests(Constant.KEY,
                        Constant.SECRET, true, true);
                Bitmap bmSmall = Bitmap.createBitmap(bitmap, 0, 0,
                        bitmap.getWidth(), bitmap.getHeight());
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                //压缩图片
                bmSmall.compress(Bitmap.CompressFormat.JPEG, 100, baos);
                byte[] datas = baos.toByteArray();
                PostParameters params = new PostParameters();
                params.setImg(datas);
                try
                {
                    //如果识别成功,调用success回调函数
                    JSONObject result = request.detectionDetect(params);
                    if (callback != null)
                    {
                        callback.success(result);
                    }
                } catch (FaceppParseException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    if (callback != null)
                    {
                        callback.error(e);
                        Log.e("JSONObject", e.toString());
                    }
                }
            }
        }).start();
    }
}

程序主要逻辑

然后我们在MainActivity中实现我们的主要逻辑。

MainActivity.class

public class MainActivity extends Activity implements OnClickListener
{
    //从相册选择照片
    private static final int PICK_CODE = 0X110;
    //照相
    private static final int TAKE_PICTURE = 0X114;
    //识别成功
    private static final int MSG_SUCCESS = 0X111;
    //识别失败
    private static final int MSG_ERROR = 0X112;
    //剪裁图片
    private static final int CROP_PHOTO = 0x115;

    private ImageButton detect, camera, photo;
    private TextView tip, ageAndgender;
    private ImageView img;
    private String mCurrentPhotoPath;
    private Bitmap mPhotoImg;
    private Canvas mCanvas;
    private Paint mPaint;

    //自定义对话框
    private CustomProgressDialog dialog;

    private Uri imageUri;
    private String filename;

    private boolean isCamera =false;

    private Dialog dialogs;

    private Handler mHandler = new Handler()
    {
        public void handleMessage(android.os.Message msg)
        {
            switch (msg.what)
            {
                //解析成功
                case MSG_SUCCESS:
                    dialog.dismiss();
                    //获取JSON数据
                    JSONObject result = (JSONObject) msg.obj;
                    //解析JSON数据
                    parseResult(result);
                    img.setImageBitmap(mPhotoImg);
                    break;
                    //解析失败
                case MSG_ERROR:
                    dialog.dismiss();
                    String errorMsg = (String) msg.obj;
                    if (TextUtils.isEmpty(errorMsg))
                    {
                        tip.setText("Error!!");
                    }
                    break;

                default:
                    break;
            }
        };
    };

在上面的代码片段中,我们定义了一些常量和控件,并且使用handler来处理 识别成功和识别失败两种情况。

/**
     * 解析JSON数据
     * @param object
     */
    private void parseResult(JSONObject object)
    {
        Bitmap bitmap = Bitmap.createBitmap(mPhotoImg.getWidth(),
                mPhotoImg.getHeight(), mPhotoImg.getConfig());
        mCanvas = new Canvas(bitmap);
        mCanvas.drawBitmap(mPhotoImg, 0, 0, null);
        mPaint.setColor(Color.RED);
        mPaint.setAntiAlias(true);
        mPaint.setStrokeWidth(3);
        mPaint.setStrokeCap(Cap.ROUND);
        JSONArray faces;
        try
        {
            faces = object.getJSONArray("face");
            int faceCount = faces.length();
            //未识别出人脸
            if (faceCount == 0)
            {
                dialogs = new AlertDialog.Builder(this)
                        .setTitle("检测结果")
                        .setMessage("长得太抽象o(╯□╰)o,识别不出来")
                        .setNegativeButton("重来",
                                new DialogInterface.OnClickListener()
                                {

                                    @Override
                                    public void onClick(DialogInterface dialog,
                                            int which)
                                    {
                                        dialogs.dismiss();
                                    }
                                }).create();
                dialogs.show();
                return;
            }
            tip.setText("发现 " + faceCount + "只 脸 ");
            //循环处理每一张脸
            for (int i = 0; i < faceCount; i++)
            {
                JSONObject face = faces.getJSONObject(i);
                JSONObject position = face.getJSONObject("position");
                //脸部中心点X坐标
                float x = (float) position.getJSONObject("center").getDouble(
                        "x");
                //脸部中心点Y坐标
                float y = (float) position.getJSONObject("center").getDouble(
                        "y");
                //脸部宽度
                float width = (float) position.getDouble("width");
                //脸部高度
                float height = (float) position.getDouble("height");

                x = x / 100 * bitmap.getWidth();
                y = y / 100 * bitmap.getHeight();
                width = width / 100 * bitmap.getWidth();
                height = height / 100 * bitmap.getHeight();
                //绘制年龄性别的显示框
                mCanvas.drawLine(x - width / 2, y - height / 2, x - width / 2,
                        y + height / 2, mPaint);
                mCanvas.drawLine(x - width / 2, y - height / 2, x + width / 2,
                        y - height / 2, mPaint);
                mCanvas.drawLine(x + width / 2, y - height / 2, x + width / 2,
                        y + height / 2, mPaint);
                mCanvas.drawLine(x - width / 2, y + height / 2, x + width / 2,
                        y + height / 2, mPaint);

                int age = face.getJSONObject("attribute").getJSONObject("age")
                        .getInt("value");
                String gender = face.getJSONObject("attribute")
                        .getJSONObject("gender").getString("value");

                Bitmap ageBitmap = buildAgeBitmap(age, gender.equals("Male"));
                int ageWidth = ageBitmap.getWidth();
                int ageHeight = ageBitmap.getHeight();
                //对年龄性别的显示框大小进行调整
                if (bitmap.getWidth() < img.getWidth()
                        && bitmap.getHeight() < img.getHeight())
                {

                    float ratio = Math.max(
                            bitmap.getWidth() * 1.0f / img.getWidth(),
                            bitmap.getHeight() * 1.0f / img.getHeight());

                    ageBitmap = Bitmap.createScaledBitmap(ageBitmap,
                            (int) (ageWidth * ratio),
                            (int) (ageHeight * ratio), false);
                }
                mCanvas.drawBitmap(ageBitmap, x - ageBitmap.getWidth() / 2, y
                        - height / 2 - ageBitmap.getHeight(), null);
                mPhotoImg = bitmap;
            }
        } catch (JSONException e)
        {
            e.printStackTrace();
        }

    }

在parseRusult方法中, 我们解析从服务器中返回的JSON数据,然后获取到我们想要的年龄和性别,脸部位置等数据。

用于服务器返回的脸部中心坐标和宽高等数据是使用在图片中的百分比所表示的,所以我们需要做下面的处理将之转换成真实像素位置。

    //脸部中心点X坐标
                float x = (float) position.getJSONObject("center").getDouble(
                        "x");
                //脸部中心点Y坐标
                float y = (float) position.getJSONObject("center").getDouble(
                        "y");
                //脸部宽度
                float width = (float) position.getDouble("width");
                //脸部高度
                float height = (float) position.getDouble("height");

                x = x / 100 * bitmap.getWidth();
                y = y / 100 * bitmap.getHeight();
                width = width / 100 * bitmap.getWidth();
                height = height / 100 * bitmap.getHeight();

然后 ,我们绘制脸部的识别框,就是示例图中的那个红色方框。他们是四条线段绘制的。

    //绘制年龄性别的显示框
                mCanvas.drawLine(x - width / 2, y - height / 2, x - width / 2,
                        y + height / 2, mPaint);
                mCanvas.drawLine(x - width / 2, y - height / 2, x + width / 2,
                        y - height / 2, mPaint);
                mCanvas.drawLine(x + width / 2, y - height / 2, x + width / 2,
                        y + height / 2, mPaint);
                mCanvas.drawLine(x - width / 2, y + height / 2, x + width / 2,
                        y + height / 2, mPaint);

下一步,我们还需要将 表示性别和年龄的显示框绘制在相应的人脸框的上边,并对显示框做相应的校正,防止其过大。

    int age = face.getJSONObject("attribute").getJSONObject("age")
                        .getInt("value");
    String gender = face.getJSONObject("attribute")
                        .getJSONObject("gender").getString("value");
                //年龄显示框的图像
    Bitmap ageBitmap = buildAgeBitmap(age, gender.equals("Male"));
                int ageWidth = ageBitmap.getWidth();
                int ageHeight = ageBitmap.getHeight();
                //对年龄性别的显示框大小进行调整
                if (bitmap.getWidth() < img.getWidth()
                        && bitmap.getHeight() < img.getHeight())
                {

                    float ratio = Math.max(
                            bitmap.getWidth() * 1.0f / img.getWidth(),
                            bitmap.getHeight() * 1.0f / img.getHeight());

                    ageBitmap = Bitmap.createScaledBitmap(ageBitmap,
                            (int) (ageWidth * ratio),
                            (int) (ageHeight * ratio), false);
                }
                mCanvas.drawBitmap(ageBitmap, x - ageBitmap.getWidth() / 2, y
                        - height / 2 - ageBitmap.getHeight(), null);
                mPhotoImg = bitmap;
            }
        } catch (JSONException e)
        {
            e.printStackTrace();
        }

    }

我们的性别年龄显示框其实就是一个TextView ,并在左边通过drawableLeft设置了表示性别的图片。buildAgeBitmap函数用于将TextView转换为Bitmap对象

        //绘制年龄性别显示框,将TextView转换为Bitmap对象
    private Bitmap buildAgeBitmap(int age, boolean isMale)
    {
        ageAndgender = (TextView) getLayoutInflater().inflate(
                R.layout.age_layout, null);
        ageAndgender.setText(age + "");
        if (isMale)
        {
            ageAndgender.setCompoundDrawablesWithIntrinsicBounds(getResources()
                    .getDrawable(R.drawable.male), null, null, null);
        } else
        {
            ageAndgender.setCompoundDrawablesWithIntrinsicBounds(getResources()
                    .getDrawable(R.drawable.female), null, null, null);
        }
        ageAndgender.setDrawingCacheEnabled(true);
        ageAndgender.measure(
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED),
                MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
        ageAndgender.layout(0, 0, ageAndgender.getMeasuredWidth(),
                ageAndgender.getMeasuredHeight());
        ageAndgender.buildDrawingCache();
        Bitmap bitmap = Bitmap.createBitmap(ageAndgender.getDrawingCache());
        return bitmap;
    }

其中age_layout.xml就是性别年龄显示框的布局文件。

age_layout.xml

<?xml version="1.0" encoding="utf-8"?>

   <TextView
       xmlns:android="http://schemas.android.com/apk/res/android"
            android:id="@+id/ageAndgender"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/hint"
            android:drawableLeft="@drawable/male"
            android:textStyle="bold"
            android:gravity="center"
            android:text="12"
            android:textColor="#ffff0000"
            android:textSize="22sp"
            android:visibility="invisible" />

拍照、相册、识别处理

最后,我们需要对底部的拍照、相册选择图片和识别按钮进行处理。

@Override
    public void onClick(View v)
    {
        switch (v.getId())
        {
            //打开相册 选取图片
            case R.id.open_photo:
                Intent intent = new Intent();
                intent.setAction(Intent.ACTION_PICK);
                intent.setType("image/*");
                startActivityForResult(intent, PICK_CODE);
                break;
            //照相并获取图片
            case R.id.open_camera:
                //图片名称 时间命名
      SimpleDateFormat format = new SimpleDateFormat("yyyyMMddHHmmss");
                Date date = new Date(System.currentTimeMillis());
             filename = format.format(date);
        //创建File对象用于存储拍照的图片 SD卡根目录
        File path = Environment.getExternalStorageDirectory();

             File outputImage = new File(path,filename+".jpg");
                try {
                    if(outputImage.exists()) {
                        outputImage.delete();
                    }
                    outputImage.createNewFile();
                } catch(IOException e) {
                    e.printStackTrace();
                }
                //将File对象转换为Uri并启动照相程序
                imageUri = Uri.fromFile(outputImage);
                Intent cameras = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //照相
                cameras.putExtra(MediaStore.EXTRA_OUTPUT, imageUri); //指定图片输出地址
                startActivityForResult(cameras,TAKE_PICTURE); //启动照相
                //拍完照startActivityForResult() 结果返回onActivityResult()函数

                break;
                //开始识别
            case R.id.detect:
                if (mCurrentPhotoPath != null
                        && !mCurrentPhotoPath.trim().equals(""))
                {
                    resizePhoto();
                } else if(!isCamera)
                {
                    //重置默认图片
                    mPhotoImg = BitmapFactory.decodeResource(getResources(),
                            R.drawable.level1);
                }

                dialog.show();

//对图片进行识别
    FaceRecognize.recognize(mPhotoImg, new CallBack()
                {

                    @Override
                    public void success(JSONObject result)
                    {
                        Message msg = Message.obtain();
                        msg.what = MSG_SUCCESS;
                        msg.obj = result;
                        mHandler.sendMessageDelayed(msg, 500);
                    }

                    @Override
                    public void error(FaceppParseException e)
                    {
                        Message msg = Message.obtain();
                        msg.what = MSG_ERROR;
                        msg.obj = e.getErrorMessage();
                        mHandler.sendMessageDelayed(msg, 500);
                    }
                });
                break;
        }
    }

在OnActivityResult回调方法中,我们分别处理拍照、相册选择照片和图片裁剪等操作。

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data)
    {
        switch (requestCode)
        {
            //从相册中选择相片
            case PICK_CODE:
                if (data != null)
                {
                    Uri uri = data.getData();
                    Cursor cursor = getContentResolver().query(uri, null, null,
                            null, null);
                    cursor.moveToFirst();
                    int index = cursor
                            .getColumnIndex(MediaStore.Images.ImageColumns.DATA);
                    mCurrentPhotoPath = cursor.getString(index);
                    cursor.close();

                    // 压缩照片
                    resizePhoto();
                    img.setImageBitmap(mPhotoImg);
                    tip.setText("Detect-->");
                }
                break;
                //照相
    case TAKE_PICTURE:
        if (resultCode == RESULT_OK)
        {

            //我们需要对图片进行剪裁
            Intent intent = new Intent("com.android.camera.action.CROP"); //剪裁
            intent.setDataAndType(imageUri, "image/*");
            intent.putExtra("scale", true);
            //设置宽高比例
            intent.putExtra("aspectX", 1);
            intent.putExtra("aspectY", 1);
            //设置裁剪图片宽高
            intent.putExtra("outputX", 340);
            intent.putExtra("outputY", 340);
            intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);
            Toast.makeText(MainActivity.this, "剪裁图片", Toast.LENGTH_SHORT).show();
            //广播刷新相册
            Intent intentBc = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
            intentBc.setData(imageUri);
            this.sendBroadcast(intentBc);
            startActivityForResult(intent, CROP_PHOTO); //设置裁剪参数显示图片至ImageView

        }
                break;
                //剪裁图片
    case CROP_PHOTO:
                //图片解析成Bitmap对象
                try
                {
                    //Bitmap bitmap = MediaStore.Images.Media.getBitmap(this.getContentResolver(), imageUri);
                    mPhotoImg = BitmapFactory.decodeStream(
                            getContentResolver().openInputStream(imageUri));
                    Toast.makeText(MainActivity.this, imageUri.toString(), Toast.LENGTH_SHORT).show();
                    isCamera=true;
                    img.setImageBitmap(mPhotoImg);
                    tip.setText("Detect-->"); //将剪裁后照片显示出来
                } catch (FileNotFoundException e)
                {
                    e.printStackTrace();
                } 

                break;
        }

        super.onActivityResult(requestCode, resultCode, data);
    }

注意,从相册中选择的图片,我们需要重新调整其大小,防止其尺寸过大而使得程序崩溃。resizeBitmap方法用于调整图片大小

//重置图片的大小 对图片进行压缩
    private void resizePhoto()
    {
        BitmapFactory.Options options = new BitmapFactory.Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeFile(mCurrentPhotoPath, options);
        double scaleRatio = Math.max(options.outWidth * 1.0d / 1024f,
                options.outHeight * 1.0d / 1024f);
        options.inSampleSize = (int) Math.ceil(scaleRatio);
        options.inJustDecodeBounds = false;
        mPhotoImg = BitmapFactory.decodeFile(mCurrentPhotoPath, options);
    }

测试

最后 ,对我们的程序进行测试~

测试结果嘛。。。。。还是阔以的!

源码下载

时间: 2024-08-27 23:12:32

android人脸识别——HowOld测测你的年龄和性别的相关文章

Android人脸识别技术

Android人脸识别技术用到的底层库:android/external/neven/,framework 层:frameworks/base/media/java/android/media/FaceDetector.java. java层接口的限制: 1.只能接受bitmap的数据. 2.只能识别出双眼睛距离不大于20像素的人脸. 3.只能检测人脸的位置,不能对人脸匹配. 下面代码的运行效果: @Override protected void onCreate(Bundle savedIns

Android 人脸识别源码APP后台接口设计

Android softboy人脸识别源码APP后台接口设计,这个是最近开发的一个人脸识别人脸系统框架,系统内容比较复杂.这里简化了主要的接口与数据,然后结合 softboy人脸识别app,就可以体验极速的人脸识别考勤体验. 这个离线app支持上传考勤记录,下载人脸数据进行离线人脸识别和活体检测,有限规避相片打卡视频欺骗等. 这个APP的下载体验地址https://pan.baidu.com/s/1i5oXoJ7 接下来看一下接口功能设计,还原提意见哦.慢慢的福利,正在做的朋友可以直接下载参考.

Android人脸识别app——基于Face++,MVP+Retofit+RxJava+Dagger

前言 最近公司项目比较空,花了点时间写了个人脸识别的app,可以查看你的性别.年龄.颜值.情绪等信息,利用的是 Face++ 的人脸识别API.本项目采用了 MVP 的架构,使用了 Retrofit.RxJava.Dagger.EventBus 等框架进行开发和解耦,利用 MaterialDesign 进行UI上的布局设计. 主要的功能就是拍照,然后将照片传至 Face++ 服务器,进行人脸识别,获取返回的信息,对信息进行处理.将人脸在照片上标出,并将信息展示出来. 话不多说,先来看一下 app

android人脸识别活体识别人脸动作活体静默活体Demo源码实现讲解

这里说活体是基于单目摄像头活体,适合所有普通安卓Android 单目摄像头的手机,双目的需要硬件支持,这里不讲述 . 体验地址: https://pan.baidu.com/s/1i5oXoJ7 下一章讲述静默活体实现原理 里面含有表情识别: 人脸动作活体: ? 头部 左摆 右摆 上抬 下低 , 眼睛,张开 闭眼 睁大眼 嘴巴:张开 合并 这些实验原理是根据人脸特征点,根据位置规则测算出来的,其实不难. 表情识别: 检测微笑 大笑 假笑 亲嘴 使眼色 失望 愤怒 吐舌/鬼脸 脸红/瞪眼 尖叫/惊

学习笔记TF058:人脸识别

人脸识别,基于人脸部特征信息识别身份的生物识别技术.摄像机.摄像头采集人脸图像或视频流,自动检测.跟踪图像中人脸,做脸部相关技术处理,人脸检测.人脸关键点检测.人脸验证等.<麻省理工科技评论>(MIT Technology Review),2017年全球十大突破性技术榜单,支付宝"刷脸支付"(Paying with Your Face)入围. 人脸识别优势,非强制性(采集方式不容易被察觉,被识别人脸图像可主动获取).非接触性(用户不需要与设备接触).并发性(可同时多人脸检测

基于安卓高仿how-old.net应用实现人脸识别估算年龄与性别

前几段微软推出的大数据人脸识别年龄应用how-old.net在微博火了一把,它可以通过照片快速获得照片上人物的年龄,系统会对瞳孔.眼角.鼻子等27个“面部地标点"展开分析,进而得出你的“颜龄". 来看下关于这款应用的截图:   昨晚闲着没事,在网上查阅了点资料仿写了一款类似功能的APP,看下截图: 关于人脸识别技术本想去使用微软给开发人员提供的SDK,但由于天朝巨坑的网络,我连How-old.net官网都登不上,只能绕道去找找其他地方有没类似功能的SDK.后来想起之前在搞O2O的时候,

结合活体检测,人脸识别在Android、IOS、服务器中的应用

随着深度学习方法的应用,人工智能的发展,人脸识别技术的识别率已经得到质的提升,通过反复开发试验,目前我司的人脸识别技术率已经达到99%.人脸识别技术与其他生物特征识别技术相吃比,在实际应用中具有天然独到的优势:通过摄像头直接获取,在非接触的方式完成识别过程.通过人脸识别与证件识别的比对,目前我司的人脸识别技术已应用在金融.教育.景区.旅运.社保等领域. 人脸识别技术简介 人脸识别技术主要分为两部分: 第一部为前端人脸活体检测技术,主要支持android.ios平台,在前端通过眨眼.张嘴.摇头.点

Android 实现人脸识别教程[运用虹软人脸识别SDK]

基于虹软人脸识别引擎,在Android平台上实现人脸识别功能,即使在离线的情况下依旧运行,不被人采集个人照片的感觉,还是爽爽的.经过整个测试过来,虹软的人脸识别还是很强大的,人脸检测可以控制在20ms之内,人脸识别大概在200ms左右.今天就来分享一下开发经验 项目的目标 我们需要实现一个人脸识别功能.简单来说,就是机的后置摄像头,识别摄像头中实时拍到的人脸信息,如果人库注册过,则显示识别后的人脸信息,如登记的名字:如果不在,提示未注册. 这个功能具有多个应用场景,比如,火车站或者打卡和门禁系统

Android 使用FACE++架构包实现人脸识别

今天给大家带来一个通过使用Face++来实现人脸识别的功能. 我们先去这个Face++官网看看:http://www.faceplusplus.com.cn 我们点开案例可以看到众多我们熟知的软件都是使用的这个公司所提供的SDK. 然后我们点击开发者中心中的开发工具与sdk下载我们所需要的sdk. 之后再点击我的应用中的创建应用之后他会给我们两个密钥. 要保存这两个值我们在程序中要用到它们 我今天实现的是实现面部捕捉并且识别性别和年龄来看一下效果图    闲话不多说我们来看看实现 1.工具类Co