【得捷电子Follow me第2期】任务4:分任务5:AI功能应用
[复制链接]
【得捷电子Follow me第2期】任务4:分任务5:AI功能应用
结合运动传感器,完成手势识别功能,识别三种手势 水平左右、前后、垂直上下。
编程语言和环境用CircuitPython:
开发板:
Adafruit Feather ESP32-S3 TFT
传感器:
lis3dh运动传感器。
运行环境:
Adafruit CircuitPython 8.2.3 on 2023-08-11
编辑器:
mu-editor
用到的额外模块:
adafruit_lis3dh.mpy
这是补充任务,买错了,买了两个一模一样的运动传感器,说我买了两个传感器,没用上不给报销,最后还是老老实实把手势识别的任务做了。
其实算不上AI,就是用DTW算法,叫什么动态路径什么的。
参考了b站:https://www.bilibili.com/video/BV11Y411p7vj ,https://www.bilibili.com/video/BV1CG411R7CS
这两个视频的
代码解析:
这个是myDTW.py文件,我做成了单独的py文件,方便以后用:
DTW(s1, s2, distanceFunc, needPath)
s1,s2是两个数组,distanceFunc需要传入求距离的函数,needPath是否返回路径,感觉返回路径没什么用。
import ulab.numpy as np
def DTW(s1, s2, distanceFunc, needPath):
n1=len(s1)
n2=len(s2)
m=np.zeros([n1, n2])
m[0,0] = distanceFunc(s1[0], s2[0])
for i in range(1,n1):
m[i,0]=distanceFunc(s1[i], s2[0])+m[i-1,0]
for j in range(1,n2):
m[0,j]=distanceFunc(s1[0], s2[j])+m[0,j-1]
for i in range(1, n1):
for j in range(1, n2):
m[i,j]=distanceFunc(s1[i], s2[j])+min(m[i-1, j-1], m[i, j-1], m[i-1, j])
if not needPath:
return m[n1-1, n2-1]
path = np.zeros([n1+n2,2])
i = n1-1
j = n2-1
k = 1
path[0]=(i,j)
while True:
if i>0 and j>0:
a=m[i-1,j]
b=m[i-1,j-1]
c=m[i,j-1]
d=min(a,b,c)
if d==b:
i-=1
j-=1
elif d==a:
i-=1
else:
j-=1
path[k]=(i,j)
k+=1
elif i==0 and j==0 :
path[k]=(0,0)
k+=1
break
elif i==0:
j-=1
path[k]=(i,j)
k+=1
elif j==0:
i-=1
path[k]=(i,j)
k+=1
return m[n1-1, n2-1], np.flip(path[:k-1],axis=0)
if __name__=="__main__":
def ds(a, b):
return abs(a-b)
d, p = DTW([1,3,4,9,8,2,1,5,7,3],[1,6,2,3,0,9,4,1,6,3], ds, True)
print(d,p)
下面是两个求距离的函数:
第一个实际就是向量a-b的模长乘以夹角的cos值,
cos值是-1~1,假如a与b同向cos值为1,我们想要相反的值0,所以用1-cos,然后是同向的长度问题,1-1等于0,跟d0乘结果都是0,无法区分,
所以需要把cos的取值范围减少,这个是乘以0.5.
第二个实际就是3轴对应相减取绝对值再求和,简单省事,结果也还行,但是速度却没提升多少,有点迷。
def ds(a, b):
alen=np.sqrt(np.dot(a,a))
blen=np.sqrt(np.dot(b,b))
cosab=np.dot(a,b)/(alen*blen)
d0=a-b
d0=np.sqrt(np.dot(d0,d0))
scale = 0.5
return (1-scale*cosab)*d0
def ds2(a, b):
return np.sum(abs(a-b))
下面是保存文件的代码,这个保存需要弹出usb才能保存,circuitpython的教程有时说保存的注意事项。
def saveRecord(npdata, name):
storage.remount("/", readonly=False)
try:
os.stat(directory)
except:
os.mkdir(directory)
try:
np.save(f'''{directory}/{name}.npy''', npdata)
finally:
storage.remount("/", readonly=True)
print(f'''{directory}/{name}.npy saved!''')
其他的就没什么好说的了,我要报销,我要报销,我要报销
下面是视频演示:
任务4:分任务5:AI功能应用
任务源码
|