React脚手架V1.0

背景

最近开始捯饬React,想着学会了React就能把React Native给学习了,然后就能写App。为了能够在React Native上少踩坑,我搭建这个脚手架之后,准备开发一个博文发布系统,作为DEMO练练手。

依赖构成

  1. React核心
  2. React-router-dom 路由
  3. Redux 状态管理
  4. ESlint 代码格式管理
  5. Vite 打包工具
  6. Axios 网络请求库
  7. Antd UI库

搭建流程

1. 初始化React

1.1 模板初始化

我们可以直接使用Vite自带的模板,初始化React,在本教程中我使用的是template指令来初始化项目。

运行以下指令初始化项目

 # npm 6.0
 npm init @vitejs/app gublog(项目名称) --template react(模板名称)
 ​
 # npm 7.0+ (需要额外的双横线)
 npm init @vitejs/app gublog(项目名称) --(额外的双横线) --template react(模板名称)

运行指令后,npm将创建一个以项目名称命名的文件夹📁,来初始化项目。

初始化完成后的文件树结构为:

 root
 └── gublog(项目名称)
    ├── dist
    ├── node_modules
    ├── src
    ├── index.html
    ├── package-lock.json
    ├── package.json
    └── vite.config.js

1.2 启动环境

  1. cd 项目文件夹
  2. npm install #下载依赖
  3. npm run dev #启动开发环境
环境启动成功

出现上图的网页时,我们就已经搭建出Vite + React的开发环境

2. 安装React-router-dom

为了能够实现无刷新切换页面,此处我的脚手架也会引入官方提供的Router来做前端路由管理。

2.1 安装依赖

运行指令安装路由组件

 npm install react-router-dom --save-dev

2.2 注意⚠️

React-Router-Dom就是React Router V4的浏览器版本,原来文档的Router要被替换成BrowserRouter才能使用。为了不使用方面,我们可以使用as关键字来修改别名。

 import 'BrowserRouter' as 'Router' from 'react-router-dom'

这里我真的很想吐槽,搞一个React-Router就好了嘛🤷‍♂️,干嘛还搞一个React-Router-Dom。这东西本质上就是套娃再封装📦。而且最近的V4版本还舍弃了旧的Router标签,改成了BrowserRouter。真的是NT。

解决方法来源:

3. 安装Redux

安装Redux主要是为了使得组件的耦合降低,使得更容易的管理状态,因此被打包到脚手架当中。

3.1 安装依赖

 npm install redux --save-dev

4. 安装ESlint

4.1 安装依赖

 npm install eslint --save-dev

5. 安装Axios网络请求库

5.1 安装依赖

 npm install axios --save-dev

6. 安装AntdUI库

AntdUI是阿里针对React设计的一个UI库,开箱即用,有丰富的文档。(而且还能改颜色)

6.1 安装依赖

 npm install redux --save-dev

6.2 引入环境

  1. main.css中添加import 'antd/dist/antd.css'导入CSS库
  2. Main.jsx的代码头部添加import {组件名称} from antd导入组件

结尾

这篇文章就此告一段落。Axios和ESlint的使用我还在摸索中,后面还会继续更新,敬请期待。目前在使用这个脚手架重写GuBlog日志程序当中,后面时机成熟后也会同新版本的脚手架文章一同推出。

npm 安装、删除依赖命令

npm安装依赖

  • npm install xxx 利用 npm 安装xxx依赖到当前命令行所在目录
  • npm install xxx -g 利用npm安装全局依赖xxx
  • npm install xxx –save 安装并写入package.json的”dependencies”中
  • npm install xxx –save-dev 安装并写入package.json的”devDependencies”中

npm删除依赖

  • npm uninstall xxx 删除xxx依赖
  • npm uninstall xxx -g 删除全局依赖xxx

PPG式心率测量小程序的技术分享

故事

背景

去年6月份的时候,参加了微信小程序官方举办的《高校微信小程序开发大赛》,做出了《活力健身房》这个小程序。按照初版设计,除了可以检测用户的跑步数据外,还可以测量用户的静止心率。但由于个人除了要准备比赛,还要准备痛苦的概率论补考,所以导致日程太过于紧凑,因此在该情况下,我就只完成了第一个目标而忽略了第二个心率测量的目标没有实现。

