手势识别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://download.csdn.net/download/corn1949/88774968

相关推荐
zmzb01031 分钟前
Python课后习题训练记录Day130
开发语言·python
阿里嘎多学长15 分钟前
2026-06-13 GitHub 热点项目精选
开发语言·程序员·github·代码托管
xiaoshuaishuai825 分钟前
C# 委托与事件
开发语言·c#
kmblack126 分钟前
javascript计算年龄
开发语言·javascript·ecmascript
肖爱Kun1 小时前
STL标准模块库操作
开发语言·音视频
Song_da_da_1 小时前
C# 接口(Interface)深度解析:规范、解耦与灵活扩展
开发语言·c#
政沅同学1 小时前
基于 C# WPF + HALCON 的工业视觉算法工具框架(开源)
开发语言·c#·wpf
影寂ldy1 小时前
C#WinForm 窗体基础(入口、部分类、属性、生命周期事件)
开发语言·c#
2301_781833521 小时前
Python 正则表达式入门教程
开发语言·python·正则表达式
gihigo19981 小时前
基于蒙特卡洛的异常值剔除(RANSAC + MC置信区间)—MATLAB实现
开发语言·算法·matlab