当前位置:   article > 正文

讯飞人脸识别_facerequest

facerequest

今天做了一套二级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文件夹中并添加进编译路径。


  1. <uses-permission android:name="android.permission.INTERNET" />
  2. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
  3. <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  4. <uses-permission android:name="android.permission.READ_PHONE_STATE" />
  5. <uses-permission android:name="android.permission.CAMERA" />
  6. <uses-permission android:name="android.permission.WRITE_SETTINGS" />
  7. <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
  8. <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  9. <uses-feature android:name="android.hardware.camera" />
  10. <uses-feature android:name="android.hardware.camera.autofocus" />

二、裁剪类

  1. package com.example.hejingzhou.facerecognition;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.content.Intent;
  5. import android.graphics.Bitmap;
  6. import android.graphics.Matrix;
  7. import android.media.ExifInterface;
  8. import android.net.Uri;
  9. import android.os.Environment;
  10. import android.provider.MediaStore;
  11. import java.io.File;
  12. import java.io.FileNotFoundException;
  13. import java.io.FileOutputStream;
  14. import java.io.IOException;
  15. /**
  16. * Created by Hejingzhou on 2016/3/22.
  17. */
  18. public class HeadTrim {
  19. public final static int REQUEST_PICTURE_CHOOSE = 1;
  20. public final static int REQUEST_CAMERA_IMAGE = 2;
  21. public final static int REQUEST_CROP_IMAGE = 3;
  22. /**
  23. * 裁剪图片 android自带的裁剪
  24. * @param activity
  25. * @param uri
  26. */
  27. public static void corpPicture(Activity activity,Uri uri){
  28. Intent innerIntent = new Intent("com.android.camera.action.CROP");//启用自带裁剪
  29. innerIntent.setDataAndType(uri, "image/*");
  30. innerIntent.putExtra("crop", "ture");//裁剪小正方形,不然没有裁剪功能,只能选取
  31. innerIntent.putExtra("aspectX", 1);//放大缩小缩放比例
  32. innerIntent.putExtra("aspectY", 1);//缩放比例 1 :1
  33. innerIntent.putExtra("outputX", 320);
  34. innerIntent.putExtra("outputY", 320);//限制图片大小
  35. innerIntent.putExtra("return-data",true);
  36. //切图大小不足 320 会出现黑框,防止出现黑框并输出
  37. innerIntent.putExtra("scale",true);
  38. innerIntent.putExtra("scaleUpIfNeeded",true);
  39. File imageFile = new File(getImagePath(activity.getApplicationContext()));//从这个文件路径创建文件
  40. innerIntent.putExtra(MediaStore.EXTRA_OUTPUT,Uri.fromFile(imageFile));
  41. //MediaStore.EXTRA_OUTPUT 表示内容解析器被用来存储请求的Uri的图像或视频
  42. innerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());//带上裁剪好的图片传递出去
  43. activity.startActivityForResult(innerIntent,REQUEST_CROP_IMAGE);
  44. }
  45. /**
  46. * 获取裁剪的图片路径
  47. * @param context
  48. * @return
  49. */
  50. public static String getImagePath(Context context){
  51. String path;
  52. if(!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
  53. //如果当前存储的状态 是 不能挂载和读写的
  54. path = context.getFilesDir().getAbsolutePath();//路径就等于这个文件的绝对路径(从根开始)
  55. }else {
  56. path = Environment.getExternalStorageDirectory().getAbsolutePath()+"/msc/";
  57. }
  58. if(!path.endsWith("/")){ //与路径的最后一个字符进行比较如果不是“/”那么就添加“/”
  59. path += "/";
  60. }
  61. File folder = new File(path);
  62. if(folder != null && !folder.exists()){//如果文件不为空 或者不存在,创建这个文件的文件夹
  63. folder.mkdirs();
  64. }
  65. path += "ifd.jpg";
  66. return path;
  67. }
  68. /**
  69. * 读取图片的属性 :的角度
  70. * @param path
  71. * @return
  72. */
  73. public static int readPictureDegree(String path){
  74. int degree = 0;//度
  75. try {
  76. ExifInterface exifInterface = new ExifInterface(path);//阅读和写作在JPEG文件的Exif标记类
  77. int orientation = exifInterface.getAttributeInt(
  78. //ExifInterface.getAttributeInt 返回指定标记的整数值
  79. ExifInterface.TAG_ORIENTATION,
  80. ExifInterface.ORIENTATION_NORMAL);//方向常规
  81. switch (orientation){
  82. case ExifInterface.ORIENTATION_ROTATE_90:
  83. degree = 90;
  84. break;
  85. case ExifInterface.ORIENTATION_ROTATE_180:
  86. degree = 180;
  87. break;
  88. case ExifInterface.ORIENTATION_ROTATE_270:
  89. degree = 270;
  90. break;
  91. }
  92. } catch (IOException e) {
  93. e.printStackTrace();
  94. }
  95. return degree;
  96. }
  97. /**
  98. * 旋转图片
  99. * @param angle 旋转角度
  100. * @param bitmap 原图
  101. * @return 旋转后的 bitmap
  102. */
  103. public static Bitmap rotateImage(int angle,Bitmap bitmap){
  104. Matrix matrix = new Matrix();
  105. matrix.postRotate(angle); //postconcats与指定的旋转矩阵
  106. Bitmap resizedBitmap = Bitmap.createBitmap(bitmap,0,0,bitmap.getWidth(),bitmap.getHeight(),matrix,true);
  107. /**
  108. * createBitmap 返回一个不可变的位图从源位图的子集
  109. * @param source The bitmap we are subsetting
  110. * @param x The x coordinate of the first pixel in source
  111. * @param y The y coordinate of the first pixel in source
  112. * @param width The number of pixels in each row
  113. * @param height The number of rows
  114. * @param m Optional matrix to be applied to the pixels 可选的矩阵应用到像素
  115. * @param filter true if the source should be filtered. 如果源应筛选,true
  116. * Only applies if the matrix contains more than just
  117. * translation.
  118. */
  119. return resizedBitmap;
  120. }
  121. /**
  122. * 保存图片
  123. * @param context
  124. * @param bitmap
  125. */
  126. public static void saveBitmapToFile(Context context, Bitmap bitmap) {
  127. String file_path = getImagePath(context);
  128. File file = new File(file_path);
  129. FileOutputStream fileOutputStream;
  130. try {
  131. fileOutputStream = new FileOutputStream(file);
  132. bitmap.compress(Bitmap.CompressFormat.JPEG,85,fileOutputStream);
  133. fileOutputStream.flush();
  134. fileOutputStream.close();
  135. } catch (FileNotFoundException e) {
  136. e.printStackTrace();
  137. } catch (IOException e) {
  138. e.printStackTrace();
  139. }
  140. }
  141. }


