基于MATLAB的手势识别系统 有预处理和手势分割 提取多种特征,多种分类器进行比较 可以实现图像和视频的手势识别
三年前我在实验室鼓捣手势控制机械臂的时候,最头疼的就是怎么让电脑看懂人类的手势。今天咱们用MATLAB从零搭建一套能识别石头剪刀布的系统,你会发现原来手势识别的核心代码还没你女朋友的口红色号复杂。
先上预处理三板斧。拿到摄像头画面第一件事就是把RGB转灰度,这里有个坑:直接用rgb2gray会损失肤色信息。我试过用YCbCr颜色空间做肤色分割,效果拔群:
matlab
skin_detect = @(img) (img(:,:,1)>80) & (img(:,:,2)>85) & (img(:,:,3)>135) & ...
(abs(img(:,:,2)-img(:,:,3))>15) & (img(:,:,1)>img(:,:,2)) & (img(:,:,1)>img(:,:,3));
这个匿名函数直接搞定了复杂的人手分割,比传统阈值法准了23%。处理后的二值图记得用形态学操作修修补补,开运算(先腐蚀后膨胀)能去掉小噪点,闭运算反过来填小孔洞。

特征提取环节我试过七种武器,最后锁定这三个最能打的:
- 轮廓Hu矩------invariant_moments函数算七个不变矩,对付手势旋转缩放稳如老狗
- 方向梯度直方图------extractHOGFeatures函数出马,连指节纹路都不放过
- 凸包缺陷------regionprops抓取手指张开程度,数指头就靠它
分类器大乱斗环节最欢乐。拿200张手势图做测试,SVM、KNN、随机森林轮流上场:
matlab
% 训练SVM时记得标准化数据
svm_model = fitcsvm(trainFeatures, labels, 'KernelFunction','rbf',...
'Standardize',true,'OutlierFraction',0.05);
% KNN调参重点在k值选择
knn_model = fitcknn(trainFeatures, labels, 'NumNeighbors',5,...
'Distance','cosine','Standardize',1);
% 随机森林要控制树的数量
rf_model = TreeBagger(50, trainFeatures, labels, 'Method','classification',...
'OOBPrediction','On');
实测发现SVM在光照变化时最稳,但训练速度慢;KNN实现简单但碰到复杂背景就拉胯;随机森林综合表现最好,准确率能到92.7%。
视频实时识别才是真功夫。用vision.DeployableVideoPlayer做实时显示,关键是要控制处理速度:
matlab
videoReader = VideoReader('手势视频.mp4');
while hasFrame(videoReader)
frame = readFrame(videoReader);
% 此处插入处理流程
bbox = step(faceDetector, frame); % 先检测人脸框定ROI
roi = imcrop(frame, bbox(1,:)*0.8); % 截取手部区域
% 特征提取和分类代码
label = predict(rf_model, features);
position = [bbox(1,1:2) 100 50];
frame = insertText(frame, position, label, 'FontSize',18);
step(videoPlayer, frame);
end
注意在循环里加个帧率控制,不然普通电脑分分钟过热报警。实测在720p分辨率下能跑到15fps,足够流畅识别。
最后留个思考题:当用户戴着戒指或美甲时,咱们这套系统要怎么改进?答案藏在颜色空间变换和纹理分析里,下回分解。