改进

在暑假期间,处于追求完美的想法,我花了一部分的时间继续学习并完成了心率检测算法的V1.0版本。而后再在这周,时隔一年的时间,重写了检测算法,推出了V1.1的版本。(至于为什么算是1.1版,在文中会说明的😂)。

技术分享

今天我写这篇文章的主要目的是跟大家分享以下的三点内容:

  1. PPG式心率测量的原理
  2. PPG式心率测量的实现
  3. 应用到小程序端的难点

1.技术原理

光体积变化描记图法 (Photoplethysmography,简称PPG) 是借光电手段在活体组织中检测血液容积变化的一种无创检测方法。当一定波长的光束照射到指端皮肤表面,每次心跳时,血管的收缩和扩张都会影响光的透射 (例如在透射PPG中,通过指尖的光线) 或是光的反射 (例如在反射PPG中,来自手腕表面附近的光线)。当光线透过皮肤组织然后再反射到光敏传感器时,光照会有一定的衰减。像肌肉、骨骼、静脉和其他连接组织对光的吸收是基本不变的 (前提是测量部位没有大幅度的运动),但是动脉会不同,由于动脉里有血液的脉动,那么对光的吸收自然也会有所变化。[1]

PPG检测的核心是通过心脏跳动影响血管中血液光线的吸收率变化,进而影响血液对光的反射率,估算受测者的心率数据。用人话说,心脏的跳动,会影响血液反射光的强度。反映到图表上,就如下图所示,心脏的舒张和收缩,会影响光强变化,形成下图的波动曲线。而心率的估算,则是通过计算60s内,有多少个波峰或者波谷。比如60s内,图表上产生了60个个波峰,则意味着1s中,心脏收缩和扩张了一次,即跳动了一次,进而可以得出60BPM的心率数据。

PPG传感器工作原理

2.技术实现

根据技术原理可以知道,PPG检测中我们需要做的事情是,计算一段时间内出现了多少个波峰,即可估算出受测者的心率。由此我们需要考虑实现以下的几个功能:

  1. 获取视频流中的某一帧
  2. 检测传感器是否被覆盖
  3. 获取当前帧的光强数据
  4. 计算波峰个数
  5. 计算BPM

1.获取视频中的某一帧

在当今社会中,人人都会有一台的智能手机。而手机上最好的颜色传感器就是摄像头了,因此在小程序端的实现中,对于数据的来源主要是摄像头。

为了实现方便,这次我依旧是使用小程序作为我的开发平台。之所以使用小程序的核心原因是官方提供了摄像头的API,使得我可以通过简单的$API$就可以获取到来自用户摄像头的视频流数据,并且不用考虑兼容性的问题。

在小程序中,我是用的是wx.createCameraContext()API来获取到视频流,同时借助onCameraFrame()来直接获取到每一帧的视频信息,极大的降低了开发的难度。通过前述的API,我们可以直接获取到当前帧Uint8数组,也就是每个像素的RGBA值。

2.检测传感器是否被覆盖

为了避免外部光照影响血管对光线的反射,因此需要受测者的手指完全覆盖摄像头。为了检测摄像头是否覆盖,我们可以通过经验主义设定一个阈值,当每个像素的实际光强小于阈值,则代表传感器完全被覆盖,此时就可以开始测试。

3.获取当前帧的光强数据

通过API,我们可以获得视频流中特定的一帧的Uint8数据。之所以使用Uint8是因为在该RGBA中,每一个通道的颜色只有256种,而我们仅仅是需要获取该帧中的光强。因此选用Uint8可以大幅度减少运算量,提高运行效率。

通过经验主义的测量以及结合论文[2] [3]的理论支持,我们可知血液在红光和绿光的照射下的吸收率是最大的,也就意味着强度值是最大的。因此可以更好的检测到强度变化,所以在后续的开发当中,我们都将使用单个像素中的红绿通道的强度值,来作为数据的来源。由于只使用了其中两个通道的强度值,我们的运算量就可以几何级数减少。