这个类中的裁剪方法挺好的,记住在别处也会用的着。


三、校验登陆(千万不能忘了初始化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>
  1. import android.content.DialogInterface;
  2. import android.content.Intent;
  3. import android.database.Cursor;
  4. import android.graphics.Bitmap;
  5. import android.graphics.BitmapFactory;
  6. import android.graphics.Canvas;
  7. import android.graphics.Color;
  8. import android.graphics.Matrix;
  9. import android.graphics.Paint;
  10. import android.graphics.Rect;
  11. import android.media.MediaScannerConnection;
  12. import android.net.Uri;
  13. import android.os.Environment;
  14. import android.provider.MediaStore;
  15. import android.support.v7.app.AppCompatActivity;
  16. import android.os.Bundle;
  17. import android.text.TextUtils;
  18. import android.util.Log;
  19. import android.view.View;
  20. import android.view.WindowManager;
  21. import android.widget.Button;
  22. import android.widget.EditText;
  23. import android.widget.ImageView;
  24. import android.widget.Toast;
  25. import com.iflytek.cloud.ErrorCode;
  26. import com.iflytek.cloud.FaceRequest;
  27. import com.iflytek.cloud.RequestListener;
  28. import com.iflytek.cloud.SpeechConstant;
  29. import com.iflytek.cloud.SpeechError;
  30. import com.iflytek.cloud.SpeechUtility;
  31. import org.json.JSONArray;
  32. import org.json.JSONException;
  33. import org.json.JSONObject;
  34. import java.io.ByteArrayOutputStream;
  35. import java.io.File;
  36. import java.io.UnsupportedEncodingException;
  37. import java.util.Currency;
  38. public class MainActivity extends AppCompatActivity implements View.OnClickListener{
  39. private String TAG = getClass().getCanonicalName();
  40. private final int REQUEST_PICTURE_CHOOSE = 1;
  41. private final int REQUEST_CAMERA_IMAGES = 2;
  42. private FaceRequest faceRequest;
  43. private Toast toast;
  44. private byte[] imageData = null;
  45. private Bitmap image = null;
  46. private EditText editTextUserPassword;
  47. private String UserPassword;
  48. private ProgressDialog progressDialog;
  49. private File pictureFile;
  50. @Override
  51. protected void onCreate(Bundle savedInstanceState) {
  52. super.onCreate(savedInstanceState);
  53. setContentView(R.layout.activity_main);
  54. init();
  55. }
  56. private void init() {
  57. this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);
  58. SpeechUtility.createUtility(this, "appid=" + getString(R.string.app_key));//初始化SDK 千万不能忘记写appid后边的等号 id是自己其官网上申请的
  59. //忘记会报 10274无效 key
  60. faceRequest = new FaceRequest(this);
  61. findViewById();
  62. toast = Toast.makeText(this,"",Toast.LENGTH_SHORT);
  63. progressDialog = new ProgressDialog(this);
  64. progressDialog.setCancelable(true);//设置是否可取消
  65. progressDialog.setTitle("请稍等...");
  66. progressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
  67. @Override
  68. public void onCancel(DialogInterface dialog) {
  69. if (null != faceRequest) {
  70. faceRequest.cancel();
  71. }
  72. }
  73. });
  74. }
  75. private void findViewById() {
  76. editTextUserPassword = (EditText)findViewById(R.id.editTextUserPassword);
  77. findViewById(R.id.buttonRegister).setOnClickListener(MainActivity.this);
  78. findViewById(R.id.buttonPicture).setOnClickListener(MainActivity.this);
  79. findViewById(R.id.buttonVerification).setOnClickListener(MainActivity.this);
  80. findViewById(R.id.imageViewHead).setOnClickListener(MainActivity.this);
  81. }
  82. @Override
  83. public void onClick(View v) {
  84. switch (v.getId()){
  85. case R.id.buttonPicture:
  86. pictureFile = new File(Environment.getExternalStorageDirectory(),
  87. "picture"+System.currentTimeMillis()/1000+".jpg");
  88. Intent picIntent = new Intent();
  89. picIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
  90. picIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(pictureFile));
  91. picIntent.putExtra(MediaStore.Images.Media.ORIENTATION,0);
  92. startActivityForResult(picIntent,REQUEST_CAMERA_IMAGES);
  93. break;
  94. case R.id.buttonRegister:
  95. UserPassword = ((EditText)findViewById(R.id.editTextUserPassword)).getText().toString();
  96. if(TextUtils.isEmpty(UserPassword)){
  97. showToast("请输入您的密钥");
  98. return;
  99. }else if(null != imageData){
  100. progressDialog.setMessage("注册中...");
  101. progressDialog.show();
  102. faceRequest.setParameter(SpeechConstant.AUTH_ID, UserPassword);//将授权标识和密码上传服务器记录
  103. faceRequest.setParameter(SpeechConstant.WFR_SST,"reg");//业务类型train Or verify
  104. faceRequest.sendRequest(imageData,requestListener);
  105. }else showToast("请先进行图像拍摄...");
  106. break;
  107. case R.id.buttonVerification:
  108. UserPassword = ((EditText)findViewById(R.id.editTextUserPassword)).getText().toString();
  109. if(TextUtils.isEmpty(UserPassword)){
  110. showToast("密钥不能为空哦...");
  111. }else if(imageData != null){
  112. progressDialog.setMessage("验证中,请稍等...");
  113. progressDialog.show();//6--12字符 不能以数字开头
  114. faceRequest.setParameter(SpeechConstant.AUTH_ID, UserPassword);
  115. faceRequest.setParameter(SpeechConstant.WFR_SST,"verify");
  116. faceRequest.sendRequest(imageData,requestListener);
  117. }else showToast("请先捕捉头像...");
  118. break;
  119. }
  120. }
  121. /**
  122. * 处理拍完照后,跳转到裁剪界面
  123. * @param requestCode
  124. * @param resultCode
  125. * @param data
  126. */
  127. @Override
  128. protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  129. Log.i(TAG, "运行到了onActivityResult");
  130. if(resultCode != RESULT_OK){
  131. Log.i(TAG,"requestCode未成功");
  132. return;
  133. }
  134. String fileSrc = null;
  135. if(requestCode == REQUEST_PICTURE_CHOOSE){
  136. if("file".equals(data.getData().getScheme())){
  137. fileSrc = data.getData().getPath();
  138. Log.i(TAG,"file "+fileSrc);
  139. }else {
  140. String[] proj = {MediaStore.Images.Media.DATA};
  141. Cursor cursor = getContentResolver().query(data.getData(), proj, null, null, null);
  142. cursor.moveToFirst();
  143. int idx = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
  144. fileSrc = cursor.getString(idx);
  145. cursor.close();
  146. }
  147. HeadTrim.corpPicture(this, Uri.fromFile(new File(fileSrc)));
  148. }else if(requestCode == REQUEST_CAMERA_IMAGES){
  149. if(null == pictureFile){
  150. showToast("拍照失败,请重试...");
  151. return;
  152. }
  153. fileSrc = pictureFile.getAbsolutePath();
  154. updataGallery(fileSrc);
  155. HeadTrim.corpPicture(this,Uri.fromFile(new File(fileSrc)));
  156. }else if(requestCode == HeadTrim.REQUEST_CROP_IMAGE){
  157. Bitmap bitmap = data.getParcelableExtra("data");
  158. Log.i(TAG,"bitmp是否为空");
  159. if(null != bitmap){
  160. HeadTrim.saveBitmapToFile(MainActivity.this,bitmap);
  161. }
  162. fileSrc = HeadTrim.getImagePath(MainActivity.this);//获取图片保存路径
  163. BitmapFactory.Options options = new BitmapFactory.Options();
  164. options.inJustDecodeBounds = true;
  165. image = BitmapFactory.decodeFile(fileSrc,options);
  166. options.inSampleSize = Math.max(1, (int) Math.ceil(Math.max(
  167. (double) options.outWidth / 1024f,
  168. (double) options.outHeight / 1024f
  169. )));
  170. options.inJustDecodeBounds = false;
  171. image = BitmapFactory.decodeFile(fileSrc,options);
  172. //如果imageBitmap 为空图片不能正常获取
  173. if(null == image){
  174. showToast("图片信息无法正常获取");
  175. return;
  176. }
  177. int degree = HeadTrim.readPictureDegree(fileSrc);
  178. if(degree != 0){
  179. image = HeadTrim.rotateImage(degree,image);
  180. }
  181. ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
  182. image.compress(Bitmap.CompressFormat.JPEG,80,byteArrayOutputStream);
  183. imageData = byteArrayOutputStream.toByteArray();
  184. ((ImageView)findViewById(R.id.imageViewHead)).setImageBitmap(image);
  185. }
  186. }
  187. @Override
  188. public void finish() {
  189. if(null != progressDialog){
  190. progressDialog.dismiss();
  191. }
  192. super.finish();
  193. }
  194. private void updataGallery(String fileName) {
  195. MediaScannerConnection.scanFile(this, new String[]{fileName}, null,
  196. new MediaScannerConnection.OnScanCompletedListener() {
  197. @Override
  198. public void onScanCompleted(String path, Uri uri) {
  199. }
  200. });
  201. }
  202. /**
  203. * 请求对象监听 , 对服务器返回来的数据进行解析 JSON格式
  204. */
  205. private RequestListener requestListener = new RequestListener() {
  206. @Override
  207. public void onEvent(int i, Bundle bundle) {
  208. }
  209. @Override
  210. public void onBufferReceived(byte[] bytes) {
  211. if(null != progressDialog){
  212. progressDialog.dismiss();
  213. }
  214. try {
  215. String result = new String(bytes,"utf-8");
  216. Log.i(TAG,result);
  217. JSONObject object = new JSONObject(result);
  218. String type = object.optString("sst");//获取业务类型
  219. if("reg".equals(type)){//注册
  220. register(object);
  221. }else if("verify".equals(type)){//校验
  222. verify(object);
  223. }else if("detect".equals(type)){
  224. detect(object);
  225. }else if("aligm".equals(type)){
  226. //align(object);
  227. }
  228. } catch (UnsupportedEncodingException e) {
  229. e.printStackTrace();
  230. } catch (JSONException e) {
  231. e.printStackTrace();
  232. }
  233. }
  234. @Override
  235. public void onCompleted(SpeechError speechError) {//完成后
  236. if(null != progressDialog){
  237. progressDialog.dismiss();
  238. }
  239. if(speechError != null ){
  240. switch (speechError.getErrorCode()){
  241. case ErrorCode.MSP_ERROR_ALREADY_EXIST:
  242. showToast("密钥已被注册,请更换后再试...");
  243. break;
  244. default:showToast(speechError.getPlainDescription(true));
  245. break;
  246. }
  247. }
  248. }
  249. };
  250. //检测
  251. private void detect(JSONObject object) throws JSONException{
  252. int ret = object.getInt("ret");
  253. if(ret != 0){
  254. showToast("检测失败");
  255. }else if("success".equals(object.get("rst"))){
  256. JSONArray jsonArray = object.getJSONArray("face");
  257. Paint paint = new Paint();
  258. paint.setColor(Color.RED);
  259. paint.setStrokeWidth(Math.max(image.getWidth(), image.getHeight()) / 100f);
  260. Bitmap bitmap = Bitmap.createBitmap(image.getWidth(),image.getHeight(), Bitmap.Config.ARGB_8888);
  261. Canvas canvas = new Canvas(bitmap);
  262. canvas.drawBitmap(image,new Matrix(),null);
  263. for(int i = 0;i<jsonArray.length();i++){
  264. float x1 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("left");
  265. float y1 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("top");
  266. float x2 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("right");
  267. float y2 = (float) jsonArray.getJSONObject(i).getJSONObject("position").getDouble("bottom");
  268. paint.setStyle(Paint.Style.STROKE);
  269. canvas.drawRect(new Rect((int)x1,(int)x2,(int)x2,(int)y2),paint);
  270. }
  271. image = bitmap;
  272. ((ImageView)findViewById(R.id.imageViewHead)).setImageBitmap(image);
  273. }else {
  274. showToast("检测失败");
  275. }
  276. }
  277. /**
  278. * 校验
  279. * @param object
  280. */
  281. private void verify(JSONObject object) throws JSONException{
  282. int ret = object.getInt("ret");
  283. Log.i(TAG,"ret校验"+ret);
  284. if(ret != 0){
  285. showToast("校验失败..."+ret);
  286. }else if("success".equals(object.get("rst"))){
  287. if(object.getBoolean("verf")){
  288. showToast("验证通过");
  289. editTextUserPassword.setText(null);
  290. startActivity(new Intent(MainActivity.this,JumpActivity.class));
  291. }else if(!object.getBoolean("verg")){
  292. showToast("验证不通过");
  293. }else showToast("验证失败");
  294. }
  295. }
  296. /**
  297. * 如果收回的数据类型是注册 进行一下处理
  298. * @param object
  299. */
  300. private void register(JSONObject object) throws JSONException{
  301. int ret = object.getInt("ret");//解析ret返回值 0代表成功 -1失败 或者其他的错误异常代码
  302. if(ret != 0){
  303. showToast("注册失败");
  304. return;
  305. }else if("success".equals(object.get("rst"))){
  306. showToast("注册成功");
  307. editTextUserPassword.setText(null);
  308. }else showToast("注册失败,错误");
  309. }
  310. //土司对话框
  311. private void showToast(final String s){
  312. toast.setText(s);
  313. toast.show();
  314. }
  315. }

Ok 就这个简单。

效果:



声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/225333
推荐阅读
相关标签
  

闽ICP备14008679号