人生处处皆考场,每一个人从小学到大学毕业,都会经历大大小小很多场考试。每一次重要的考试,都会有监考人员对考生的身份进行比对,并要求考生签到。如果有一台能自动识别考生、并且能够自动签到的系统,就可以提高识别的准确率,并且减轻监考人员的负担,使比对及统计工作更加简单方便。
本项目想要实现的效果是:当考生走到系统前,系统蓝灯闪烁并播放音乐提醒考生"对准摄像头”,如果考生在考场名单中,则显“***签到成功,祝你好运”,同时亮绿灯,播放签到成功的音乐;如果考生不在本场名单中,则显示“无法识别,你是走错考场了吗?”,亮红灯,播放签到不成功的音乐;如果有人重复签到,则不亮灯,并显示“你已签到成功,无需再次签到”。在系统工作过程中,可以随时查看签到人数及具体名单,也可查看未签到人数。在考生签到时,系统向服务器发送签到数据,及签到人数。
步骤1 二哈人脸识别设置
考生报名时,都需要进行头像采集,此时可以让二哈进行多人像学习。
首先进行二哈多个人脸识别设置。
1.拨动“功能按键”,至屏幕顶部为“人脸识别”。
2.长按“功能按键”,进入“人脸识别”二级菜单。
3.拨动“功能按键”,至“学习多个”,在“学习多个”上方出现一滑条,再次拨动“功能按键”,至滑条最右。
4.短按“功能按键”,退出“学习多个”,再次拨动至“检测阀值”、“NMS阀值”、“识别阀值”等,拨动“功能按键”,设置合适的数值。此数值可先行测试,过低容易造成识别准确度不高;过高又可能造成识别困难。
5.拨动“功能按键”至“保存并退出”,确认“保存”,再次短按退出。
步骤2 二哈人脸学习
1.将屏幕中的“+”对准要学习的人脸,长按“学习键”,从各个角度录入人脸,屏幕中的白色方框角落出现人脸ID号,松开“学习键”。
2.再次按下“学习键”,学习另一个人脸,以此类推。
3.操作中,尽量避免“遗忘”,在屏幕显示”遗忘“时,意味着前期录入数据清空,将需要重新录入。
步骤3 线路连接
掌控板自带显示屏、LED灯、百灵鸽可以播放音乐,因此连接时,只需要将摄像头连接到百灵鸽的IIC接口即可,连接方式极为简单。
步骤4 SIOT设置
1.下载适用的SIOT,并运行。
2. 访问服务器,设置好项目及设备。
具体操作可参考另一个帖子《掌控无线测温仪》,https://mc.dfrobot.com.cn/thread-302719-1-1.html。
步骤5 程序编写
1.首先是主程序。
2.按A键签到。其实原来的设想是当有人靠近时,就启动签到程序。但是又担心如果用人体热释电模块,会与其它按键冲突,于是选择放弃。
3.按B键,清空当场考试记录。
4.触摸Y键显示签到情况。
5.触摸O键显示未签到人数和其它的一些函数。
步骤6 积木组装
这部分,没有参考,作者也没啥天赋,纯属瞎凑~
/*!
* MindPlus
* mpython
*
*/
#include <MPython.h>
#include <SimpleList.h>
#include <DFRobot_Iot.h>
#include <MPython_NtpTime.h>
#include <DFRobot_HuskyLens.h>
// 动态变量
String mind_s_qdmd;
volatile float mind_n_num, mind_n_i, mind_n_numw, mind_n_ksxh;
SimpleList<String> mind_l_QianDaoMingDan, mind_l_QuanBuKaoShengMingDan, mind_l_WeiQianDaoMingDan;
// 函数声明
void onButtonBPressed();
void pin14TouchCallback();
void DF_TongJiZhong();
void pin15TouchCallback();
void DF_ChengGongLED();
void DF_WuFaShiBie();
void DF_ChuShiHuaKaoShengMingDan();
void onButtonAPressed();
void DF_DengDaiQianDao();
void DF_WuFaShiBieLED();
// 静态常量
const String topics[5] = {"ksqdy/1号","ksqdy/2号","","",""};
// 创建对象
DFRobot_Iot myIot;
DFRobot_HuskyLens huskylens;
MPython_NtpTime ntptime;
// 主程序开始
void setup() {
mPython.begin();
buttonB.setPressedCallback(onButtonBPressed);
touchPadY.setTouchedCallback(pin14TouchCallback);
touchPadO.setTouchedCallback(pin15TouchCallback);
buttonA.setPressedCallback(onButtonAPressed);
rgb.write(-1, 0x000000);
myIot.wifiConnect("FAST_103", "y2611278");
display.fillScreen(0);
display.setCursor(5, 22);
display.print("Wi-Fi正在连接中……");
while (!myIot.wifiStatus()) {yield();}
display.fillScreen(0);
display.setCursor(15, 22);
display.print("Wi-Fi已连接成功");
delay(1000);
display.fillScreen(0);
display.setCursor(5, 22);
display.print("MQTT正在连接中……");
myIot.init("192.168.0.102","siot","","dfrobot", topics, 1883);
myIot.connect();
while (!myIot.connected()) {yield();}
display.fillScreen(0);
display.setCursor(15, 22);
display.print("MQTT已连接成功");
huskylens.beginI2CUntilSuccess();
huskylens.writeAlgorithm(ALGORITHM_FACE_RECOGNITION);
delay(3000);
display.fillScreen(0);
display.setCursor(10, 22);
display.print("考生自动识别签到仪");
delay(5000);
mind_l_QuanBuKaoShengMingDan.clear();
DF_ChuShiHuaKaoShengMingDan();
mind_n_num = 0;
display.fillScreen(0);
display.setCursor(35, 0);
display.print("使用方法");
display.setCursor(6, 15);
display.print("A键识别,B键清空考场记录。Y键查看已签到,O键查看未签到。");
}
void loop() {
}
// 自定义函数
void DF_TongJiZhong() {
rgb.brightness(round(3));
for (int index = 0; index < 3; index++) {
rgb.write(-1, 0xFFFF00);
delay(200);
rgb.write(-1, 0x000000);
delay(200);
yield();
}
rgb.write(-1, 0xFFFF00);
}
void DF_ChengGongLED() {
rgb.brightness(round(3));
for (int index = 0; index < 3; index++) {
rgb.write(-1, 0x33CC00);
delay(200);
rgb.write(-1, 0x000000);
delay(200);
yield();
}
rgb.write(-1, 0x33CC00);
}
void DF_WuFaShiBie() {
display.fillScreen(0);
display.setCursor(15, 15);
display.print("你好,无法识别,");
display.setCursor(10, 32);
display.print("你是走错试场了吗?");
}
void DF_ChuShiHuaKaoShengMingDan() {
mind_l_QuanBuKaoShengMingDan.push_back("贾迎春");
mind_l_QuanBuKaoShengMingDan.push_back("贾惜春");
mind_l_QuanBuKaoShengMingDan.push_back(" 妙玉");
mind_l_QuanBuKaoShengMingDan.push_back("贾元春");
mind_l_QuanBuKaoShengMingDan.push_back("贾探春");
mind_l_QuanBuKaoShengMingDan.push_back("贾宝玉");
mind_l_QuanBuKaoShengMingDan.push_back("林黛玉");
mind_l_QuanBuKaoShengMingDan.push_back("薛宝钗");
mind_l_QuanBuKaoShengMingDan.push_back("史湘云");
}
void DF_DengDaiQianDao() {
rgb.brightness(round(3));
for (int index = 0; index < 3; index++) {
rgb.write(-1, 0x0000FF);
delay(200);
rgb.write(-1, 0x000000);
delay(200);
yield();
}
rgb.write(-1, 0x0000FF);
}
void DF_WuFaShiBieLED() {
rgb.brightness(round(3));
for (int index = 0; index < 3; index++) {
rgb.write(-1, 0xFF0000);
delay(200);
rgb.write(-1, 0x000000);
delay(200);
yield();
}
rgb.write(-1, 0xFF0000);
}
// 事件回调函数
void onButtonBPressed() {
mind_l_QianDaoMingDan.clear();
rgb.write(-1, 0x000000);
display.fillScreen(0);
display.setCursor(17, 22);
display.print("考场记录已删除");
delay(5000);
display.fillScreen(0);
}
void pin14TouchCallback() {
ntptime.setNtpTime(ntptime.UTCEast8_t, "ntp.ntsc.ac.cn");
display.fillScreen(0);
display.setCursor(5, 22);
display.print("签到人数正在统计……");
DF_TongJiZhong();
delay(5000);
display.fillScreen(0);
display.setCursor(0, 15);
display.print((String(ntptime.localTime(ntptime.Year)) + String((String("年") + String((String(ntptime.localTime(ntptime.Month)) + String((String("月") + String((String(ntptime.localTime(ntptime.Date)) + String((String("日") + String((String(ntptime.localTime(ntptime.Hour)) + String((String("时") + String((String(ntptime.localTime(ntptime.Minute)) + String("分")))))))))))))))))));
display.setCursor(0, 32);
display.print((String("已签到") + String((String((String(mind_n_num).toInt())) + String("人,分别为:")))));
delay(2000);
mind_n_i = 0;
mind_s_qdmd = "";
while (!(mind_n_i==mind_n_num)) {
mind_n_i += 1;
mind_s_qdmd = (String((String(mind_l_QianDaoMingDan[mind_n_i-1]) + String("、"))) + String(mind_s_qdmd));
yield();
}
display.fillScreen(0);
display.setCursor(0, 0);
display.print(mind_s_qdmd);
}
void pin15TouchCallback() {
ntptime.setNtpTime(ntptime.UTCEast8_t, "ntp.ntsc.ac.cn");
display.fillScreen(0);
display.setCursor(0, 22);
display.print("未签到人数正在统计……");
DF_TongJiZhong();
delay(5000);
mind_n_numw = (mind_l_QuanBuKaoShengMingDan.size()-mind_l_QianDaoMingDan.size());
display.fillScreen(0);
display.setCursor(0, 15);
display.print((String(ntptime.localTime(ntptime.Year)) + String((String("年") + String((String(ntptime.localTime(ntptime.Month)) + String((String("月") + String((String(ntptime.localTime(ntptime.Date)) + String((String("日") + String((String(ntptime.localTime(ntptime.Hour)) + String((String("时") + String((String(ntptime.localTime(ntptime.Minute)) + String("分,")))))))))))))))))));
display.setCursor(15, 32);
display.print((String("未签到") + String((String((String(mind_n_numw).toInt())) + String("人")))));
}
void onButtonAPressed() {
display.fillScreen(0);
display.setCursor(10, 22);
display.print("你好,请对准摄像头");
DF_DengDaiQianDao();
buzz.play(DADADADUM, Once);
huskylens.request();
delay(2000);
if (huskylens.isAppearDirect(HUSKYLENSResultBlock)) {
if (huskylens.isLearned(huskylens.readBlockCenterParameterDirect().ID)) {
mind_n_ksxh = huskylens.readBlockCenterParameterDirect().ID;
if (mind_l_QianDaoMingDan.contains(mind_l_QuanBuKaoShengMingDan[mind_n_ksxh-1])) {
rgb.write(-1, 0x000000);
display.fillScreen(0);
display.setCursor(5, 15);
display.print((String(mind_l_QuanBuKaoShengMingDan[mind_n_ksxh-1]) + String(",你已签到成功")));
display.setCursor(30, 32);
display.print("无需再次签到。");
}
else {
buzz.play(ENTERTAINER, Once);
display.fillScreen(0);
display.setCursor(20, 15);
display.print((String(mind_l_QuanBuKaoShengMingDan[mind_n_ksxh-1]) + String("签到成功")));
display.setCursor(36, 32);
display.print("祝你好运!");
DF_ChengGongLED();
mind_l_WeiQianDaoMingDan.remove(mind_n_ksxh-1);
delay(1000);
mind_l_QianDaoMingDan.push_back(mind_l_QuanBuKaoShengMingDan[mind_n_ksxh-1]);
mind_n_num += 1;
myIot.publish(topic_0, (String((String(mind_l_QuanBuKaoShengMingDan[mind_n_ksxh-1]) + String("已签到,"))) + String((String("目前签到人数为") + String((String((String(mind_n_num).toInt())) + String("人")))))));
}
}
else {
buzz.play(JUMP_DOWN, Once);
DF_WuFaShiBie();
DF_WuFaShiBieLED();
}
}
}
附件
gray66662020.04.09
好玩的项目。。。。。