从原来的 2^{32} 个数据转变为了 2^{16} 个数据

获取光强的方法是:

该帧的光强值 = \frac{单个通道的强度值}{像素的个数}

4.计算波峰个数

在1.0版本中我的实现方法是通过经验值测算出一条固定的基线,来判断历史采集的光强值,有多少个跃出基线的数据,就计作多少个波峰。

V1.0 固定基线法

但这种设计是有问题的,比如最右侧的波峰,因为各种外部原因强度没有达到基线,导致丢失。当通过人眼的辨识,这个波峰不属于噪声,应该是要被记录的。

另外通过测试我们可以很容易的发现下图的假波峰和假波谷的噪声信号,这种变化幅度过大的数据也应该是被丢弃的。

噪声曲线

因此在1.1版本中,基线的计算方法做了改进。通过动态基线可以适应复杂环境光线的变化,提高测量的效率和准确性。

V1.1 动态基线法

通过动态基线,判断有多少多少次实际的跃出,进而换算出有多少个波峰。

5.计算BPM

仅仅记录波峰个数是远远不够的,我们还要计算一次跃出所消耗的时间(从波谷到跃出基线到波峰所消耗的时间)。因为受测者的光线环境如果不稳定,含有频繁的光线变化,则可能导致光强变化幅度过大,造成数据的计算误差。因此我们还需要将跃出时间作为计算的一个因素,计算平均的跃出时间。最后计算出每分钟的心率次数:

BPM = \frac{测量最大时间}{平均跃出时间}

小程序端的技术难点

到目前为止,小程序端最大的难点不在于测量算法的开发上。反而是在优雅的展示上画了大量的时间。

  1. FrameData大小
  2. Canvas绘图效率低

1.FrameData大小。通过Camera组件,我们可以直接获取到手机的视频流。由于我们这个算法中仅仅需要计算帧的光强,所以仅仅需要最低质量的FrameData即可。即降低了资源的消耗也提升了算法运行的效率。通过frame-data属性,修改为small即可启用最低质量的FrameData。

2.Canvas绘图效率低。在去年小程序退出了Canvas 2D的绘图API,可以实现同层渲染。为了更高的渲染效率,我自然就是选择并使用了最新的API进行曲线的绘制。在电脑模拟器上的表现确实印证了效率更好的这一说法。但诡异的是在Android端上,Canvas2D的运行效率非常低,导致经常性假死,不知道怎么修复。因此只能暂时被搁置,待到日后有能力后再做修复。

收获

这次的开发通过学习更多前人的研究结论来帮助我将算法优化出来,收获满满。感觉到非常的振奋人心。期待后面能继续搞点好玩的DEMO。

未来的方向

最近看到Tensorflow的BlazeFace。可以用很小的体积的模型来识别人脸,感觉可以借此,结合PPG算法,实现rPPG式的检测算法,日后有时间可以继续搞一下,感觉会非常的好玩。同时Canvas的问题也需要被修复,或许能够通过WebGL来修复?但是我还不肯定,需要后续的实验才能证明,待到后面再修吧。

结尾

由于本人不是电子工程专业,所以上文中可能会涉及到部分不规范的说明和解释。如果您能够在评论中帮助我指出来并帮助我改正,我将十分感激您,谢谢。

参考

[1] ECG/PPG量测解决方案

[2] 不同波长近红外光下手掌静脉图像质量分析

[3] 血液成分对光吸收规律的实验研究

日常碎碎念 2021.6.20

上周总结

  1. 疫苗接种
  2. 期末考试
  3. 重写PPG式心率测量算法
  4. 学习React

1.疫苗接种。学校终于通知我们打疫苗了,下个月要去深圳实习,打了疫苗才能安心一点呀。打疫苗过程中真的是热死🥵人了,被热蒸气熏蒸,感觉人都快晕掉了,好在以后不用再接种了。(希望)

