Android课程设计 人脸识别签到(二)

学习完百度人脸API的调用,现在即可开发自己的人脸识别签到系统,下面作者先贴上部分功能源码来给大家参考和学习

(一)百度人脸库的人脸验证

1°   获取待识别的照片

既然是人脸认证 那么当然首先得向百度人脸库添加你的人脸

然后再把你需要进行人脸识别的照片与百度人脸库的人脸进行校对,如果校对成功,即签到打卡成功

关于获取带人脸识别的照片,作者采取了两种方式获取(即时拍照、从相册导入)

即时拍照:

Camera.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        StrictMode.VmPolicy.Builder builder = new StrictMode.VmPolicy.Builder();
        StrictMode.setVmPolicy(builder.build());
        builder.detectFileUriExposure();            //Android7.0拍照必加   且需要在方法类前加@SuppressLint("NewApi")

        File outputImage = new File(Environment.getExternalStorageDirectory() + File.separator + "face.jpg");     //临时照片存储地
        try {
            if (outputImage.exists()) {
                outputImage.delete();              //若临时存储地已有照片则delete
            }
            outputImage.createNewFile();           //临时存储地创建新文件
        } catch (IOException e) {
            e.printStackTrace();
        }
        imageUri = Uri.fromFile(outputImage);              //获取临时存储地Uri
        ImagePath = outputImage.getAbsolutePath();           //得到绝对路径
        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);    //跳转相机
        intent.putExtra(MediaStore.EXTRA_OUTPUT, imageUri);                          //相片输出路径
        startActivityForResult(intent, CAMERA);                        //返回照片路径
    }
});

从相册直接获取:

       getImage.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent in = new Intent(Intent.ACTION_PICK);      //选择数据
                in.setType("image/*");                //选择的数据为图片
                startActivityForResult(in, Photo_ALBUM);
            }
        });

获取照片之后需要把照片显示到手机APP界面上,给用户做一个预览   也就是方法startActivityForResult的作用

