需求分析
第一步我对该实验做了一个完整性的需求分析:
我们需要做到以下几点:
(1)学生信息的管理,对学生的信息的添加,删除,编译修改;
(2)基于每个学生的人脸上传,并识别该图片是否是一个人脸图片;
(3)基于上传后的学生人脸,进行同一个人的不同角度,不同角度进行不同程度的人脸识别控制;
(4)开启二维码扫描功能,解析二维码的含义;
(5)开启物品识别功能;
4.2 数据考察和数据收集
系统分为以下三部分:
4.4 系统实际操作流程
4.5 实际操作实现
4.5.1 主页面的设计:
布局采取LinearLayout线性布局,因为手机屏幕的大小有限,所以采取使用ScrollView控件,使得该activity布局页面可以添加入更多的控件,在ScrollView中添加控件到屏幕以外后,它会自动的向下滑动并把该控件包含在屏幕中,不会使控件无法显示在屏幕中。在ScrollView中继续使用线性布局,在线性布局的第一行中嵌套一个LinearLayout线性布局,使用一个relativeLayout布局添加app的header,在线性布局的第二,第三,第四,第五行对应的是学生信息管理、查询学生信息、学生人脸上传、点名系统模块。
额外添加: 因为系统自带顶部tittle不美观,所以设计了一个tittle.xml插入到每一个页面,在后面的报告中不再馁述。
添加代码:
TitleLayout代码如下:
显示:
Xml代码
主页面如下:
因为该主题是图像处理,所以该报告主要解释上传头像和点名系统的人脸图像处理模块
4.5.2 学生信息模块:
(1)布局解释
主布局设计为线性布局,设计list列表的每一列的列名,采用listview显示学生的基本信息,因为手机的屏幕宽度有限,所以我设计在listview 中只显示学生图片,学生的id号,学生的姓名,学生的联系方式(电话号码),在每一行的节点item的尾部设计删除按键,可以选择删除指定学生,并实现listview节点item点击事件,点击节点item显示该学生的详细信息,在显示详细信息后可选择编译按钮对学生信息的修改,注意:学生的id号无法修改,因为用id特征分辨不同学生,不能存在两个相同id的学生。在信息添加的过程中使用了以下几种控件,以简便输入学生的信息:在性别选择上使用单选框控件RadioButton,分别只能选择男或者女;在年龄上使用下拉式菜单,选择1岁50岁;在班级上使用下拉式菜单,只能选择13班中的一个选项。点击按钮添加后,会验证每一个选项是否填入正确,若非法则提示相应提醒。
(2)布局显示
添加信息后会使所有填入信息置为空,并相应提醒填入的值。
(3)逻辑代码实现
①Listview显示逻辑代码:
获取lv实例:
lv = (ListView) findViewById(R.id.lv);
执行lv.setAdapter(new Adapter); listview适配器代码显示listview中的item值
②自定义适配器代码:
private class MyAdapter extends BaseAdapter {
@Override
public int getCount() {
return dao.getTotalCount();
}
@Override
public View getView(final int position, View convertView, ViewGroup parent) {
View view = View.inflate(addstudent.this,R.layout.item,null);
TextView tv_item_id = (TextView) view.findViewById(R.id.tv_item_id);
TextView tv_item_name = (TextView) view.findViewById(R.id.tv_item_name);
TextView tv_item_phone = (TextView) view.findViewById(R.id.tv_item_phone);
ImageView touxiang_image=(ImageView) view.findViewById(R.id.student_image);
ImageView iv_delete = (ImageView) view.findViewById(R.id.iv_delete);
final Map<String, String> map = dao.getStudentInfo(position);
iv_delete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean result = dao.delete(map.get("studentid"));
if (result) {
Toast.makeText(addstudent.this,"删除成功", Toast.LENGTH_SHORT).show();
lv.setAdapter(new MyAdapter());
}
}
});
//界面只显示三列即可
tv_item_id.setText(String.valueOf(map.get("studentid")));
tv_item_name.setText(map.get("name"));
tv_item_phone.setText(map.get("phone"));
//此处image 初始使用同一个默认图片
if(map.get("touxiang_id")==null||map.get("touxiang_id").equals("1")){
touxiang_image.setImageDrawable(ContextCompat.getDrawable(getApplicationContext(),R.drawable.jjy1));
}
else {
touxiang_image.setImageBitmap(getimage(map.get("touxiang_id")));
}
return view;
}
@Override
public StudentInfo getItem(int position) {
// return list.get(position);
return null;
}
@Override
public long getItemId(int position) {
return 0;
}
}
把自定义适配器传入lv适配器拷贝构造函数中,使lv初始化本地SQLit数据库中的学生信息数据。
③点击事件的实现:用AlertDialog+View 定义显示框,显示出学生的详细信息,并且添加确定和编译按钮,实现编译和确定的事件:
显示框的初始化:
final LayoutInflater inflater=addstudent.this.getLayoutInflater();
final View view1=inflater.inflate(R.layout.authorize_dialog,null,false);
Context mContext=addstudent.this;
AlertDialog.Builder builder=new AlertDialog.Builder(mContext);
builder.setView(view1);
builder.setCancelable(false);
final AlertDialog alert=builder.create();
Listview的item点击事件:
lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int position, long id) {
final Map<String, String> de = dao.getStudentInfo(position);
EditText stu_id = (EditText) view1.findViewById(R.id.student_id);
EditText stu_name = (EditText) view1.findViewById(R.id.student_name);
EditText stu_sex = (EditText) view1.findViewById(R.id.student_sex);
EditText major_na = (EditText) view1.findViewById(R.id.student_major_name);
EditText college_na = (EditText) view1.findViewById(R.id.student_college_name);
EditText tel_number = (EditText) view1.findViewById(R.id.student_tel);
EditText banji = (EditText) view1.findViewById(R.id.student_banji);
EditText age=(EditText) view1.findViewById(R.id.student_age);
edts=new ArrayList<EditText>();
edts.add(stu_id);
edts.add(stu_name);
edts.add(stu_sex);
edts.add(major_na);
edts.add(college_na);
edts.add(tel_number);
edts.add(banji);
edts.add(age);
setEdictale(false);// 无法编译
ImageView image_title=(ImageView)view1.findViewById(R.id.student_image);
if(de.get("touxiang_id")!=null&&!de.get("touxiang_id").equals("1")){
image_title.setImageBitmap(getimage(de.get("touxiang_id")));
}
stu_id.setText(de.get("studentid"));
stu_name.setText(de.get("name"));
stu_sex.setText(de.get("sex"));
System.out.println(de.get("age"));
age.setText(de.get("age"));
banji.setText(de.get("banji"));
major_na.setText(de.get("major_na"));
college_na.setText(de.get("college_na"));
tel_number.setText(de.get("phone"));
banji.setText(de.get("banji"));
alert.show();
}
});
点击后的程序显示执行效果如下:
注意:在没有上传学生的人脸图像前使用系统初始化图片:此处使用的我自己的偶像—鞠婧祎的照片啦!
点击显示资料 编译显示 编译完成4.5.3 学生头像上传系统模块:
学生通过学生自己的学号id和密码(初始密码为该学生学号id)进入上传,通过调用本机系统照相机进行拍照人脸或者上传本地相册,然后开启新线程对上传的图片进行比对是否人脸,然后返回一个提醒,如果是人脸那么返回上传成功,如果不是人脸或者其他光线过差等情况则返回一个提示。注意:无论是否上传成功,都会把拍照后的图片保存到本地文件夹下,该文件夹在上传时添加,若不添加则保存到系统根目录下,照片的名字为该学生id.jpg。
学生上传头像主页面: 上传学生人脸选择框:
上传中:
上传过程图:
4.5.4 头像验证系统模块:
在头像上传后,我们希望可以通过人脸识别+人脸比对来对同一个学生的不同人脸图片进行人脸识别。通过与上传对图片处理的同样操作,对传入的图片进行放缩+质量压缩转化为Base64Util代码,上传到百度api进行人脸比对,如果在该人脸库就返回签到成功。如果不存在等情况,即返回一个提示信息。如果签到成功,即使该学生的item上的checkbox置为true。
运行状况图:
上传签到人脸,进行人脸识别与该学生的真实人脸进行比对,签到成功效果图