2.期末考试。上周四的时候,终于将最重要也是最难的两科考试考完了,普天同庆。虽然NT学校安排了一门开卷考试在7月2日。但是可以放松下来,随心所欲的学习也是不错的感觉。希望最后一门考试也能取得好成绩吧。

3.重写PPG式心率测量算法。之前在《活力健身房》中做了一个心率测量的功能。但是随着我的电脑更换,我那部分的代码被迫丢失了。因此趁着最近有空余时间了,整理了一下之前的思路,重写了整个心率测量的算法。并且由于最近也在学习React+React Native。所以希望将这套算法重写验证后,移植到React Native上,做出一个App上架到App Store中国呢赚一点零花钱。(到时候我也会单独写一篇文章来介绍算法的原理以及具体的实现方式)

3.学习React。下个月就要开始鹅厂的实习生活了,问了leader有什么内容需要我提前学习的。React就是入门的门槛了,后面还要转成React Native。看来跨端开发真的是未来5-6年的发展方向啊。UniAPP,Vue多端编译,React Native。另外React的JSX语法其实还挺有趣的,感觉小程序与React的实现非常相似,后面也打算出一些关于小程序底层的分析文章,到时候可以相互比较一下思路。

本周计划

  1. 学习React
  2. 完成《创新创业课程实训》
  3. 完成《PPG式心率测量小程序的技术分析》撰写
  4. 摸鱼

结尾

这一周的主旋律还是摸🐟为主,毕竟没有很难得考试了。可以花点时间摸摸鱼休息一下,如果能出门去逛一下就更好了

日常碎碎念 2021.6.14

上周总结

  1. 端午节假期
  2. 学校封校
  3. 软件测试与质量保证考试
  4. 看书《自制编程语言》

1. 端午节假期。学校为了提前放假,把后续的所有课程都提到6月的周末进行授课。因此导致端午假期其实都是在上课。(不幸中的万幸,主要的课程在5月底就已经结束,现在只剩下一个学校的企业实训课程,压力还算不是很大。)另外学校可能🤔是为了安慰大家,端午节居然开始派发粽子了。读了3年书,这是第一次。2020年和2021年真的是奇妙,什么新鲜事都见到了。

2.学校封校。由于学校需要配合当地的疫情防控要求,因此对校园实施了封校处理。但u1s1,我们学校就是在郊区,偏僻的不得了。平时也没啥人会专门流动到我们这里来,实在是想不通为啥要实施封校处理。封校处理也直接导致校外的商业气息消失的一干二净,非常的安静,静悄悄的,都没有烟火气了💔。另外不能出门喝咖啡☕️和剪头发💇‍♂️也是让人感到好不方便啊。(上一次为了去拍照,找了一个100块的理发师,现在看来100还是物有所值的。秒杀我平时去的60块的理发馆,起码头发长了,那个形态还是整齐的,下次还会回去剪。)

3.软件测试与质量保证考试。3月开放回校,4月雅思考试,5月面试大厂。时间飞逝,转眼间就到了6月,迎来了第一场考试。考试的手感还行,希望能够再接再厉,后续能够取得更好的成绩吧。

3.《自制编程语言》。最近618购物节,没啥好买的。在当当网上偶然瞥见了这本书,感觉非常的有趣,因此上网下载了一本PDF版的电子书来阅读。后悔当初学习编译原理的时候没早点看到这本书。作者通过生动的图像,以及平易近人的话语,来向读者介绍了程序语言以及编译器的工作原理,并在后面手把手教授读者自己开发一个编译型语言出来。个人觉得真的是非常有趣的一本书。目前刚刚把编译器的梗概介绍读完,正在跟着作者实用yacc(语法分析器)和lex(词法分析器)来开发一个编译器和编译语言。通过实践,能够更加明确的认识到上个学期学习的自动机,文法,归约,移进等名词,在实践中的应用。非常过瘾和令人兴奋🥰。读完之后我会单独写一篇读后感,希望到时候能够有人来看。

本周计划

  1. 软件工程师资格培训-期末考试
  2. PHP Web高级应用开发-期末考试
  3. 完成企业实训任务
  4. 继续读书

结尾

