讯飞人脸识别
来源:互联网 发布:php程序员桌面壁纸 编辑:程序博客网 时间:2024/04/28 10:42
今天做了一套二级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;">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 就这个简单。
效果:
源码 http://download.csdn.net/detail/csdnhejingzhou/9470349
0 0
- 讯飞人脸识别
- 讯飞人脸在线识别
- 科大讯飞人脸识别,语音听写,声纹识别踩坑记
- 篮球飞人
- 飞人博尔特
- 牙买加飞人
- 篮球飞人
- Android手机游戏:外星飞人(推荐)
- 百帮忙飞人端隐私政策
- 语音识别&人脸识别
- 永远的飞人--★迈克尔.乔丹★- -
- 瑞士“飞人”刷新纪录 独立飞行17公里(图)
- “猎豹”狂人犬:每小时28.3英里 超越飞人
- 【人脸识别】初识人脸识别
- 【人脸识别】初识人脸识别
- OpenCV的行人识别&人脸识别
- 图片识别之人脸识别API
- OpenCV的行人识别&人脸识别
- Common Lisp 笔记(1)
- 如何省略显示过多的child views
- 第4周项目3(2)小学生算数能力测试
- Struts2中 Result类型配置详解
- 303. Range Sum Query - Immutable
- 讯飞人脸识别
- jQuery学习笔记(二)
- 【bzoj3437】【小p的牧场】【斜率优化dp】
- android学习之内存泄露(更新中)
- Spring MVC hello world!
- hdu 1540 Tunnel Warfare(线段树单点更新+区间合并)
- server2012/win8 卸载.net framework 4.5后 无法进入系统桌面故障解决
- jQuery学习笔记(三)
- 红糖水白糖水的交换