孩子独自在家上网课不放心?一台闲置的手机就能帮你忙!

基于Aidlux平台和七牛云、喵提醒工具实现的网课专注度提醒小助手

本文正在参加『In AidLux,To AIoT』AI应用案例征集活动

0.前言

  • 工作繁忙没有时间照顾放假的小朋友?
  • 孩子上网课时总是东张西望,注意力不集中?
  • 每天都在跟小朋友斗智斗勇害怕他们沉迷手机?

只要家里有一台闲置的手机,就能不在家也能监管孩子的学习状态,在专注度差时自动发送提醒至家长手机,再也不需要在家里安装监控,还要费心费力地实时查看了,让aidlux平台的AI能力来帮助你!

完整的产品效果视频如下,当出现学习状态不够专注时,家长手机会自动收到一条提醒,并能查看孩子不专注的学习状态:

1.Aidlux介绍

  • Aidlux通过软件平台以非虚拟机的形式提供给Android系统同时运行Linux的能力,提供丰富且完善的AI工具链支持,能够帮助开发者和企业轻松落地AI应用。

Aidlux平台提供的能力,很好地解决了很多开发者,心有余(想法、方案)而力(算力、硬件)不足的困境,在ARM架构智能终端(Android系统手机、平板等)上能够同时运行Linux,提供了一系列AidLite API,动态调度CPU、GPU、NPU计算单元,充分释放AI算力,让我们在ARM架构上开发自己的AI应用提供了极大的便利,方便AI项目更快落地,是一个伟大的出现。

2.网课专注度提醒小助手方案介绍

首先介绍一下本文所提供的网课专注度提醒小助手使用到的全部硬件及软件名称和介绍,硬件为一台带有摄像头的Android手机即可,采用七牛云平台存储学习状态异常的图片,在家长手机上通过在喵提醒公众号上创建自己的实例来达到孩子专注度不够时提醒家长的目的,全程基于Aidlux平台使用远程桌面连接手机进行开发。

本文所采用的后端存储和微信公众号发送提醒的方式是采用江大白老师提供的方案万字长文手把手教你Yolov5制作家庭安防告警系统,大家有兴趣可以关注一下江大白老师,公众号里都是满满的干货。

序号 名称 介绍
1 华为荣耀10 青春版 系统:Andriod 9 + CPU:海思麒麟710 + GPU:Mail-G51
2 Aidlux Android手机Aidlux版本1.2.1
3 七牛云平台 使用对象存储Kodo功能存储后端数据
4 喵提醒平台 使用公众号提醒功能将后端图片数据外链发送到家长手机

本文采用人脸检测和人脸关键点定位的方案,通过对每一帧图像中是否有人脸->判断人脸关键点位置是否异常(低头、趴下、东张西望)->判断异常状态持续若干帧来判定孩子的学习状态是否异常,工作流程如下图所示:

关于学习状态的情况,我将其大致分为四类:

  1. 正常情况(人脸关键点位置正常——学习状态正常,专注度尚可),如下图所示:

  2. 异常情况一(无人脸——学习状态异常,存在逃课嫌疑)

  3. 异常情况二(有人脸,但人脸关键点位置异常——存在东张西望,注意力不集中嫌疑),如下图所示:

  4. 异常情况三(有人脸,但人脸关键点位置异常——存在精神不集中,打瞌睡嫌疑),如下图所示:

通过观察可以得知当学习状态异常时几个关键点的位置特点,通过代码中条件判断可以实现对正在上网课的人脸专注度进行界定。

3.网课专注度提醒小助手方案实现

3.1 七牛云注册及使用

首先我们需要在七牛云官网上进行注册,点击左上角折叠栏,选中“对象存储Kodo”。

点击空间管理,新建空间输入名称,并将其设置为公开。

此时我们点击进入我们刚刚创建的空间,点击文件管理,我们先上传一张本地的文件测试一下效果。

上传好后,我们点击图片详情,找到图片链接,将它复制到电脑或者手机浏览器上打开即可。

