Android移动开发-在Android项目里集成face++人脸识别的实现
“人工智能”是今年比较火的一个名词,甚至大多数人认为“人工智能”是继“IT互联网”之后一个新的浪潮,将会是本世纪最高科技的水准。个人觉得,目前国内语音识别做的比较好的是科大讯飞,图像识别(或人脸识别)做的比较好的是face++(旷视)。那么,如何在Android项目里集成face++人脸识别的实现呢? 首先在face++的开发平台网址:https://www.faceplusplus.com.cn
·
“人工智能”是今年比较火的一个名词,甚至大多数人认为“人工智能”是继“IT互联网”之后一个新的浪潮,将会是本世纪最高科技的水准。个人觉得,目前国内语音识别做的比较好的是科大讯飞,图像识别(或人脸识别)做的比较好的是face++(旷视)。
那么,如何在Android项目里集成face++人脸识别的实现呢?
首先在face++的开发平台网址:https://www.faceplusplus.com.cn/ ,然后在平台注册成为开发者后在点击“应用管理”——创建“API Key”号,如下图所示:
接着再绑定Bundle ID号,如下图所示:
- layout/activity_main.xml界面布局代码如下:
<?xml version="1.0" encoding="utf-8"?>
<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"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<ImageView
android:id="@+id/id_photo"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentLeft="true"
android:layout_alignParentRight="true"
android:layout_alignParentTop="true"
android:layout_alignTop="@+id/id_detect"
android:src="@drawable/face" />
<TextView
android:id="@+id/id_tip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignTop="@+id/id_detect"
android:layout_marginRight="10dp"
android:layout_toLeftOf="@+id/id_detect"
android:gravity="center"
android:text="tip" />
<Button
android:id="@+id/id_detect"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_marginRight="10dip"
android:layout_toLeftOf="@+id/id_getImg"
android:text="检测人脸" />
<Button
android:id="@+id/id_getImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentRight="true"
android:layout_marginRight="10dp"
android:text="选择图片" />
<FrameLayout
android:id="@+id/id_waiting"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clickable="true"
android:visibility="gone">
<ProgressBar
android:id="@+id/id_progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center" />
<TextView
android:id="@+id/id_age_and_gender"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@drawable/hint"
android:drawableLeft="@drawable/male"
android:gravity="center"
android:text="123"
android:textColor="#ffff00ff"
android:textSize="22sp"
android:visibility="invisible" />
</FrameLayout>
</RelativeLayout>
- 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
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- MainActivity.java逻辑代码如下:
package com.fukaimei.facerecognition;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import com.facepp.error.FaceppParseException;
import com.fukaimei.facerecognition.utils.FaceppDetect;
import android.content.Intent;
import android.content.pm.PackageManager;
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.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements OnClickListener {
private ImageView mPhoto;
private Button mDetect, mGetImg;
private TextView mTip;
private View mWaiting;
private Canvas canvas;
private Paint mPaint;
private String mCurrentPhotoStr;
private Bitmap mBitmapPhoto;
private static final int PICK_CODE = 0x110;
private static final int MSG_SUCCESS = 0x111;
private static final int MSG_ERROR = 0x112;
private Handler mHandler = new Handler() {
public void handleMessage(android.os.Message msg) {
switch (msg.what) {
case MSG_SUCCESS:
mWaiting.setVisibility(View.GONE);
JSONObject rs = (JSONObject) msg.obj;
prepareResultBitmap(rs);
mPhoto.setImageBitmap(mBitmapPhoto);
break;
case MSG_ERROR:
mWaiting.setVisibility(View.GONE);
String errorMsg = (String) msg.obj;
if (TextUtils.isEmpty(errorMsg)) {
mTip.setText("Error.");
} else {
mTip.setText(errorMsg);
}
break;
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 申请访问SD卡的动态权限
sdPermissions();
mPhoto = (ImageView) findViewById(R.id.id_photo);
mDetect = (Button) findViewById(R.id.id_detect);
mGetImg = (Button) findViewById(R.id.id_getImg);
mTip = (TextView) findViewById(R.id.id_tip);
mWaiting = findViewById(R.id.id_waiting);
mDetect.setOnClickListener(this);
mGetImg.setOnClickListener(this);
mPaint = new Paint();
}
// 定义访问SD卡的动态权限
private void sdPermissions() {
if (ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
android.Manifest.permission.READ_EXTERNAL_STORAGE}, 1);
}
}
/**
* 重写onRequestPermissionsResult方法
* 获取动态权限请求的结果,再访问SD卡
*/
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
if (requestCode == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
} else {
Toast.makeText(this, "用户拒绝了权限", Toast.LENGTH_SHORT).show();
}
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
private void prepareResultBitmap(JSONObject rs) {
// TODO Auto-generated method stub
Bitmap bitmap = Bitmap.createBitmap(mBitmapPhoto.getWidth(), mBitmapPhoto.getHeight(),
mBitmapPhoto.getConfig());
canvas = new Canvas(bitmap);
canvas.drawBitmap(mBitmapPhoto, 0, 0, null);
try {
JSONArray faces = rs.getJSONArray("face");
int faceCount = faces.length();
mTip.setText("find " + faceCount);
for (int i = 0; i < faceCount; i++) {
// 拿到单独face对象
JSONObject face = faces.getJSONObject(i);
JSONObject positonObj = face.getJSONObject("position");
// get face position
float x = (float) positonObj.getJSONObject("center").getDouble("x");
float y = (float) positonObj.getJSONObject("center").getDouble("y");
float w = (float) positonObj.getDouble("width");
float h = (float) positonObj.getDouble("height");
x = x / 100 * bitmap.getWidth();
y = y / 100 * bitmap.getHeight();
w = w / 100 * bitmap.getWidth();
h = h / 100 * bitmap.getHeight();
mPaint.setColor(0xffffffff);
mPaint.setStrokeWidth(3);
// draw box
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);// 右
canvas.drawLine(x - w / 2, y - h / 2, x + w / 2, y - h / 2, mPaint);// 上
// get age and gender
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()<=mPhoto.getWidth() && bitmap.getHeight()<=mPhoto.getHeight()){
float ratio = Math.max(bitmap.getWidth() * 1.0f / mPhoto.getWidth(),
bitmap.getHeight() * 1.0f / mPhoto.getHeight());
ageBitmap = Bitmap.createScaledBitmap(ageBitmap, (int) (ageWidth * ratio),
(int) (ageHeight * ratio), false);
canvas.drawBitmap(ageBitmap, x - ageBitmap.getWidth() / 2, y - h / 2 - ageBitmap.getHeight(), null);
}
mBitmapPhoto = bitmap;
}
} catch (JSONException e) {
e.printStackTrace();
}
};
private Bitmap buildAgeBitmap(int age, boolean isMale) {
TextView tv = (TextView) mWaiting.findViewById(R.id.id_age_and_gender);
tv.setText(age + "");
if (isMale) {
tv.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.male), null, null, null);
} else {
tv.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.female), null, null, null);
}
tv.setDrawingCacheEnabled(true);
Bitmap bitmap = Bitmap.createBitmap(tv.getDrawingCache());
tv.destroyDrawingCache();
return bitmap;
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 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);
mCurrentPhotoStr = cursor.getString(index);
cursor.close();
resizePhoto();
mPhoto.setImageBitmap(mBitmapPhoto);
mTip.setText("点击检测 ==>");
}
}
super.onActivityResult(requestCode, resultCode, data);
}
private void resizePhoto() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeFile(mCurrentPhotoStr, options);
double ratio = Math.max(options.outWidth * 1.0d / 1024f, options.outHeight * 1.0d / 1024f);
options.inSampleSize = (int) Math.ceil(ratio);
options.inJustDecodeBounds = false;
mBitmapPhoto = BitmapFactory.decodeFile(mCurrentPhotoStr, options);
}
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.id_getImg:
Intent intent = new Intent(Intent.ACTION_PICK);
intent.setType("image/*");
startActivityForResult(intent, PICK_CODE);
break;
case R.id.id_detect:
if (mBitmapPhoto != null && !mBitmapPhoto.isRecycled()) {
mWaiting.setVisibility(View.VISIBLE);
FaceppDetect.detect(mBitmapPhoto, new FaceppDetect.CallBack() {
@Override
public void success(JSONObject result) {
Message msg = mHandler.obtainMessage(MSG_SUCCESS);
msg.obj = result;
msg.sendToTarget();
}
@Override
public void error(FaceppParseException exception) {
Message msg = mHandler.obtainMessage(MSG_ERROR);
msg.obj = exception.getErrorMessage();
msg.sendToTarget();
}
});
} else {
Toast.makeText(MainActivity.this, "请选择您要检测的人脸图片", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
- 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
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 然后在 Constant.java逻辑代码下添加在face++平台申请到的APP_KEY码和APP_SECRET码如下:
package com.fukaimei.facerecognition;
public class Constant {
public static final String APP_KEY = "填写你申请到的APP_KEY码";
public static final String APP_SECRET = "填写你申请到的APP_SECRET码";
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- Demo程序运行效果界面截图如下:
更多推荐
已为社区贡献1条内容
所有评论(0)