转载请标明出处:http://blog.csdn.net/u011546655/article/details/46608995

背景

最近在市场中出现了一个特牛逼的功能,那就是刷脸,当然并不是老马的刷脸支付功能,而是how-old的刷脸神器,刷出自己的真实年龄和性别,看起来很牛叉,当然face++中也是实现了这个功能,当然既然是Android的刷脸神器,那么其实在红米和小米手机上,其实你也可以看到更更加强大的刷脸,照相功能自带刷脸识别,只刷神器,好了不吹牛逼了。


一:接下来看效果图

二:how-old和face++简介

how-old地址:http://www.how-old.net/

face++地址:http://www.faceplusplus.com.cn/

上面分别是how-old和face++的地址,我们这里呢,可以直接去用他们的api进行快速开发,首先我想我们都避免不了需要去注册什么账号等,反正跟着做就好了,这里呢,我推荐大家使用face++,关于how-old呢,并不是说不能用,因为它是微软开发的,需要什么微软账号,注册起来,相当的蛋疼,反正我觉得麻烦,虽然我是不怕麻烦的人,但是呢,我还是很闲麻烦找上门。


这里呢,我们会获取两个值分别为:API_KEYAPI_SECRET



不多说,接下来看看face++开发的详解,我们身为开发者,那么一定是看开发者文档咯,不用多说,直蹦主题




其实,我们可以看到,在face++给我们提供的api中有很多接口,功能说明,其中有检测脸,两张脸相似,脸的分类啊等等,看起来face++还是非常牛逼的,说明都为我们准备好了,我们呢,只是做一个简单的刷刷脸,所以,那么就看看第一个接口,检测脸,这个接口。戳进去看看:

首先是:参数介绍,不详细说,自己看看



接下来就是调用示例:需要什么参数,组件什么url等等。

http://apicn.faceplusplus.com/v2/detection/detect?api_key=YOUR_API_KEY&api_secret=YOUR_API_SECRET&url=http%3A%2F%2Ffaceplusplus.com%2Fstatic%2Fimg%2Fdemo%2F1.jpg&attribute=glass,pose,gender,age,race,smiling

Gson数据格式

{    "face": [        {            "attribute": {                "age": {                    "range": 5,                     "value": 23                },                 "gender": {                    "confidence": 99.9999,                     "value": "Female"                },                 "glass": {                    "confidence": 99.945,                     "value": "None"                },                 "pose": {                    "pitch_angle": {                        "value": 17                    },                     "roll_angle": {                        "value": 0.735735                    },                     "yaw_angle": {                        "value": -2                    }                },                 "race": {                    "confidence": 99.6121,                     "value": "Asian"                },                 "smiling": {                    "value": 4.86501                }            },             "face_id": "17233b4b1b51ac91e391e5afe130eb78",             "position": {                "center": {                    "x": 49.4,                     "y": 37.6                },                 "eye_left": {                    "x": 43.3692,                     "y": 30.8192                },                 "eye_right": {                    "x": 56.5606,                     "y": 30.9886                },                 "height": 26.8,                 "mouth_left": {                    "x": 46.1326,                     "y": 44.9468                },                 "mouth_right": {                    "x": 54.2592,                     "y": 44.6282                },                 "nose": {                    "x": 49.9404,                     "y": 38.8484                },                 "width": 26.8            },             "tag": ""        }    ],     "img_height": 500,     "img_id": "22fd9efc64c87e00224c33dd8718eec7",     "img_width": 500,     "session_id": "38047ad0f0b34c7e8c6efb6ba39ed355",     "url": "http://www.faceplusplus.com.cn/wp-content/themes/faceplusplus/assets/img/demo/1.jpg?v=4"}

三:具体实施

①下载face++sdk

下载地址:http://www.faceplusplus.com.cn/dev-tools-sdks/


②完成配置文件的编写