关于拍照旋转角度问题解释(https://www.jianshu.com/p/6179f16907dc)

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        // 相册选择图片
        if (requestCode == Photo_ALBUM) {
            if (data != null) {
                Uri uri = data.getData();           //获取图片uri
                Cursor cursor = getContentResolver().query(uri, null, null, null, null);
                cursor.moveToNext();
                ImagePath = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));   //获得图片的绝对路径
                cursor.close();
                resizePhoto();         //将图片变成缩小的bitmap  方法后贴
                int degree = getPicRotate(ImagePath);        //获取拍照图片的旋转角度   可以查一下我给出的地址  getPicRotate方法在下面
                Matrix m = new Matrix();    //对图形处理
                m.setRotate(degree);        //旋转
                lastp = Bitmap.createBitmap(myBitmapImage, 0, 0, myBitmapImage.getWidth(), myBitmapImage.getHeight(), m, true);    //获取缩小且旋转好的图片
                myPhoto.setImageBitmap(lastp);       //显示图片
                Log.i("图片路径", ImagePath);
            }
        } else if (requestCode == CAMERA) {
            try {
                resizePhoto();
                int degree = getPicRotate(ImagePath);          //获取旋转角度
                Matrix m = new Matrix();    //对图形处理的类
                m.setRotate(degree);        //旋转

               lastp = Bitmap.createBitmap(myBitmapImage, 0, 0, myBitmapImage.getWidth(), myBitmapImage.getHeight(), m, true);
                myPhoto.setImageBitmap(lastp);       //显示图片
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

获取旋转角度

 1  public int getPicRotate(String path) {          //旋转图片
 2         int degree = 0;
 3         try {
 4             ExifInterface exifInterface = new ExifInterface(path);
 5             int orientation = exifInterface.getAttributeInt(
 6                     ExifInterface.TAG_ORIENTATION,
 7                     ExifInterface.ORIENTATION_NORMAL);          //命名空间 命名空间所属属性
 8             switch (orientation) {
 9                 case ExifInterface.ORIENTATION_ROTATE_90:
10                     degree = 90;
11                     break;
12                 case ExifInterface.ORIENTATION_ROTATE_180:
13                     degree = 180;
14                     break;
15                 case ExifInterface.ORIENTATION_ROTATE_270:
16                     degree = 270;
17                     break;
18             }
19         } catch (IOException e) {
20             e.printStackTrace();
21         }
22         return degree;
23     }

2°   上传待查照片到百度开发平台,与百度人脸库里已存的照片进行匹配

既然已经获取了待查照片,那么现在即把照片与人脸库的已有照片进行匹配,若百度人脸库存在此人,那么就匹配成功(即签到成功)

1.当点击识别按钮后,将待查照片上传,并创建一个线程用于处理放回的结果

 detect.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                res = null;
                tip.setVisibility(View.VISIBLE);         //识别中提示   在Android界面显示
                if (myBitmapImage == null) {
                    Toast.makeText(MainActivity.this, "请添加图片!!!", Toast.LENGTH_LONG).show();
                    tip.setVisibility(View.GONE);         //隐藏    识别中提示
                }
                else if(Class.getText().toString().trim().equals("请输入查课节次")==true){
                    Toast.makeText(MainActivity.this, "请输入查课节次!!!", Toast.LENGTH_LONG).show();
                    tip.setVisibility(View.GONE);
                    }
                else {
                       //对于上传的图片进行处理
                    int degree = getPicRotate(ImagePath);
                    Matrix m = new Matrix();    //对图形处理
                    m.setRotate(degree);        //旋转
                    bitmapSmall = Bitmap.createBitmap(myBitmapImage, 0, 0, myBitmapImage.getWidth(), myBitmapImage.getHeight(), m, true);
                    ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    //图片转数据流
                    bitmapSmall.compress(Bitmap.CompressFormat.JPEG, 100, stream);     //图片压缩格式,压缩率,文件输出流对象
                    final byte[] arrays = stream.toByteArray();                 //转成二进制数组
                    final String pic = android.util.Base64.encodeToString(arrays, Base64.DEFAULT);   //获取图片 Base64格式的String
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            HashMap<String, String> options = new HashMap<>();
                            options.put("quality_control", "NORMAL");                  //质量控制
                            options.put("liveness_control", "LOW");                      //活体控制
                            options.put("max_user_num", "3");                         //返回结果的最大个数

                            String groupId = "ruan1,ruan2";                              //查询的人脸组
                            String imageType = "BASE64";                                    //上传的图片格式

                            AipFace client = new AipFace("15119543", "lwxkzZOqjm4bcN2DmHoe8giy", "skYUhhZAfsUCFsBud7VQPIdWPvMt7tOM");
                            client.setConnectionTimeoutInMillis(2000);          //超时设置
                            client.setSocketTimeoutInMillis(6000);

                            res = client.search(pic, imageType, groupId, options);         //获取查询结果集

                            try {
                                Message message = Message.obtain();
                                message.what = 1;
                                message.obj = res;
                                handler.sendMessage(message);
                            } catch (Exception e) {
                                e.printStackTrace();
                                Message message = Message.obtain();
                                message.what = 2;
                                handler.sendMessage(message);
                            }

                        }
                    }).start();
                }
            }
        });
    }

2.当上传完图片后,即可获取查询结果集,那么将结果集交由线程进行处理