```
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661150942924274125.png" alt="" /></p>
<p>接下来我们测试使用python代码在Aidlux的环境中将本地图片上传至七牛云空间,首先需要在手机的应用商店中下载Aidlux应用软件,大小约2.1个G,进入后还需要下载一些相关依赖(建议在wifi环境下进行~)。</p>
<p>进入手机Aidlux软件之后,我们可以点击下方的“Cloud_ip”图标,就可以在电脑上远程反问Aidlux桌面,方便了我们的开发,当然没有电脑的情况下也可以就在手机上进行开发,只不过稍微麻烦一些,其他方面都是一样的。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661151668348811732.png" alt="" /></p>
<p>我是远程连接电脑进行开发的,连接上之后点击下方的“终端”按钮,输入 <code>pip3 install qiniu  -i https://pypi.tuna.tsinghua.edu.cn/simple</code>,先下载七牛云所需要的依赖包。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661151818027104114.png" alt="" /></p>
<p>下载成功后,点击下方“AidCode”图标,点击左上角“+”号,选择“New”,新建一个名为qiniu_test的python文件。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661152004839276303.png" alt="" /></p>
<p>将下面这段代码复制进去:</p>
<pre><code class="language-python">from qiniu import Auth, put_file
from qiniu import BucketManager
from qiniu import CdnManager

# 配置七牛云信息
access_key = &quot;HoXmloGu85nrmHm089U05rAg1MTQcBl-5Yn1tpSx&quot;
secret_key = &quot;l1q_-M24NCZHDwwZ16jKTtXDlCf6yvpGwhnmVHJh&quot;
bucket_name = &quot;aidlux-xzw&quot;
bucket_url = &quot;rgpgm392c.bkt.clouddn.com&quot;
q = Auth(access_key, secret_key)
bucket = BucketManager(q)

cdn_manager = CdnManager(q)

# 将本地图片上传到七牛云中
def upload_img(bucket_name, file_name, file_path):
    # generate token
    token = q.upload_token(bucket_name, file_name, 3600)
    put_file(token, file_name, file_path)

# 获得七牛云服务器上file_name的图片外链
def get_img_url(bucket_url, file_name):
    img_url = 'http://%s/%s' % (bucket_url, file_name)
    return img_url

# 需要上传到七牛云的图片路径
image_up_path = &quot;zidane.jpg&quot;
# 上传到七牛云后,保存成的图片名称
image_qiniu_name = &quot;zidane.jpg&quot;
# 将图片上传到七牛云,并保存成image_qiniu_name的名称
upload_img(bucket_name, image_qiniu_name, image_up_path)
# 取出image_qiniu_name一样名称图片的url
url_receive = get_img_url(bucket_url, image_qiniu_name)
print(url_receive)
# 需要刷新的文件链接,由于不同时间段上传的图片有缓存,因此需要CDN清除缓存
urls = [url_receive]
# URL刷新缓存链接,一天有500次的刷新缓存机会
refresh_url_result = cdn_manager.refresh_urls(urls)
</code></pre>
<p>需要注意,此处的 <code>access_key</code>、<code>secret_key</code>、<code>bucket_name</code>(空间名称)和 <code>bucket_url</code>(外链域名)都需要根据自己的七牛云空间上的信息进行相应的修改。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661152425763863279.png" alt="" /></p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661152461542504494.png" alt="" /></p>
<p>当然 <code>image_path_up</code>也需要修改成自己提前在Aidlux文件管理中本地上传的一张图片的路径,这样才不会报错,修改完成后点击左上角“Run Now”,运行完毕后会在下方output区域打印一个链接,我们复制用浏览器打开,如果能顺利看到我们需要上传的图片,那么就大功告成了!</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661153000306637023.png" alt="" /></p>
<p>接下来我们在qiniu_test.py中定义一个函数upload_qiniuyun,方便我们在需要上传图片的时候调用。</p>
<pre><code class="language-python">def upload_qiniuyun(image_name, image_path):
    # 将图片上传到七牛云,并保存成image_qiniu_name的名称
    upload_img(bucket_name, image_name, image_path)
    # 取出image_qiniu_name一样名称图片的url
    url_receive = get_img_url(bucket_url, image_name)
    # 需要刷新的文件链接,由于不同时间段上传的图片有缓存,因此需要CDN清除缓存
    urls = [url_receive]
    # URL刷新缓存链接,一天有500次的刷新缓存机会
    refresh_url_result = cdn_manager.refresh_urls(urls)
    return url_r
</code></pre>
<h3>3.2 喵提醒注册及使用</h3>
<p>有了七牛云帮助我们存储孩子上网课专注度不够的图片后,我们还需要一个工具将图片发送到家长的手机上,让家长能够及时监督到孩子的状态,这个功能我们可以使用喵提醒公众号来帮助我们实现,微信公众号搜索喵提醒后,关注,注册进入公众号主界面点击下方的提醒 -&gt; 新建提醒即可,这里的“喵码”需要我们留存,作为每一个喵提醒的标识符,后面我们会用到。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661156252622292915.jpg" alt="" /></p>
<p>新建好提醒后我们还是在Aidlux应用中打开AidCode,新建一个名为miaotixing_test的python文件来测试我们的提醒发送功能,将如下代码复制进去,其中 <code>id</code>需要替换为自己新建提醒生成的喵码,相应的 <code>text</code>后面的图片路径也修改成上面七牛云提供的图片外链即可。</p>
<pre><code class="language-python">import time
import requests

# 填写对应喵码
# id = 'tW5iDu1'
id = 'tSe50aT'
# 填写喵提醒中,发送的消息,这里放上面前面提到的图片外链
text = &quot;告警图片:&quot; + &quot;  http://rgpgm392c.bkt.clouddn.com/zidane.jpg&quot;
# 时间戳
ts = str(time.time())
# 返回内容格式
type = 'json'
request_url = &quot;http://miaotixing.com/trigger?&quot;

headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrom/87.0.4280.67'
}

result = requests.post(request_url + &quot;id=&quot; + id + &quot;&amp;text=&quot; + text + &quot;&amp;ts=&quot; + ts + &quot;&amp;type&quot; + type, headers=headers)
print(result)
</code></pre>
<p>运行一下,当出现&lt;Response [200]&gt;,并且在手机上收到提醒后,则提醒功能已经实现了。</p>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661158402424823929.png" alt="" /><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661158576351200476.jpg" alt="" /></p>
<p>同样我们也在python文件中写一个函数 <code>miaotixing_post</code>,方便在需要发送提醒的时候调用。</p>
<pre><code class="language-python">def miaotixing_post(image_url):
    id = 'tSe50aT'
    text_iamge_url = &quot;告警图片:&quot; + image_url
    print(text_iamge_url)
    ts = str(time.time())
    type = 'json'
    request_url = &quot;http://miaotixing.com/trigger?&quot;
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrom/87.0.4280.67'
    }
    result = requests.post(request_url + &quot;id=&quot; + id + &quot;&amp;text=&quot; + text_iamge_url + &quot;&amp;ts=&quot; + ts + &quot;&amp;type&quot; + type, headers=headers)
    print(result)
</code></pre>
<h3>3.3 使用人脸关键点检测器逻辑判定实现专注度监测</h3>
<h4>3.3.1 使用blazeface作为人脸关键点检测器</h4>
<p>看了江大白老师的那篇文章,原本我的想法是使用yolov5-face作本方案的人脸检测器,但是我在Aidlux系统的examples例子中心里看到了使用blazeface的6个人脸关键点定位和多张人脸同时检测的超轻量检测器,同时考虑到有些朋友可能不具备本机的python和深度学习环境,所以决定使用Aidlux提供的模型来实现本方案。</p>
<p>首先我们在Aidlux系统中的Home目录下,新建一个文件夹名为study_status_detect,同时将/home/examples/face/models目录下的几个模型文件和目录一起复制过来,再将上一级目录的blazeface.py文件同样拷贝一份在我们目录下,还需要将我们之前创建的qiniu_test.py和miaotixing_test.py拷贝过来。</p>
<p>接下来,新建一个study_judge.py作为我们的主要运行的python文件,使用blazeface作为人脸检测器,检测器推理、回归代码都可以在Aidlux中的实例代码可以找到。</p>
<p>主体代码篇幅过长这里不予展示,文章末尾会放github链接,需要的话可以自行clone一下。</p>
<p>根据上文,我们主要需要的是左眼、右眼、左耳、右耳这四个关键的点位置,我们找到检测代码的 <code>plot_detections</code>函数,找到这几个点的序号并保存进相应变量中(注:每个关键点存储的内容分别是该点的x坐标和y坐标):</p>
<pre><code class="language-python">for i in range(len(detections)):
        left_eye =(int(detections[i, 4] * img.shape[1]), int(detections[i, 5] * img.shape[0])) 
	right_eye =(int(detections[i, 6] * img.shape[1]), int(detections[i, 7] * img.shape[0]))   
	left_ear =(int(detections[i, 12] * img.shape[1]), int(detections[i, 13] * img.shape[0])) 
	right_ear =(int(detections[i, 14] * img.shape[1]), int(detections[i, 15] * img.shape[0]))
</code></pre>
<h4>3.3.2 使用逻辑策略判断学习状态</h4>
<p>有了四个关键点的位置后,我们可以编写相应的逻辑来界定当前帧人脸的学习状态是否正常,定义一个函数 <code>judge_study_status</code>:</p>
<ol>
<li>若任何一个关键点没有数据,这里用一个 <code>left_eye</code>进行判定即可,即画面中没有人脸的情况,则判断此时属于异常学习状态之逃课。</li>
<li>若双耳连线的中点y值小于双眼连线的中点y值,则判断此时属于异常学习状态之低头,存在打瞌睡嫌疑。</li>
<li>若双耳连线的中点x值不在左眼x值和右眼x值的区间范围内,则判断此时属于异常学习状态之东张西望,存在开小差嫌疑。</li>
</ol>
<pre><code class="language-python">def judge_study_status(left_eye, right_eye, left_ear, right_ear):
    if left_eye == None:
        print(&quot;abnormal: no face&quot;)
        return False
    elif (left_ear[1] + right_ear[1])/2 &lt; (left_eye[1] + right_eye[1])/2:
        print(&quot;abnormal: bow head&quot;)
        return False
    elif not left_eye[0] &lt; (left_ear[0] + right_ear[0])/2 &lt; right_eye[0]:
        print(&quot;abnormal: look around&quot;)
        return False
    return True
</code></pre>
<p>当然我们不可能出现学习状态异常的一帧就立马发送提醒,这样孩子得崩溃,家长也得烦死(手动狗头),所以我们需要几个标志位和帧数 <code>frame_id</code>来帮助我们:</p>
<p><code>frame_id</code>初始置为0,每检测一帧就+1,<code>abnormal_start_frameid</code>用来记录每次不专注行为开始出现的 <code>frame_id</code>,<code>last_fram_study_status</code>用来记录上一帧学习状态,比对是否开始出现不专注行为,若上一帧学习状态正常,这一帧出现不专注行为时,则用 <code>abnormal_start</code>来标记异常学习状态开始。</p>
<pre><code class="language-python">frame_id = 0  
abnormal_start_frameid = 0
last_fram_study_status = True
abnormal_start = False
abnormal_count = 0
</code></pre>
<p>这里因为我拍摄的视频比较短,所以不专注行为持续30帧(约1s)便判定学习状态异常,在实际使用的时候可以根据自己的硬件能力和实际情况来设置,如果没有跳帧的话可以设置成300帧(约10s),如果跳帧的话进行相应调整即可。</p>
<pre><code class="language-python">    detections = blazeface(raw_boxes, classificators, anchors)
    out, now_study_status=plot_detections(frame, detections[0])
    if not now_study_status and last_fram_study_status:
        abnormal_start = True
        abnormal_start_frameid = frame_id
        save_abnormal_image = True
    if not now_study_status and abnormal_start  and frame_id - abnormal_start_frameid &gt; 30:
        study_status = False
    if now_study_status and not last_fram_study_status:
        abnormal_start_frameid = frame_id
        abnormal_start = False
        study_status = True
    last_fram_study_status = now_study_status
</code></pre>
<h4>3.3.3 保存异常图片并上传至七牛云发送给家长</h4>
<p>整段的逻辑不难读懂,有两个新增的变量,一个是 <code>save_abnormal_image</code>,用来控制异常图片的保存并上传七牛云和发送喵提醒,但没必要学习状态异常之后每一帧都发送,一次即可,另 <code>abnormal_count</code>可以记录不专注的次数。这里的 <code>upload_qiniuyun</code>和 <code>miaotixing_post</code>就是我们之前在做测试时定义的函数,传入本地文件的路径和要保存的图片名字,再把七牛云返回的外链url传给喵提醒的工具即可。</p>
<pre><code class="language-python">   if study_status:
        cv2.putText(out, &quot;study status normal &quot;, (0, 30),cv2.FONT_ITALIC, 1, (0, 255, 129), 2)
    else:
        cv2.putText(out,  &quot;study status abnormal&quot;, (0, 30),cv2.FONT_ITALIC, 1, (255, 0, 0), 2)
        if save_abnormal_image:
            save_abnormal_image = False
            abnormal_count += 1
            img_save_path = 'study_status_abnormal/study_status_abnormal_{}.jpeg'.format(abnormal_count)
            cv2.imwrite(img_save_path, out)
            img_name = img_save_path.split('\\')[-1]
            url_receive = upload_qiniuyun(img_name, img_save_path)
            miaotixing_result = miaotixing_post(url_receive)
            print(miaotixing_post)
</code></pre>
<h2>4. 专注度提醒小助手最终效果</h2>
<h3>4.1 测试视频效果</h3>
<iframe src="https://player.bilibili.com/player.html?aid=259760420&amp;bvid=BV1wa411o7ak&amp;cid=812211461&amp;page=1" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"></iframe>
<h3>4.2 七牛云平台上传的图片</h3>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661254451269183083.jpg" alt="" /></p>
<h3>4.3 手机上收到的提醒</h3>
<p><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661254498179115250.jpg" alt="" /><img src="https://aidlux.oss-cn-beijing.aliyuncs.com/imgs/1661254516946354195.png" alt="" /></p>
<h2>5. 优化方向和改进</h2>
<p>由于时间的关系本实现方案写的还是比较仓促,逻辑判定上也比较简单,在实际测试中会发现几个问题:</p>
<h3>5.1 保存图片时容易卡顿</h3>
<p>所有推理、读写操作都放在了主线程,导致保存图片的时候容易卡顿。</p>
<p>优化方向:在python代码里使用多线程,另起一个线程进行读写操作。</p>
<h3>5.2 运行时间长手机发热严重</h3>
<p>Aidlux调度CPU算力的功能十分优秀,像这样比较老式的CPU帧率也能达到80~120左右,可能是由于调用摄像头时间过长了,发热比较严重,暂时没有什么降低功耗的方案,所以只能采取物理手段:风扇/空调降温,或者寻求官方的帮助了。</p>
<p>优化方向:暂无</p>
<h3>5.3 喵提醒连续发送提醒时容易漏发送</h3>
<p>在实际测试中,由于两次发送提醒的时间间隔较短(小于5s),会出现漏发送提醒的情况。</p>
<p>优化方向:可以将专注度不够的时间阈值调高,变为一分钟或者更高,亦或者是修改代码逻辑,改为每10分钟就自动发送一张提醒图片监管当前状态即可。</p>
<h3>5.4 微信缓存导致接收到的图片不对</h3>
<p>实际测试中也发现无论发送多少条提醒,打开的url链接一直是同一张图片,这是因为微信中有缓存,需要复制到浏览器再进行打开..这个也是有点麻烦的地方,不知道官方是否有想法也开发一个这样的公众号呢(此处手动@Aidlux官方),既然是手机上的智慧生态,不如一条龙服务做到底,哈哈哈哈哈哈……</p>
<h2>6 结语</h2>
<p>至此,一个实现网课专注度提醒小助手的实现方案就介绍完毕了,感谢Aidlux提供这样一个平台可以让AI应用落地如此简单,成为一个AI应用开发者的门槛也降低了很多,真正实现了人人都能使用AI能力为自己的生活提供便利,以后我也会继续使用Aidlux平台,继续开发出更多更好更实用的AI小应用给大家分享(如果能有一个带7T算力的盒子就更好了,嘻嘻)。</p>
<p>全部代码github链接:https://github.com/PaulX1029/study_status</p>
<p>我坚信人生不是一条弯弯曲曲的线,而是一个个难忘的点,我想在人生的白纸上,多留下一些浓墨重彩的点。</p>
<p>欢迎大家在帖子下方留言交流,让我们一起在学习的道路上努力~</p>

挖沙,太牛了!马上动起来!

这个有意思,牛啊!

大神好多,太厉害了

孩子们都哭了哈哈哈哈

孩子:我太难了 哈哈哈

孩子:我这就去学编程,搞个反监测?‍♂️

孩子:挫折不能打倒我 反使我更加强大

哇哦,那宠物是不是也可以

家长内卷的新方式。?

家长内卷的新方式。?

孩子哭了