package com.how_old.tools;/** * 配置类 *  * @author zengtao 2015年5月25日 下午9:30:22 * */public class Config {// face++public static final String APP_KEY = "66324964c66934cb35a1eb6f1dfc1db8";public static final String API_SECRET = "dSe2p0Vn39O8MEQGXd1bSRuaZ-VqXYa2";}


③完成网络请求的编写

package com.how_old.utils;import java.io.ByteArrayOutputStream;import org.json.JSONObject;import android.graphics.Bitmap;import com.facepp.error.FaceppParseException;import com.facepp.http.HttpRequests;import com.facepp.http.PostParameters;import com.how_old.tools.Config;/** * 网络请求 *  * @author zengtao 2015年5月25日 下午9:29:54 * */public class Https {/** * 将图片转换成二进制:发送请求 *  * @param bitmap */public static void detect(final Bitmap bitmap, final CallBack callBack) {new Thread(new Runnable() {@Overridepublic void run() {try {HttpRequests requests = new HttpRequests(Config.APP_KEY,Config.API_SECRET, true, true);Bitmap b = Bitmap.createBitmap(bitmap, 0, 0,bitmap.getWidth(), bitmap.getHeight());ByteArrayOutputStream stream = new ByteArrayOutputStream();b.compress(Bitmap.CompressFormat.JPEG, 100, stream);byte[] arrays = stream.toByteArray();// 这里面封装好了key-value的键值对PostParameters parameters = new PostParameters();parameters.setImg(arrays);JSONObject jsonObject = requests.detectionDetect(parameters);if (callBack != null) {callBack.success(jsonObject);System.out.println("Return Success : \n" + jsonObject);}} catch (FaceppParseException e) {e.printStackTrace();if (callBack != null) {callBack.faile(e);System.out.println("Return Fail : \n" + e);}}}}).start();}// 设置回调public interface CallBack {void success(JSONObject jsonObject);void faile(FaceppParseException e);}}

④布局文件

<RelativeLayout 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" >    <ImageView        android:id="@+id/photo"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:src="@drawable/t4" />    <!-- 底部 -->    <LinearLayout        android:id="@+id/layout"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_alignParentBottom="true"        android:gravity="center"        android:orientation="horizontal" >        <TextView            android:id="@+id/display_photomessage"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:gravity="center"            android:text="photo info"            android:textSize="12sp" />        <Button            android:id="@+id/check_photo"            android:layout_width="wrap_content"            android:layout_height="40dp"            android:gravity="center"            android:text="check photo"            android:textSize="12sp" />        <Button            android:id="@+id/open_grally"            android:layout_width="wrap_content"            android:layout_height="40dp"            android:gravity="center"            android:text="open grally"            android:textSize="12sp" />    </LinearLayout>    <!-- 进度 -->    <FrameLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_centerInParent="true" >        <ProgressBar            android:id="@+id/waitProgressBar"            android:layout_width="match_parent"            android:layout_height="wrap_content"            android:visibility="gone" />        <TextView            android:id="@+id/topview"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:background="#EEAD0E"            android:drawableLeft="@drawable/male"            android:gravity="center"            android:text="123"            android:textColor="#ff0000"            android:textSize="18sp"            android:visibility="invisible" />    </FrameLayout></RelativeLayout>

⑤添加权限

  <!-- 权限 -->    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />



⑥主界面的调用

1.初始化视图
/** * 初始化 */private void initView() {mImageView = (ImageView) findViewById(R.id.photo);find_message = (TextView) findViewById(R.id.display_photomessage);check_photo = (Button) findViewById(R.id.check_photo);open_grally = (Button) findViewById(R.id.open_grally);mProgressBar = (ProgressBar) findViewById(R.id.waitProgressBar);topview = (TextView) findViewById(R.id.topview);open_grally.setOnClickListener(listener);check_photo.setOnClickListener(listener);mPaint = new Paint();mPaint.setColor(0xffffffff);mPaint.setStrokeWidth(3);mPaint.setAntiAlias(true);}


2.监听事件
/** * 点击事件 */OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.check_photo:mProgressBar.setVisibility(View.VISIBLE);if (photoPath != null && !photoPath.trim().equals("")) {compressPhoto();} else {bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.t4);}checkPhoto();break;case R.id.open_grally:openGrally();break;}}};


3. 打开本地图库,选择图片,压缩图片,返回图片
/** * 打开本地相册 */private void openGrally() {Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);intent.setType("image/*");startActivityForResult(intent, 1);}/** * 压缩图片大小:防止图片太大出现异常 */private void compressPhoto() {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(photoPath, options);// 获取最大的比例double scale = Math.max(options.outWidth * 1.0 / 1024f, options.outHeight * 1.0 / 2014f);options.inSampleSize = (int) Math.ceil(scale);options.inJustDecodeBounds = false;bitmap = BitmapFactory.decodeFile(photoPath, options);}/** * 打开之后点击照片,显示在自己的app中 */@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == 1) {if (resultCode == RESULT_OK) {if (data != null) {// 1.获取路劲Uri uri = data.getData();Cursor cursor = getContentResolver().query(uri, null, null, null, null);cursor.moveToFirst();int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);photoPath = cursor.getString(index);cursor.close();// 2.压缩图片compressPhoto();// 3.设置图片mImageView.setImageBitmap(bitmap);}}}super.onActivityResult(requestCode, resultCode, data);}


4. 检测图片,绘制脸框,年龄和性别
/** * 解析json文件 *  * @param jsonObject */protected void parperJsonBitmap(JSONObject jsonObject) {Bitmap bit = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());Canvas canvas = new Canvas(bit);canvas.drawBitmap(bitmap, 0, 0, null);try {JSONArray faces = jsonObject.getJSONArray("face");// System.out.println("Return faces : " + faces);int facecount = faces.length(); // 找到了几张脸find_message.setText("find : " + facecount);for (int i = 0; i < facecount; i++) {JSONObject face = faces.getJSONObject(i); // 当前的那张脸// System.out.println("Return face : " + face);JSONObject pos = face.getJSONObject("position"); // 单张脸下的postion对象// System.out.println("Return pos : " + pos);float x = (float) pos.getJSONObject("center").getDouble("x");float y = (float) pos.getJSONObject("center").getDouble("y");float w = (float) pos.getDouble("width");float h = (float) pos.getDouble("height");x = x / 100 * bit.getWidth();y = y / 100 * bit.getHeight();w = w / 100 * bit.getWidth();h = h / 100 * bit.getHeight();// 画boxcanvas.drawLine(x - w / 2, y - h / 2, x - w / 2, y + h / 2, mPaint);canvas.drawLine(x - w / 2, y - h / 2, x + w / 2, y - h / 2, mPaint);canvas.drawLine(x + w / 2, y - h / 2, x + w / 2, y + h / 2, mPaint);canvas.drawLine(x - w / 2, y + h / 2, x + w / 2, y + h / 2, mPaint);// --------------------------------------------------------// --------------------------------------------------------// --------------------------------------------------------// 获取头部要显示的信息:年龄和性别String gender = face.getJSONObject("attribute").getJSONObject("gender").getString("value");int age = face.getJSONObject("attribute").getJSONObject("age").getInt("value");Bitmap ageBitmap = buildBitmap(age, "Male".endsWith(gender));int ageWidth = ageBitmap.getWidth();int ageHeight = ageBitmap.getHeight();if (bit.getWidth() < mImageView.getWidth() && bit.getHeight() < mImageView.getHeight()) {float scale = Math.max(bit.getWidth() * 1.0f / mImageView.getWidth(), bit.getHeight() * 1.0f / mImageView.getHeight());ageBitmap = Bitmap.createScaledBitmap(ageBitmap, (int) (ageWidth * scale), (int) (ageHeight * scale), false);}canvas.drawBitmap(ageBitmap, x - ageBitmap.getWidth() / 2, y - h / 2 - ageBitmap.getHeight(), null);// 将绘制好的图片返回给要设置的图片bitmap = bit;}} catch (JSONException e) {e.printStackTrace();}}/** * 显示年龄和性别的view *  * @param age * @param endsWith * @return */private Bitmap buildBitmap(int age, boolean isMale) {topview.setText(age + "");if (isMale) {topview.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.male), null, null, null);} else {topview.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.female), null, null, null);}topview.setDrawingCacheEnabled(true);Bitmap bitmap = Bitmap.createBitmap(topview.getDrawingCache());topview.destroyDrawingCache();return bitmap;}/** * 检测照片 */private void checkPhoto() {Https.detect(bitmap, new CallBack() {@Overridepublic void success(JSONObject jsonObject) {Message msg = new Message();msg.what = SUCCESS;msg.obj = jsonObject;handler.sendMessage(msg);}@Overridepublic void faile(FaceppParseException e) {Message msg = new Message();msg.what = FAIL;msg.obj = e.getMessage();handler.sendMessage(msg);}});}

四:示例源码

package com.how_old.ui;import org.json.JSONArray;import org.json.JSONException;import org.json.JSONObject;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Intent;import android.database.Cursor;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Paint;import android.net.Uri;import android.os.Bundle;import android.os.Handler;import android.os.Message;import android.provider.MediaStore;import android.text.TextUtils;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageView;import android.widget.ProgressBar;import android.widget.TextView;import com.facepp.error.FaceppParseException;import com.how_old.utils.Https;import com.how_old.utils.Https.CallBack;/** * 主界面 *  * @author zengtao 2015年5月25日 下午9:30:11 * */public class MainActivity extends Activity {private Button check_photo, open_grally;private ImageView mImageView;private TextView find_message, topview;private String photoPath;private Bitmap bitmap;private ProgressBar mProgressBar;private Paint mPaint;private static final int SUCCESS = 0x111;private static final int FAIL = 0x112;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);initView();}@SuppressLint("HandlerLeak")private Handler handler = new Handler() {public void handleMessage(android.os.Message msg) {switch (msg.what) {case SUCCESS:mProgressBar.setVisibility(View.GONE);JSONObject jsonObject = (JSONObject) msg.obj;parperJsonBitmap(jsonObject);mImageView.setImageBitmap(bitmap);break;case FAIL:mProgressBar.setVisibility(View.GONE);String err = (String) msg.obj;if (TextUtils.isEmpty(err)) {find_message.setText(err);}break;}};};/** * 初始化 */private void initView() {mImageView = (ImageView) findViewById(R.id.photo);find_message = (TextView) findViewById(R.id.display_photomessage);check_photo = (Button) findViewById(R.id.check_photo);open_grally = (Button) findViewById(R.id.open_grally);mProgressBar = (ProgressBar) findViewById(R.id.waitProgressBar);topview = (TextView) findViewById(R.id.topview);open_grally.setOnClickListener(listener);check_photo.setOnClickListener(listener);mPaint = new Paint();mPaint.setColor(0xffffffff);mPaint.setStrokeWidth(3);mPaint.setAntiAlias(true);}/** * 解析json文件 *  * @param jsonObject */protected void parperJsonBitmap(JSONObject jsonObject) {Bitmap bit = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());Canvas canvas = new Canvas(bit);canvas.drawBitmap(bitmap, 0, 0, null);try {JSONArray faces = jsonObject.getJSONArray("face");// System.out.println("Return faces : " + faces);int facecount = faces.length(); // 找到了几张脸find_message.setText("find : " + facecount);for (int i = 0; i < facecount; i++) {JSONObject face = faces.getJSONObject(i); // 当前的那张脸// System.out.println("Return face : " + face);JSONObject pos = face.getJSONObject("position"); // 单张脸下的postion对象// System.out.println("Return pos : " + pos);float x = (float) pos.getJSONObject("center").getDouble("x");float y = (float) pos.getJSONObject("center").getDouble("y");float w = (float) pos.getDouble("width");float h = (float) pos.getDouble("height");x = x / 100 * bit.getWidth();y = y / 100 * bit.getHeight();w = w / 100 * bit.getWidth();h = h / 100 * bit.getHeight();// 画boxcanvas.drawLine(x - w / 2, y - h / 2, x - w / 2, y + h / 2, mPaint);canvas.drawLine(x - w / 2, y - h / 2, x + w / 2, y - h / 2, mPaint);canvas.drawLine(x + w / 2, y - h / 2, x + w / 2, y + h / 2, mPaint);canvas.drawLine(x - w / 2, y + h / 2, x + w / 2, y + h / 2, mPaint);// --------------------------------------------------------// --------------------------------------------------------// --------------------------------------------------------// 获取头部要显示的信息:年龄和性别String gender = face.getJSONObject("attribute").getJSONObject("gender").getString("value");int age = face.getJSONObject("attribute").getJSONObject("age").getInt("value");Bitmap ageBitmap = buildBitmap(age, "Male".endsWith(gender));int ageWidth = ageBitmap.getWidth();int ageHeight = ageBitmap.getHeight();if (bit.getWidth() < mImageView.getWidth() && bit.getHeight() < mImageView.getHeight()) {float scale = Math.max(bit.getWidth() * 1.0f / mImageView.getWidth(), bit.getHeight() * 1.0f / mImageView.getHeight());ageBitmap = Bitmap.createScaledBitmap(ageBitmap, (int) (ageWidth * scale), (int) (ageHeight * scale), false);}canvas.drawBitmap(ageBitmap, x - ageBitmap.getWidth() / 2, y - h / 2 - ageBitmap.getHeight(), null);// 将绘制好的图片返回给要设置的图片bitmap = bit;}} catch (JSONException e) {e.printStackTrace();}}/** * 显示年龄和性别的view *  * @param age * @param endsWith * @return */private Bitmap buildBitmap(int age, boolean isMale) {topview.setText(age + "");if (isMale) {topview.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.male), null, null, null);} else {topview.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.female), null, null, null);}topview.setDrawingCacheEnabled(true);Bitmap bitmap = Bitmap.createBitmap(topview.getDrawingCache());topview.destroyDrawingCache();return bitmap;}/** * 检测照片 */private void checkPhoto() {Https.detect(bitmap, new CallBack() {@Overridepublic void success(JSONObject jsonObject) {Message msg = new Message();msg.what = SUCCESS;msg.obj = jsonObject;handler.sendMessage(msg);}@Overridepublic void faile(FaceppParseException e) {Message msg = new Message();msg.what = FAIL;msg.obj = e.getMessage();handler.sendMessage(msg);}});}/** * 打开本地相册 */private void openGrally() {Intent intent = new Intent();intent.setAction(Intent.ACTION_PICK);intent.setType("image/*");startActivityForResult(intent, 1);}/** * 压缩图片大小:防止图片太大出现异常 */private void compressPhoto() {BitmapFactory.Options options = new BitmapFactory.Options();options.inJustDecodeBounds = true;BitmapFactory.decodeFile(photoPath, options);// 获取最大的比例double scale = Math.max(options.outWidth * 1.0 / 1024f, options.outHeight * 1.0 / 2014f);options.inSampleSize = (int) Math.ceil(scale);options.inJustDecodeBounds = false;bitmap = BitmapFactory.decodeFile(photoPath, options);}/** * 打开之后点击照片,显示在自己的app中 */@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == 1) {if (resultCode == RESULT_OK) {if (data != null) {// 1.获取路劲Uri uri = data.getData();Cursor cursor = getContentResolver().query(uri, null, null, null, null);cursor.moveToFirst();int index = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA);photoPath = cursor.getString(index);cursor.close();// 2.压缩图片compressPhoto();// 3.设置图片mImageView.setImageBitmap(bitmap);}}}super.onActivityResult(requestCode, resultCode, data);}/** * 点击事件 */OnClickListener listener = new OnClickListener() {@Overridepublic void onClick(View v) {switch (v.getId()) {case R.id.check_photo:mProgressBar.setVisibility(View.VISIBLE);if (photoPath != null && !photoPath.trim().equals("")) {compressPhoto();} else {bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.t4);}checkPhoto();break;case R.id.open_grally:openGrally();break;}}};}

五:总结

以上就完成了刷脸神器,现在等待你的就是赶紧找自己的图片来试一试,发现自己的颜值到底有多高,来试一试最近风靡一时的刷脸神器,就这样在你手中完成了,当然你想要理解原来,那么你还需要了解更多。 Demo下载地址: http://download.csdn.net/detail/u011546655/8832163

更多相关文章

  1. Android之cardview属性以及阴影处理
  2. Android瀑布流优化,解决Recyclerview展示大批量图片时Item自动切
  3. Android(安卓)自定义camera压缩图片到指定大小
  4. Android生成自定义二维码(三)--保存和分享二维码图片
  5. Android(安卓)ImageView 不显示JPEG图片 及 Android(安卓)Studio
  6. Android实现动态高斯模糊效果示例代码
  7. Android(安卓)上传图片到 Asp.Net 服务器的问题
  8. android实现图片翻转动画
  9. android volley 框架图片请求后有时会导致第一次初始化过慢的原

随机推荐

  1. Android程序开发初级教程(一) 开始 Hello
  2. Android开发学习系列-----开发环境准备
  3. 如何启动Android SDK 1.5模拟器
  4. 初涉Android之文件保存
  5. 分享偶的android秘籍
  6. Android(安卓)自定义EditText, 增加设置
  7. 真实可行的android 基站定位代码
  8. Android Studio Gradle 添加.so 支持文件
  9. Android项目打包、Eclipse视图和UI控件
  10. Android保存数据几种常用方法解析