private Handler handler = new Handler() {
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            JSONObject jsonObject=null;
            String classes = null;
            String Record_class = null;
            String PId =  null;
            String name =  null;
            if (msg.what == 1) {                     //放回有效的结果集
                JSONObject res = (JSONObject) msg.obj;
                System.out.println(res);
                error_code = res.optString("error_code");        //看是否查询成功
                System.out.println(error_code);
                if (error_code.equals("0") == true) {
                    JSONArray TEMP = res.optJSONObject("result").optJSONArray("user_list");       //获取查询结果集的  用户列表

                    try {
                        jsonObject = TEMP.getJSONObject(0);
                        String Tscore = jsonObject.getString("score");
                         classes = jsonObject.getString("group_id");                  //这里获取classes到获取name  是为了后面实现将查询结果同步到服务器数据库做准备
                         Record_class = Class.getText().toString().trim();
                         PId = jsonObject.getString("user_id");
                         name = jsonObject.getString("user_info");
                        System.out.println(classes+Record_class+ PId+ name);
                        System.out.println(jsonObject);
                        System.out.println(Tscore);
                        score = Double.parseDouble(Tscore);                //获取最相似人脸分数    因为最相似人脸会直接放到查询的user_list的第一个
                        System.out.println(score);

                        //  score=Math.ceil(Double.parseDouble(Tscore));
                    } catch (JSONException SE) {
                        SE.printStackTrace();
                    }
                    if (score >= 75) {                                //若相似度大于75
                        addrecord(classes,Record_class,PId,name);                 //服务器数据库添加查询成功的结果
                        } else
                        Toast.makeText(MainActivity.this, "打卡失败,请重新导入照片", Toast.LENGTH_LONG).show();

                        myBitmapImage = null;
                        InitBitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.show, null);
                        tip.setVisibility(View.GONE);
                         myPhoto.setImageBitmap(InitBitmap);
                }
                else
                    Toast.makeText(MainActivity.this, "打卡失败,请重新导入照片", Toast.LENGTH_LONG).show();
                    tip.setVisibility(View.GONE);
            }

        }
    };

关于addrecord方法,我用了Android的volley框架来进行与自己服务器后台的交互

 public void addrecord(final String classes,final String Record_class,final String PId,final String name){
        Log.d("addrecord",classes+","+PId+","+name);
        //请求地址,需要换接口

        String url="http://47.106.10.15:8080/FtoFserver/FtoFserver/addRecord";     //服务器后台的接口   我接口使用Servelet写的

        String tag = "addrecord";
        //取得请求队列
        RequestQueue requestQueue = Volley.newRequestQueue(MainActivity.this);          //传参为当前的context
        //防止重复请求,所以先取消tag标识的请求队列
        requestQueue.cancelAll(tag);
        //创建StringRequest,定义字符串请求的请求方式为POST(省略第一个参数会默认为GET方式)
        StringRequest request = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>() {
                    @Override
                    public void onResponse(String response) {
                        Log.d("response",response);
                        try {
                            JSONObject jsonObject = new JSONObject(response);        //获取的到的后台回应
                            temp = jsonObject.getString("canLogin");
                            if(temp.equals("true")){
                                //等待接口
                                System.out.println("发布成功");
                                Toast.makeText(MainActivity.this, "打卡成功!!!", Toast.LENGTH_LONG).show();
                            }else {
                                System.out.println("发布失败");
                                Toast.makeText(MainActivity.this, "网络延迟,请重新上传!!!", Toast.LENGTH_LONG).show();
                            }
                        } catch (JSONException e) {
                            //做自己的请求异常操作,如Toast提示(“无网络连接”等);
                            e.printStackTrace();
                        }
                    }
                }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                //做自己的响应错误操作,如Toast提示(“请稍后重试”等)
                Log.d("error",error.toString());
            }
        }) {
            @Override
            protected Map<String, String> getParams() throws AuthFailureError {
                Map<String,String> params = new HashMap<>();                      //将打卡成功的人的信息同步到自己的服务器端
                params.put("classes", classes);                                    //传参到服务器接口
                params.put("Record_class",Record_class);
                params.put("PId",PId);
                params.put("name",name);
                System.out.println(name);
                return params;
            }

        };

        //设置Tag标签
        request.setTag(tag);
        request.setRetryPolicy(new DefaultRetryPolicy(20*1000,1,1.0f));
        //将请求添加到队列中
        requestQueue.add(request);
    }

3°当验证完所有人脸,又把验证结果同步到自己事先部署的服务器端后,即完成了所以打卡操作

接下来   就可以用普通的servelet来获取服务器中存储的所有总的签到结果

即可导出已签到的人和未签到的人

补充 :

当然百度人脸库的更新、添加、删除也与打卡操作大同小异   也可以编辑类似上面的代码 来直接在安卓端操作

例如:

你可以事先在百度人脸库创建分组,然后往分组添加人脸的时候,同时完成添加人脸和添加自己服务端的人脸花名册信息操作

这样既可以抛去对直接去操作百度控制台的的操作

查询已经签到人:

