手势识别MATLAB代码

手势识别是智能设备常用的需求, 下面我们用MATLAB来识别手部的形态:

主程序main.m

clc;clear all;close all;%清除命令行和窗口

im=imread('DSC05815.JPG');

skin,bwycbcr,w,h\] = hand_segmentation(im); im1=bwycbcr; % se = strel('ball',\[1 1 1;1 1 1;1 1 1\]); im1 = imdilate(im1,\[1 1 1;1 1 1;1 1 1\]); figure; imshow(im1); title('Dilated'); I_closed = imageclose(im1); bw2=imadjust(I_closed,\[0,1\]); %去除少像素连通区域 bw3=bwareaopen(bw2,round(w\*h/10)); figure; imshow(bw3); title('去除少数像素'); se=strel('disk',5); I_closed2=imclose(bw3,se); I=I_closed2; BW1=edge(I,'sobel'); %用SOBEL算子进行边缘检测 BW2=edge(I,'roberts');%用Roberts算子进行边缘检测 BW3=edge(I,'prewitt'); %用prewitt算子进行边缘检测 BW4=edge(I,'log'); %用log算子进行边缘检测 BW5=edge(I,'canny'); %用canny算子进行边缘检测 h=fspecial('gaussian',5); BW6=edge(I,'canny'); figure; subplot(2,3,1), imshow(BW1); title('sobel edge check'); subplot(2,3,2), imshow(BW2); title('sobel edge check'); subplot(2,3,3), imshow(BW3); title('prewitt edge check'); subplot(2,3,4), imshow(BW4); title('log edge check'); subplot(2,3,5), imshow(BW5); title('canny edge check'); subplot(2,3,6), imshow(BW6); title('gasussian\&canny edge check');%此为用高斯滤波后Canny算子边缘检测结果 r1=im(:,:,1); b1=im(:,:,2); g1=im(:,:,3); %% 判断边缘 \[w1,h1,k43\]=size(im); for i=1:w1 for j=1:h1 if BW6(i,j)==1%是边缘 % 用红色标出边缘 r1(i,j)=255; b1(i,j)=0; g1(i,j)=0; end end end Iegde=zeros(w1,h1,3); % 合成彩色图 Iegde(:,:,1)=r1; Iegde(:,:,2)=b1; Iegde(:,:,3)=g1; Iegde=double(Iegde/255);%转换为0-1彩色图 figure; imshow(Iegde);%绘制识别出来的图 **子函数imageclose.m** %执行了先膨后胀腐蚀的闭运算 function I_closed = imageclose(im1) %I=imread('result.bmp'); se=strel('disk',3); I_closed=imclose(im1,se); %subplot(1,2,1); %imshow(im1); figure; imshow(I_closed); title('闭运算后图像'); %imwrite(I_opened,'result1.bmp'); **子函数 hand_segmentation.m** function \[skin,bwycbcr,w,h\] = hand_segmentation(im) %imgrgb=imread('IMG_2755.jpg'); % im=imread('DSC05818.JPG'); \[w h\]=size(im(:,:,1)); %Laplacian 八邻域模板滤波 h1=\[-1,-1,-1;-1,9,-1;-1,-1,-1\]; bw1=imfilter(im,h1); % bw1=im; \[m,n,c\]=size(bw1); % delete strFile,c; %将RGB色彩空间转换为Ycbcr色彩空间 imgrgb3=rgb2ycbcr(bw1); y=imgrgb3(:,:,1); cb=imgrgb3(:,:,2); cr=imgrgb3(:,:,3); %================================== %在Ycbcr色彩空间中分割肤色区域 cb=double(cb); cr=double(cr); y=double(y); bwycbcr=zeros(m,n); for i=1:m for j=1:n if y(i,j)\<125 cb1=108+(125-y(i,j))\*10/109; cr1=154-(125-y(i,j))\*10/109; wcb=23+(y(i,j)-16)\*23.97/109; wcr=20+(y(i,j)-16)\*18.76/109; cb1=(cb(i,j)-cb1)\*46.97/wcb+cb1; cr1=(cr(i,j)-cr1)\*38.76/wcr+cr1; elseif y(i,j)\>188 cb1=108+(y(i,j)-188)\*10/47; cr1=154+(y(i,j)-188)\*22/47; wcb=14+(235-y(i,j))\*32.97/47; wcr=10+(235-y(i,j))\*28.76/47; cb1=(cb(i,j)-cb1)\*46.97/wcb+cb1; cr1=(cr(i,j)-cr1)\*38.76/wcr+cr1; else cb1=cb(i,j); cr1=cr(i,j); end x1=\[-0.819 0.574\]\*\[cb1-109.38;cr1-152.02\]; y1=\[-0.574 -0.819\]\*\[cb1-109.38;cr1-152.02\]; if (x1-1.60).\^2/644.6521+(y1-2.41).\^2/196.8409\<=1 bwycbcr(i,j)=1; else bwycbcr(i,j)=0; end end end %strWrite=strcat('a',strFile1); %imwrite(bwycbcr,strWrite,'jpg'); figure; %subplot(2,2,1); imshow(im); %title('原始图像'); figure; %subplot(2,2,2); imshow(bw1); figure; %title('Laplacian滤波'); %subplot(2,2,3); imshow(bwycbcr); % figure; %title('Ycbcr皮肤颜色模型'); %subplot(2,2,4); %把bwycbcr拉伸到\[0,1

bw2=imadjust(bwycbcr,[0,1]);

skin=bw2;

%去除少像素连通区域

skin=bwareaopen(skin,round(w*h/1000));

% imshow(skin);

% title('去除少数像素');

%imwrite(skin,'result.bmp');

子函数Datafind_V1.m

function [Cpx_C_fft_new5]=Datafind_V1(im4)

%im5=imread('result4.bmp');

Y X\]=size(im4); flag=1; %寻找链码的起始点 for k=1:Y if flag==0 break; end for kk=1:X b=im4(k,kk); if b==1 p_x=kk; p_y=k; flag=0; break; end end end imagesc(im4); colormap(gray); flag=1; cur_x=p_x; cur_y=p_y; chainCode=\[p_y p_x\]; im_bak=im4; while flag==1 im4(cur_y,cur_x)=0; imblock=im4(cur_y-1:cur_y+1,cur_x-1:cur_x+1); if sum(sum(imblock))==0 if sum(sum(im4))==0 \| abs(cur_x-p_x)+abs(cur_y-p_y)\<3 break; else im_bak(cur_y,cur_x)=0; im4=im_bak; cur_y=p_y; cur_x=p_x; chainCode=\[\]; end else \[n_y n_x\]=findNb(imblock); tmp=\[n_y+cur_y n_x+cur_x\]; chainCode=\[chainCode; tmp\]; cur_y=tmp(1); cur_x=tmp(2); end end %将链码出的边缘点组成复数点,并做归一化的傅里叶变换 Cpx_C=chainCode(:,1)+chainCode(:,2)\*i; N=length(Cpx_C); Cpx_C_fft=1/N\*fft(Cpx_C); figure;plot(real(Cpx_C),imag(Cpx_C)); title('链码点plot图片'); Cpx_C_fft_new5=abs(Cpx_C_fft(2:11)); %save data5.mat Cpx_C_fft_new5 ; %Cpx_C_new=ifft(Cpx_C_fft_new1); %figure;plot(real(Cpx_C_new),imag(Cpx_C_new)); %BW=10; %Cpx_C_fft_new=zeros(1,N); %Cpx_C_fft_new(1:BW+1)=Cpx_C_fft(1:BW+1); %Cpx_C_fft_new(N-(BW-1):N)=Cpx_C_fft(N-(BW-1):N); %Cpx_C_new=ifft(Cpx_C_fft_new); %figure;plot(real(Cpx_C_new),imag(Cpx_C_new)); 子函数boundary_trace.m %function g=boundary_trace(f) %g=boundary_trace(f)跟踪目标的外边界,f为输入的二值图像,g为输出的二值图像 %此处f g都是认为是二维矩阵 【行 列】==【y x】 %此算法只适用于二值图像 %f=imread('result1.bmp'); %去掉整幅图像四周围的像素点,保证图像目标的连通性 function g=boundary_trace(im2) \[YS,XS\]=size(im2); im2(1,1:XS)=0; im2(YS,1:XS)=0; im2(1:YS,1)=0; im2(1:YS,XS)=0; f=im2bw(im2); imshow(im2); offsetr=\[-1,0,1,0\]; offsetc=\[0,1,0,-1\]; next_search_dir_table=\[4 1 2 3\];%搜索方向查找表 next_dir_table=\[2 3 4 1\];%搜索顺序查找表 start=-1; boundary=-2; %找出起始点 \[rv,cv\]=find((f(2:end-1,:)\>0)\&(f(1:end-2,:)==0)); %此处可以简化处理,只用找出一个初始点即可。 rv=rv+1; startr=rv(1); startc=cv(1); f=im2double(f); f(startr,startc)=start; cur_p=\[startr,startc\]; init_dir=-1; done=0; next_dir=2; %初始搜索方向 flag=1; while\~done dir=next_dir; found_neighbour=0; for i=1:length(offsetr) %四邻域上的寻找下一个边缘点 offset=\[offsetr(dir),offsetc(dir)\]; neighbour=cur_p+offset; if(f(neighbour(1),neighbour(2)))\~=0 %找到新的边缘点 if(f(cur_p(1),cur_p(2))==start)\&(init_dir==-1) init_dir=dir; %记下离开初始点时的方向 %当前点为初始点且新的边缘点的离开方向为初始离开方向,表明跟踪过程已饶了一圈 elseif(f(cur_p(1),cur_p(2))==start)\&(init_dir==dir) done=1; found_neighbour=1; break; end next_dir=next_search_dir_table(dir); %下一个搜索方向 found_neighbour=1; if f(neighbour(1),neighbour(2))\~=start f(neighbour(1),neighbour(2))=boundary; end cur_p=neighbour; break; end dir=next_dir_table(dir); end end bi=find(f==boundary); f(:)=0; f(bi)=1; f(startr,startc)=1; g=im2bw(f); figure,imshow(g); %title('边缘追踪后图像'); %imwrite(g,'result4.bmp'); %\[Y,X\]=find(g); %corr=zeros(2,length(X)); %corr(1,:)=X; %corr(2,:)=Y; %frac_dim = boxcount(corr, 10,1); **子函数boundary_thin.m** function i_new1=boundary_thin(im3) %i=imread('result47.bmp'); %imshow(im3); %i_new=i\>128; %i_new1=bwmorph(i_new,'thin');2 i_new1=bwmorph(im3,'thin'); figure,imshow(i_new1); title('细化图像'); %imwrite(i_new1,'result5.bmp'); 子函数adjustsize.m function I_new1=adjustsize(im1) %I=imread('result.bmp'); %找到最左边和最右边灰度值不为1点的横坐标 J=sum(im1); m=size(im1,2); for i=1:m if J(i)\~=0 p=i; break; else continue; end end for j=m:-1:1 if J(j)\~=0 q=j; break; else continue; end end %找到最左边和最右边灰度值不为1点的纵坐标 I1=im1'; J1=sum(I1); n=size(I1,2); for k=1:n if J1(k)\~=0 r=k; break; else continue; end end for l=n:-1:1 if J1(l)\~=0 s=l; break; else continue; end end %剪切出以坐标点(p,r)和(q,s)组成的矩形区域 I_new=imcrop(im1,\[p r q-p s-r\]); %figure,imshow(I_new); I_new1=imresize(I_new,\[150 150\]); figure,imshow(I_new1); title('调整大小为150\*150图像'); 程序结果如下: ![](https://file.jishuzhan.net/article/1751216655897202689/e095b85210dc958d59db967844f02b73.webp) ![](https://file.jishuzhan.net/article/1751216655897202689/8eab0314badf09657bb7074209ceac44.webp) ![](https://file.jishuzhan.net/article/1751216655897202689/a0c42faea7d0fc716b8098383d25953b.webp) 完整代码见:[https://download.csdn.net/download/corn1949/88774968](https://download.csdn.net/download/corn1949/88774968 "https://download.csdn.net/download/corn1949/88774968")

相关推荐
夜夜敲码23 分钟前
C语言教程(十八):C 语言共用体详解
c语言·开发语言
大学生亨亨1 小时前
go语言八股文(五)
开发语言·笔记·golang
raoxiaoya1 小时前
同时安装多个版本的golang
开发语言·后端·golang
cloues break.2 小时前
C++进阶----多态
开发语言·c++
我不会编程5552 小时前
Python Cookbook-6.10 保留对被绑定方法的引用且支持垃圾回收
开发语言·python
道剑剑非道3 小时前
QT开发技术【qcustomplot 曲线与鼠标十字功能】
开发语言·qt·计算机外设
刘婉晴3 小时前
【环境配置】Mac电脑安装运行R语言教程 2025年
开发语言·macos·r语言
Despacito0o3 小时前
C++核心编程:类与对象全面解析
开发语言·c++
Tiger Z3 小时前
R 语言科研绘图第 43 期 --- 桑基图-冲击
开发语言·r语言·贴图
全栈师4 小时前
C#中分组循环的做法
开发语言·c#