Android(安卓)刷脸神器,颜值价更高
转载请标明出处: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_KEY 和 API_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更多相关文章
- Android之cardview属性以及阴影处理
- Android瀑布流优化,解决Recyclerview展示大批量图片时Item自动切
- Android(安卓)自定义camera压缩图片到指定大小
- Android生成自定义二维码(三)--保存和分享二维码图片
- Android(安卓)ImageView 不显示JPEG图片 及 Android(安卓)Studio
- Android实现动态高斯模糊效果示例代码
- Android(安卓)上传图片到 Asp.Net 服务器的问题
- android实现图片翻转动画
- android volley 框架图片请求后有时会导致第一次初始化过慢的原