今天是6月14日端午节,不知道看到这篇博文的你吃粽子了吗?另外也祝你端午安康😊!

日常碎碎念 2021.06.06

本周总结

  1. 阿里实习Offer
  2. 主要课程结束
  3. 小程序大赛&交接
  4. 工作室容器化工作流
  5. 核酸检测
  6. 软件设计师资格考试和六级考试

1. 阿里实习Offer。终于等到了来自阿里的实习Offer,对于我一个来自三本的学生而言,真的是非常的惊喜了。去到了广州的支付宝质量保证与技术风险部,主要做的是内部工具。想到有机会接触到底层技术的开发,想想就令人很激动啊🥳。(可惜现在广州有疫情的牵制,不然上下班30min的优势真的是好爽啊!)

2.主要课程结束。大三下的课程转眼间就要结束了,下周就要开始准备考试了,感觉时间过的真的好快啊。同时6月已经悄然来临,2021年就要过去一半了,感觉时间流逝最快的是4月找实习的日子,平和🙃,焦虑😖,喜悦😝的感觉至今都难以忘怀,相信这段经历会伴随我一辈子吧。不过还是要端正态度,不骄不躁,好好迎接接下来的考试,不要把之前的优势丢失了,加油😎。

3.小程序大赛&交接。去年的《软件项目管理课程》中,召集了几位dalao,一起开发了一个课室签到小程序。今年年初被老师怂恿着,拿着这个小程序去参加了比赛。不过计划始终是赶不上变化,年初的时候,雄心壮志的立下了许多先进的目标,4月就开始各奔东西找实习,5月接OC摸🐟,导致6月只能把最原始的1.0版本交上去。老师也可能是看到这个原因,感觉我们靠不住,就找大二的dalao来接手了,希望他们不会像我这么摸,能够把小程序成功落地,造福学校的师生吧。(感觉自己就是个反面教材🤣)

4.工作室容器化工作流。最近终于下定决心,通过众筹,购入了一年的云服务器。开始构建工作室的容器化工作流了。之前都是需要先push到github上,等待学校管理员,pull到服务器上面的。自由度非常非常低,而且还会有很多的局限性。因此我希望这次可以借助这个机会,构建一条全自动化的工作流:上传Github->构建docker image->推送到docker container->上线。并且借助网页面板,能够在线管理服务。期望这样子可以实现后端服务的无缝迁移和运行。不论是哪一届,都能继承这套内部工具来进行业务的测试开发。彻底摆脱学校的限制🚫。

5.核酸检测。广州最近出现了大量的新冠疫情感染者,因此被要求进行全市的核酸检测。市区部分在前3-4天已经完成2-3次的检测任务了。但是我们这些郊区一直没有消息,昨天临时接到通知,要通宵做核酸检测。因此凌晨3点被拉出去做了核酸检测,真的是辛苦了医护人员了👨‍⚕️👩‍⚕️,广州加油。另外5.6号的时候,我因为喝了浓鸳鸯而通宵;没想到一个月后的6.6号我因为核酸检测,再次通宵,历史惊人的相似,真的是难忘的大学经历了😄。

6.软件设计师资格考试和六级考试。由于广州的疫情原因,导致这两门考试在广州的考点不得不延期举行。(其实就是取消6月的考试了)对于我来说,其实我是高兴的,主要是因为我没做多少的复习,去考试也是去浪费金钱💰和时间⌚️。反倒是我的舍友们损失惨重,每天都看见他们在努力💪学习,刷题到深夜,希望他们能够在之后的考试中获🉐️出色的成绩吧。

下周计划

  1. 软件测试与质量保证 考试
  2. 复习下周考试内容

实施情况

计划使用周日、周一、周二的时间进行复习,准备周三的考试。期望能够通过这三天的努力取得一个出色的成绩吧。

PHP和软件工程师的课程期末考试在下下周,因此同样需要耗费一定的时间来准备,目前计划周三考完试再进行准备。

结尾

明天就是6.7号,一年一度的高考日,还是要来了。在期待自己能够在下周取得好成绩的同时也祝福高考考生旗开得胜吧!