基于matlab gui的手势识别,导入手部图片,基于肤色模型的颜色分割,去噪,边缘提取,傅立叶算子特征提取,利用最小距离识别手势。
最近在研究基于Matlab GUI的手势识别,觉得还挺有趣,来和大家分享分享。
导入手部图片
首先,得把我们要处理的手部图片导入到Matlab环境中。在Matlab里,这其实挺简单的。假设图片放在当前工作目录下,代码如下:
matlab
img = imread('hand_image.jpg');
imshow(img);
这里,imread函数就是用来读取图片的,括号里写上图片的文件名就行。imshow函数则是把读进来的图片显示出来,方便我们看看图片是不是导入对了。
基于肤色模型的颜色分割
肤色模型是手势识别中很关键的一步,通过它我们可以把手部区域从背景中大致分割出来。常见的肤色模型有YCrCb模型等。在Matlab里实现基于YCrCb模型的肤色分割,代码如下:
matlab
ycbcr = rgb2ycbcr(img);
Cb = ycbcr(:,:,2);
Cr = ycbcr(:,:,3);
skin_mask = (Cb >= 77) & (Cb <= 127) & (Cr >= 133) & (Cr <= 173);
skin_img = img;
skin_img(~skin_mask,:) = 0;
imshow(skin_img);
上面这段代码,先把RGB图像转换为YCrCb图像,然后提取出其中的Cb和Cr分量。接着通过设定合适的阈值范围,创建一个二值化的掩码skin_mask,符合肤色范围的像素为1,其他为0。最后,用这个掩码处理原始图像,得到只包含肤色区域的图像并显示。
去噪
经过颜色分割后的图像可能会存在一些噪声,这时候就需要去噪处理,让图像更干净,方便后续处理。高斯滤波是一种常用的去噪方法,Matlab实现代码如下:
matlab
denoised_img = imgaussfilt(skin_img, 2);
imshow(denoised_img);
imgaussfilt函数就是进行高斯滤波的,第二个参数2表示高斯核的标准差,标准差越大,滤波效果越平滑,但也可能会丢失一些细节,这里根据实际情况调整这个参数。
边缘提取
有了干净的图像后,边缘提取能帮助我们确定手势的轮廓。Canny边缘检测算法是比较经典的,代码如下:
matlab
edges = edge(denoised_img, 'Canny');
imshow(edges);
edge函数里指定使用'Canny'算法,它会自动检测图像中的边缘,并生成一个二值化的边缘图像显示出来。
傅立叶算子特征提取
傅立叶算子可以把图像从空间域转换到频域,提取一些频域特征。这里简单演示一下对图像进行二维傅里叶变换:
matlab
img_fft = fft2(double(edges));
img_fft_shifted = fftshift(img_fft);
magnitude_spectrum = log(1 + abs(img_fft_shifted));
imshow(magnitude_spectrum, []);
fft2函数对图像进行二维傅里叶变换,fftshift函数把零频率分量移到频谱中心,方便观察。最后取对数并加上1是为了更好地显示频谱,因为傅里叶变换后的幅度值范围很大,直接显示很难看出细节。
利用最小距离识别手势
最后一步就是利用前面提取的特征,通过最小距离法来识别手势啦。假设有一些已知手势的特征模板,代码大致框架如下:
matlab
% 假设已经提取了测试手势的特征向量test_feature
% 假设有多个已知手势的特征向量存储在feature_templates矩阵中,每行一个特征向量
distances = pdist2(test_feature, feature_templates, 'euclidean');
[min_distance, min_index] = min(distances);
recognized_gesture = gesture_labels(min_index);
这里pdist2函数计算测试特征向量与每个模板特征向量之间的欧氏距离。min函数找到最小距离及其对应的索引,通过这个索引就能从gesture_labels里找到识别出来的手势标签。
基于Matlab GUI实现手势识别,每一步都充满了挑战与乐趣,希望这篇文章能给同样对这个领域感兴趣的小伙伴一些启发。
