概述
今天做了一套二级Java题,直接就绝望了。选择题就得了25分,错了将近一半,大后天就考了,忐忑。。
前天晚上和大前天晚上加班写了一个讯飞的一个人脸识别,结果昨天电脑系统让我安装Linux按的系统炸了。去他的,按了一下午系统昨天晚上干到十二点又写了一遍,不仅写的时间缩短了,而且更加清楚套路了。
整体来看,大约分以下步骤进行写。
1.从官网上申请服务,会给你个id也就是访问的key。吧这个记下来,下载人脸识别的SDK包括两个jar,和几个二进制文件。SDk里面有例程,导入Eclipce中运行无误后就可以看结构仿写了。
2.因为是用Android Studio写的所以较麻烦,需要将jar文件和so文件放入正确的位置。
3.主要分为两个类写的,第一个类就是进行照完的人脸进行裁剪类,这个是使用android自带的裁剪器,进行相应的配置,这个类里面主要是裁剪,对摄影的角度的判断,旋转图片,保存图片这几个方法。
4.第二个类就是通过SDK类进行识别了,首先需要将自己的申请的key在初始化SDK的时候添加进去,作为App唯一的标志允许访问服务,这个类主要是分三大块:Button的监听、对返回的数据进行Json解析判断、对Intent的监听(主要是照完相后对图片进行裁剪)。
一、下载的jar so文件的处理
新建jniLibs文件夹放入so文件 将Msc.jar Sunflower.jar文件放入libs文件夹中并添加进编译路径。
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />
二、裁剪类
package com.example.hejingzhou.facerecognition;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.media.ExifInterface;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* Created by Hejingzhou on 2016/3/22.
*/
public class HeadTrim {
public final static int REQUEST_PICTURE_CHOOSE = 1;
public final static int REQUEST_CAMERA_IMAGE = 2;
public final static int REQUEST_CROP_IMAGE = 3;
/**
* 裁剪图片 android自带的裁剪
* @param activity
* @param uri
*/
public static void corpPicture(Activity activity,Uri uri){
Intent innerIntent = new Intent("com.android.camera.action.CROP");//启用自带裁剪
innerIntent.setDataAndType(uri, "image/*");
innerIntent.putExtra("crop", "ture");//裁剪小正方形,不然没有裁剪功能,只能选取
innerIntent.putExtra("aspectX", 1);//放大缩小缩放比例
innerIntent.putExtra("aspectY", 1);//缩放比例 1 :1
innerIntent.putExtra("outputX", 320);
innerIntent.putExtra("outputY", 320);//限制图片大小
innerIntent.putExtra("return-data",true);
//切图大小不足 320 会出现黑框,防止出现黑框并输出
innerIntent.putExtra("scale",true);
innerIntent.putExtra("scaleUpIfNeeded",true);
File imageFile = new File(getImagePath(activity.getApplicationContext()));//从这个文件路径创建文件
innerIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(imageFile));
//MediaStore.EXTRA_OUTPUT 表示内容解析器被用来存储请求的Uri的图像或视频
innerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//带上裁剪好的图片传递出去
activity.startActivityForResult(innerIntent,REQUEST_CROP_IMAGE);
}
/**
* 获取裁剪的图片路径
* @param context
* @return
*/
public static String getImagePath(Context context){
String path;
if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
//如果当前存储的状态 是 不能挂载和读写的
path = context.getFilesDir().getAbsolutePath();//路径就等于这个文件的绝对路径(从根开始)
}else {
path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/msc/";
}
if(!path.endsWith("/")){ //与路径的最后一个字符进行比较如果不是“/”那么就添加“/”
path += "/";
}
File folder = new File(path);
if(folder != null && !folder.exists()){//如果文件不为空 或者不存在,创建这个文件的文件夹
folder.mkdirs();
}
path += "ifd.jpg";
return path;
}
/**
* 读取图片的属性 :的角度
* @param path
* @return
*/
public static int readPictureDegree(String path){
int degree = 0;//度
try {
ExifInterface exifInterface = new ExifInterface(path);//阅读和写作在JPEG文件的Exif标记类
int orientation = exifInterface.getAttributeInt(
//ExifInterface.getAttributeInt 返回指定标记的整数值
ExifInterface.TAG_ORIENTATION,
ExifInterface.ORIENTATION_NORMAL);//方向常规
switch (orientation){
case ExifInterface.ORIENTATION_ROTATE_90:
degree = 90;
break;
case ExifInterface.ORIENTATION_ROTATE_180:
degree = 180;
break;
case ExifInterface.ORIENTATION_ROTATE_270:
degree = 270;
break;
}
} catch (IOException e) {
e.printStackTrace();
}
return degree;
}
/**
* 旋转图片
* @param angle 旋转角度
* @param bitmap 原图
* @return 旋转后的 bitmap
*/
public static Bitmap rotateImage(int angle,Bitmap bitmap){
Matrix matrix = new Matrix();
matrix.postRotate(angle); //postconcats与指定的旋转矩阵
Bitmap resizedBitmap = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
/**
* createBitmap 返回一个不可变的位图从源位图的子集
* @param source The bitmap we are subsetting
* @param x The x coordinate of the first pixel in source
* @param y The y coordinate of the first pixel in source
* @param width The number of pixels in each row
* @param height The number of rows
* @param m Optional matrix to be applied to the pixels 可选的矩阵应用到像素
* @param filter true if the source should be filtered. 如果源应筛选,true
* Only applies if the matrix contains more than just
* translation.
*/
return resizedBitmap;
}
/**
* 保存图片
* @param context
* @param bitmap
*/
public static void saveBitmapToFile(Context context, Bitmap bitmap) {
String file_path = getImagePath(context);
File file = new File(file_path);
FileOutputStream fileOutputStream;
try {
fileOutputStream = new FileOutputStream(file);
bitmap.compress(Bitmap.CompressFormat.JPEG,85,fileOutputStream);
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
这个类中的裁剪方法挺好的,记住在别处也会用的着。
三、校验登陆(千万不能忘了初始化SDK并加入自己的key和实例化FaceRequest)
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">package com.example.hejingzhou.facerecognition;</span>
<span style="font-family: Arial, Helvetica, sans-serif; font-size: 12px;">package com.example.hejingzhou.facerecognition;</span>
<span style="font-family: Arial, Helvetica, sans-serif;">import android.app.ProgressDialog;</span>
import android.content.DialogInterface;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Rect;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.os.Environment;
import android.provider.MediaStore;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.Toast;
import com.iflytek.cloud.ErrorCode;
import com.iflytek.cloud.FaceRequest;
import com.iflytek.cloud.RequestListener;
import com.iflytek.cloud.SpeechConstant;
import com.iflytek.cloud.SpeechError;
import com.iflytek.cloud.SpeechUtility;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.UnsupportedEncodingException;
import java.util.Currency;
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
private String TAG = getClass().getCanonicalName();
private final int REQUEST_PICTURE_CHOOSE = 1;
private final int REQUEST_CAMERA_IMAGES = 2;
private FaceRequest faceRequest;
private Toast toast;
private byte[] imageData = null;
private Bitmap image = null;
private EditText editTextUserPassword;
private String UserPassword;
private ProgressDialog progressDialog;
private File pictureFile;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
init();
}
private void init() {
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
SpeechUtility.createUtility(this, "appid=" + getString(R.string.app_key));//初始化SDK 千万不能忘记写appid后边的等号 id是自己其官网上申请的
//忘记会报 10274无效 key
faceRequest = new FaceRequest(this);
findViewById();
toast = Toast.makeText(this,"",Toast.LENGTH_SHORT);
progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(true);//设置是否可取消
progressDialog.setTitle("请稍等...");
progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
if (null != faceRequest) {
faceRequest.cancel();
}
}
});
}
private void findViewById() {
editTextUserPassword = (EditText)findViewById(R.id.editTextUserPassword);
findViewById(R.id.buttonRegister).setOnClickListener(MainActivity.this);
findViewById(R.id.buttonPicture).setOnClickListener(MainActivity.this);
findViewById(R.id.buttonVerification).setOnClickListener(MainActivity.this);
findViewById(R.id.imageViewHead).setOnClickListener(MainActivity.this);
}
@Override
public void onClick(View v) {
switch (v.getId()){
case R.id.buttonPicture:
pictureFile = new File(Environment.getExternalStorageDirectory(),
"picture"+System.currentTimeMillis()/1000+".jpg");
Intent picIntent = new Intent();
picIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
picIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pictureFile));
picIntent.putExtra(MediaStore.Images.Media.ORIENTATION,0);
startActivityForResult(picIntent,REQUEST_CAMERA_IMAGES);
break;
case R.id.buttonRegister:
UserPassword = ((EditText)findViewById(R.id.editTextUserPassword)).getText().toString();
if(TextUtils.isEmpty(UserPassword)){
showToast("请输入您的密钥");
return;
}else if(null != imageData){
progressDialog.setMessage("注册中...");
progressDialog.show();
faceRequest.setParameter(SpeechConstant.AUTH_ID, UserPassword);//将授权标识和密码上传服务器记录
faceRequest.setParameter(SpeechConstant.WFR_SST,"reg");//业务类型train Or verify
faceRequest.sendRequest(imageData,requestListener);
}else showToast("请先进行图像拍摄...");
break;
case R.id.buttonVerification:
UserPassword = ((EditText)findViewById(R.id.editTextUserPassword)).getText().toString();
if(TextUtils.isEmpty(UserPassword)){
showToast("密钥不能为空哦...");
}else if(imageData != null){
progressDialog.setMessage("验证中,请稍等...");
progressDialog.show();//6--12字符 不能以数字开头
faceRequest.setParameter(SpeechConstant.AUTH_ID, UserPassword);
faceRequest.setParameter(SpeechConstant.WFR_SST,"verify");
faceRequest.sendRequest(imageData,requestListener);
}else showToast("请先捕捉头像...");
break;
}
}
/**
* 处理拍完照后,跳转到裁剪界面
* @param requestCode
* @param resultCode
* @param data
*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.i(TAG, "运行到了onActivityResult");
if(resultCode != RESULT_OK){
Log.i(TAG,"requestCode未成功");
return;
}
String fileSrc = null;
if(requestCode == REQUEST_PICTURE_CHOOSE){
if("file".equals(data.getData().getScheme())){
fileSrc = data.getData().getPath();
Log.i(TAG,"file "+fileSrc);
}else {
String[] proj = {MediaStore.Images.Media.DATA};
Cursor cursor = getContentResolver().query(data.getData(), proj, null, null, null);
cursor.moveToFirst();
int idx = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
fileSrc = cursor.getString(idx);
cursor.close();
}
HeadTrim.corpPicture(this, Uri.fromFile(new File(fileSrc)));
}else if(requestCode == REQUEST_CAMERA_IMAGES){
if(null == pictureFile){
showToast("拍照失败,请重试...");
return;
}
fileSrc = pictureFile.getAbsolutePath();
updataGallery(fileSrc);
HeadTrim.corpPicture(this,Uri.fromFile(new File(fileSrc)));
}else if(requestCode == HeadTrim.REQUEST_CROP_IMAGE){
Bitmap bitmap = data.getParcelableExtra("data");
Log.i(TAG,"bitmp是否为空");
if(null != bitmap){
HeadTrim.saveBitmapToFile(MainActivity.this,bitmap);
}
fileSrc = HeadTrim.getImagePath(MainActivity.this);//获取图片保存路径
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
image = BitmapFactory.decodeFile(fileSrc,options);
options.inSampleSize = Math.max(1, (int) Math.ceil(Math.max(
(double) options.outWidth / 1024f,
(double) options.outHeight / 1024f
)));
options.inJustDecodeBounds = false;
image = BitmapFactory.decodeFile(fileSrc,options);
//如果imageBitmap 为空图片不能正常获取
if(null == image){
showToast("图片信息无法正常获取");
return;
}
int degree = HeadTrim.readPictureDegree(fileSrc);
if(degree != 0){
image = HeadTrim.rotateImage(degree,image);
}
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.JPEG,80,byteArrayOutputStream);
imageData = byteArrayOutputStream.toByteArray();
((ImageView)findViewById(R.id.imageViewHead)).setImageBitmap(image);
}
}
@Override
public void finish() {
if(null != progressDialog){
progressDialog.dismiss();
}
super.finish();
}
private void updataGallery(String fileName) {
MediaScannerConnection.scanFile(this, new String[]{fileName}, null,
new MediaScannerConnection.OnScanCompletedListener() {
@Override
public void onScanCompleted(String path, Uri uri) {
}
});
}
/**
* 请求对象监听 , 对服务器返回来的数据进行解析 JSON格式
*/
private RequestListener requestListener = new RequestListener() {
@Override
public void onEvent(int i, Bundle bundle) {
}
@Override
public void onBufferReceived(byte[] bytes) {
if(null != progressDialog){
progressDialog.dismiss();
}
try {
String result = new String(bytes,"utf-8");
Log.i(TAG,result);
JSONObject object = new JSONObject(result);
String type = object.optString("sst");//获取业务类型
if("reg".equals(type)){//注册
register(object);
}else if("verify".equals(type)){//校验
verify(object);
}else if("detect".equals(type)){
detect(object);
}else if("aligm".equals(type)){
//align(object);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (JSONException e) {
e.printStackTrace();
}
}
@Override
public void onCompleted(SpeechError speechError) {//完成后
if(null != progressDialog){
progressDialog.dismiss();
}
if(speechError != null ){
switch (speechError.getErrorCode()){
case ErrorCode.MSP_ERROR_ALREADY_EXIST:
showToast("密钥已被注册,请更换后再试...");
break;
default:showToast(speechError.getPlainDescription(true));
break;
}
}
}
};
//检测
private void detect(JSONObject object) throws JSONException{
int ret = object.getInt("ret");
if(ret != 0){
showToast("检测失败");
}else if("success".equals(object.get("rst"))){
JSONArray jsonArray = object.getJSONArray("face");
Paint paint = new Paint();
paint.setColor(Color.RED);
paint.setStrokeWidth(Math.max(image.getWidth(), image.getHeight()) / 100f);
Bitmap bitmap = Bitmap.createBitmap(image.getWidth(),image.getHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
canvas.drawBitmap(image,new Matrix(),null);
for(int i = 0;i<jsonArray.length();i++){
float x1 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("left");
float y1 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("top");
float x2 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("right");
float y2 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("bottom");
paint.setStyle(Paint.Style.STROKE);
canvas.drawRect(new Rect((int)x1,(int)x2,(int)x2,(int)y2),paint);
}
image = bitmap;
((ImageView)findViewById(R.id.imageViewHead)).setImageBitmap(image);
}else {
showToast("检测失败");
}
}
/**
* 校验
* @param object
*/
private void verify(JSONObject object) throws JSONException{
int ret = object.getInt("ret");
Log.i(TAG,"ret校验"+ret);
if(ret != 0){
showToast("校验失败..."+ret);
}else if("success".equals(object.get("rst"))){
if(object.getBoolean("verf")){
showToast("验证通过");
editTextUserPassword.setText(null);
startActivity(new Intent(MainActivity.this,JumpActivity.class));
}else if(!object.getBoolean("verg")){
showToast("验证不通过");
}else showToast("验证失败");
}
}
/**
* 如果收回的数据类型是注册 进行一下处理
* @param object
*/
private void register(JSONObject object) throws JSONException{
int ret = object.getInt("ret");//解析ret返回值 0代表成功 -1失败 或者其他的错误异常代码
if(ret != 0){
showToast("注册失败");
return;
}else if("success".equals(object.get("rst"))){
showToast("注册成功");
editTextUserPassword.setText(null);
}else showToast("注册失败,错误");
}
//土司对话框
private void showToast(final String s){
toast.setText(s);
toast.show();
}
}
Ok 就这个简单。
最后
以上就是淡然钢笔为你收集整理的讯飞人脸识别整体来看,大约分以下步骤进行写。一、下载的jar so文件的处理二、裁剪类三、校验登陆(千万不能忘了初始化SDK并加入自己的key和实例化FaceRequest)package com.example.hejingzhou.facerecognition;的全部内容,希望文章能够帮你解决讯飞人脸识别整体来看,大约分以下步骤进行写。一、下载的jar so文件的处理二、裁剪类三、校验登陆(千万不能忘了初始化SDK并加入自己的key和实例化FaceRequest)package com.example.hejingzhou.facerecognition;所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复