使用Python和Kinect进行手势识别:HMM学习
我想用Python和Kinect做手势识别。
在了解了一些理论后,我觉得一种不错的方法是使用无监督学习和隐马尔可夫模型(HMM),结合一些已知的手势数据,来训练出一组HMM(每个我想识别的手势一个)。
接下来,我会通过匹配观察到的数据与训练好的HMM,找到最大对数似然(可能是用维特比算法?)。
举个例子,我用Kinect设备记录了一些手势的数据(右手的坐标x,y,z),比如打招呼、踢拳、用手画圈,然后我进行一些训练:
# training
known_datas = [
tuple( load_data('punch.mat'), 'PUNCH' ),
tuple( load_data('say_hello.mat'), 'HELLO' ),
tuple( load_data('do_circle_with_hands.mat'), 'CIRCLE' )
]
gestures = set()
for x, name in known_datas:
m = HMM()
m.baumWelch(x)
gestures.add(m)
然后我会对新的观察数据进行识别,计算最大对数似然,并选择之前保存的手势中,最大对数似然对应的手势,针对每个训练好的HMM:
# recognition
observed = load_data('new_data.mat')
logliks = [m.viterbi(observed) for m in gestures]
print 'observed data is ', gestures[logliks.index(max(logliks))]
我有几个问题:
- 这样做是不是完全傻?
- 实际案例需要多少训练数据集?
- 每个HMM需要多少个状态?
- 能否做到实时识别?
2 个回答
这个方法已经在很多不同的情况下成功应用过了:http://scholar.google.co.il/scholar?hl=en&q=HMM+Gesture+Recognition。
备注:
- 这是一个适合机器学习问题的地方:https://stats.stackexchange.com/
- 可以看看这个手势挑战赛。
首先,这个问题很特别,你需要找一个机器学习方面的专家来帮忙。不幸的是,目前在Stack Exchange网站上还没有类似的机器学习专栏……也许将来会有吧。:)
我觉得你的思路是对的,不过有几点需要注意:
你这里提到的
HMM
类,通过HMM()
来实例化,需要设计得当,这样它的结构才能表示类似手势的东西。HMM有状态和它们之间的转移,那么你怎么定义一个手势的HMM呢?我相信这是可行的(我甚至觉得这是个好方法),但需要一些思考。也许状态可以是一个3D立方体的角落,对于你识别的手势中的每一个观察点,你可以选择离它最近的那个角落。然后,BW算法可以通过你的训练数据来近似转移的可能性。不过,你可能需要选择一个更细致的状态模型,比如一个n * n * n的体素网格。维特比算法并不是给你模型的可能性,而是给你在给定观察序列下最可能的状态序列。如果我没记错的话,你应该使用前向算法来获取在给定模型下某个观察序列的概率。
我猜,如果有一个训练得很好且不太复杂的HMM,你应该能够实时识别手势,但这只是我的一个推测。:)