可以直接查看自己服务器端的签到记录获取

查看未签到人:

可以通过服务器端的  班级花名册  减去签到记录已有的人

既可以获取未签到的人

原文地址:https://www.cnblogs.com/Mr-BING/p/10160920.html

时间: 2024-10-11 05:10:17

Android课程设计 人脸识别签到(二)的相关文章

Android静态图片人脸识别的完整demo(附完整源码)

Demo功能:利用android自带的人脸识别进行识别,标记出眼睛和人脸位置.点击按键后进行人脸识别,完毕后显示到imageview上. 第一部分:布局文件activity_main.xml [html] view plaincopyprint? <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.co

[Android]虹软arcface人脸识别SDK引擎使用总结

虹软开放了人脸识别的SDK引擎(免费的哦),刚好有Android版的,就体验了一波.下面来说说Android版的SDK使用心得: ArcFace 虹软人脸认知引擎简介 目前开放的版本有人脸比对(1:1)和人脸检索(1:N),根据应用场景可选择 人脸检索分为小型网络(检测100人内),中型网络(1000人内),大型网络(需联系虹软官方) 目前开放的功能有人脸比对,人脸识别,人脸追踪 关于如何使用 在官网下载SDK引擎后集成到你的项目中,然后我在此举例说下其中一个sample:人脸识别 官方samp

Android课程设计第六天欢迎界面(跳转)

注意:课程设计只为完成任务,不做细节描述~ package com.example.myapplication; import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.widget.TextView; /** * Created by 樱花落舞

Android课程设计第二天界面排版

注意:课程设计只为完成任务,不做细节描述~ 老师叫我们做一个这个样子,然后.. 1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 xmlns:tools="http://schemas.android.com/tools"

Android课程设计第五天欢迎界面(滑动)

注意:课程设计只为完成任务,不做细节描述~ 滑动界面 1 package com.example.myapplication; 2 3 import android.content.Intent; 4 import android.os.Handler; 5 import android.os.Message; 6 import android.support.v7.app.AppCompatActivity; 7 import android.os.Bundle; 8 9 import Uti

Android课程设计第四天ListView运用

注意:课程设计只为完成任务,不做细节描述~ 效果图 1 <?xml version="1.0" encoding="utf-8"?> 2 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 4 xmlns:tools="http://schemas.android.com/tools" 5 android:l

android上实现人脸识别的功能

====================问题描述==================== 如题,小弟想在android上实现一个基于人脸识别的功能,大致的实现框架是这样的: 1.通过前置照相机捕捉到人的脸部特征2.将人的脸部特征通过一些算法(网上查看诸如adaboost算法,PCA算法)取得特征值,然后ID化3.将人脸ID化的结果存入数据库4.重复1,2如果ID化的结果在人脸特征值数据库中某记录值的阈值范围内,则证明该值存在,通过验证,否则,提醒注册人脸特征库. 现在基本确定实现是这样的一个流程

Android课程设计——博学谷1.0

没错,又是一学期期末时,我又来补课程设计了,hhh. 总体认识 服务器端: 首先在NetBeans中打开服务器端程序: 然后打开Navicat,连接到wlw1db数据库,建立一张自己的表,再添加所要访问的用户信息: 然后再修改服务器程序中连接数据库的常用类——DBUtil中的连接方法getConn(),确保数据库连接成功. 最后运行serverlet中的ListAllUserServlet可以在浏览器中看到所有用户username和password的json串. 手机端: 首先模拟运行之前的An

人脸识别签到 电子班牌加速校园智慧化进程

2018年教育部印发<教育部2018年工作要点>,提出信息化2.0,校园.班级也随之步入了精细化的数字管理时代.为加速推进落地智慧教育政策方针,传统的教学方式不再可以满足"走班制"教学的要求,电子班牌开始成为教育现代化和信息化的关键工具. 以往,课堂教学模式通常有口头点名.手抄黑板报.纸质课表等,学生管理方式落后.校园文化建设方式陈旧.家校沟通不及时是一直以来普遍存在的几大难题.智慧电子班牌正是为解决这些问题而生. 郑州非思丸是一家致力于结合云计算.物联网.人工智能.移动社