%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Trainingfilenum = 3; % 训练人数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第一部分: 从不同文件夹导入图片
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% %%%% %%%% 第一步: 导入二值化步态图片,图片来自中科院CASIA数据库B库
% 导入图集为各个行人的步态图像;然后以下以第一次出现步态跨度最小至第三次出现步态最小为一个步态周期。
figure('NumberTitle','off','Name','数据库图集');
%%%% %%%% 从图集中读取所有图片
fileDir = ['gaitpic\Trainingset\cl',num2str(filnum),'\']; % 文件夹路径(这里指的图片文件),filnum为行人XXX的步态
filePattern = '*.png'; % 文件格式(图片格式)
dis = dir([fileDir,filePattern]); % 利用dir函数,返回fileDir路径下、filePattern
% 所有文件(文件名、文件路径、日期、字节等)
infilenames = {dis.name}; % 得到文件名
infilenums = length(infilenames); % 得到文件个数
for i=1:infilenums % 循环读取文件
filen = [fileDir infilenames{i}]; % '\gaitpic\Trainingset\cl-filnum\第i个文件'
gpic = imread(filen); % imread('gaitpic\Trainingset\cl-filnum\第i个文件')
GaitMessage(filnum).GaitPicture(:,:,i) = gpic;
imshow(GaitMessage(filnum).GaitPicture(:,:,i));title(['No.1-',num2str(i)]);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第一部分 导入图片
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第二部分: 图像预处理
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% 1、形态学处理
figure('NumberTitle','off','Name','图像预处理-形态学处理');
% picnums获取第filnum个人的步态图片张数
[height,width,picnums] = size( GaitMessage(filnum).GaitPicture);
% 选取形态学处理的结构元素
close_se = strel('disk',4); % 边长为4的圆盘结构元素
open_se = strel('disk',4); % 边长为4的圆盘结构元素
%%%% 进行边长为4的八边形 先闭后开运算
for i=1:picnums % 对该人的所有步态图像进行形态学处理
clo = imclose( GaitMessage(filnum).GaitPicture(:,:,i) ,close_se); % 闭运算操作
ope = imopen(clo,open_se); % 开运算操作
GaitMessage(filnum).Morphology(:,:,i) = ope; % 形态学处理后的图片
imshow( GaitMessage(filnum).Morphology(:,:,i) );title(['No.2-',num2str(filnum),'-1-',num2str(i)]);
end
%%%% %%%% 2、人像轮廓提取(边缘检测) - 骨骼提取(细化函数) - 生成轮廓骨骼图像
figure('NumberTitle','off','Name','图像预处理-边缘检测');
for i=1:picnums
GaitMessage(filnum).Edgepic(:,:,i) = edge( GaitMessage(filnum).Morphology(:,:,i),'sobel'); % sobel算子
GaitMessage(filnum).Skeletonpic(:,:,i) = bwmorph( GaitMessage(filnum).Morphology(:,:,i),'thin',Inf); % 人体细化
GaitMessage(filnum).EdgeandSkeleton(:,:,i) = GaitMessage(filnum).Edgepic(:,:,i) + GaitMessage(filnum).Skeletonpic(:,:,i); % 生成轮廓骨骼图
% 保存下来,保存路径为:gaitpic/EdgeandSkeleton/all/filnum-es-i.png
imwrite( GaitMessage(filnum).EdgeandSkeleton(:,:,i) , strcat(['gaitpic/EdgeandSkeleton/all/',num2str(filnum),'es',num2str(i),'.png']));
% 画图部分
% imshow( GaitMessage(filnum).Edgepic(:,:,i) );title(['No.2-',num2str(filnum),'-2-',num2str(i)]); % 显示轮廓图 ;
% imshow( GaitMessage(filnum).Skeletonpic(:,:,i) );title(['No.2-',num2str(filnum),'-2-',num2str(i)]); % 显示骨骼图
imshow( GaitMessage(filnum).EdgeandSkeleton(:,:,i) );title(['No.2-',num2str(filnum),'-2-',num2str(i)]); % 显示轮廓骨骼图
% 画图结束
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第二部分: 图像预处理
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
// An highlighted block
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第三部分: 步态周期检测与提取
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% picnums获取第filnum个人的步态图片张数
[height,width,picnums] = size( GaitMessage(filnum).GaitPicture);
%%%% %%%% 获得每个轮廓的最小外接矩形 & 以其矩形的长宽作为人像高宽
for i=1:picnums
imbiEdgepic = imbinarize( GaitMessage(filnum).Morphology(:,:,i) ); % 步态图二值化
%%%% regionprops函数用于返回图片的属性,求各个轮廓的最小外接矩形
GaitMessage(filnum).BoundBs(1,i) = regionprops(imbiEdgepic,'BoundingBox'); % 利用函数度量图像区域属性,这里度量最小外接矩形
% 返回一个结构数据,其内是有关最小外接矩形的位置
% 长、宽信息,调用格式:s.BoundingBox
% s.BoundingBox = [x,y,w(△x),h(△y)]
%%%% 求各个对应的宽高比
rec_width = GaitMessage(filnum).BoundBs(i).BoundingBox(3); % 宽
rec_heigh = GaitMessage(filnum).BoundBs(i).BoundingBox(4); % 高
GaitFeatures(filnum).Aspectratio(1,i) = rec_width / rec_heigh; % 宽高比特征
end
% 画图部分:
figure('NumberTitle','off','Name','步态周期检测-宽高比');
plot(GaitFeatures(filnum).Aspectratio); title(['No.3-',num2str(filnum),'步态集-人像宽高比变化曲线']);% 画出面积走势图
% 画图结束
%%%% %%%% 取连续三个局部最小值之间为一个周期(也可以取得连续三个局部最大值之间为一个周期)
%%%% 利用寻找峰值函数找到局部极值
[peas,locs] = findpeaks( -GaitFeatures(filnum).Aspectratio );% 由于想寻找局部极小值,而该函数是寻找局部极大值,所以对其取负
peas = - peas; % 将值还原 % 由于本次未使用这个值,所以注释掉了;如果需要使用,则需要将注释去除,不然值是所需值的负数
%%%% 取连续三个局部最小值之间为一个周期,第一个极小为起点,第三个极小为终点
periodstart = 1;periodend = 3;
GaitMessage(filnum).periodlocs = [locs(periodstart) locs(periodend)];
%%%% 取宽高比周期
GaitMessage(filnum).mPeriod = GaitFeatures(filnum).Aspectratio(GaitMessage(filnum).periodlocs(1):GaitMessage(filnum).periodlocs(2));
% 画图部分:
figure('NumberTitle','off','Name','步态周期检测-周期提取');
plot(GaitMessage(filnum).mPeriod);title(['No.3-',num2str(filnum),'步态集-步态周期内人像宽高比变化曲线']);% 画出面积走势图
% 画图结束
%%%% 取周期内的步态图片
GaitMessage(filnum).GaitPeriod = GaitMessage(filnum).EdgeandSkeleton(:,:,GaitMessage(filnum).periodlocs(1):GaitMessage(filnum).periodlocs(2));
[height,width,picnums] = size( GaitMessage(filnum).GaitPeriod );
for i = 1:picnums
%保存下来,保存路径为:gaitpic/EdgeandSkeleton/period/filnum-es-i.png
imwrite( GaitMessage(filnum).GaitPeriod(:,:,i) , strcat(['gaitpic/EdgeandSkeleton/period/',num2str(filnum),'es',num2str(i),'.png']));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第三部分: 步态周期检测
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第四部分: 角度特征提取
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% %%%% %%%% 第四步: 步态特征提取
sectornums = 2; % 分区数,即将下半身分为两个分区,将人像以垂直轴(y轴)为分界线,左右分别为一个分区
%%%% %%%% 整个过程角度特征距离特征 以质心为原点,对下半身采用2分区,提取各个分区信息以及轮廓像素信息,
[GaitFeatures(filnum).nthsectorFeatures,Outlinepixelmessage,centroid] = test_Outlinepixel2Centroid_AngleDistance(GaitMessage(filnum).EdgeandSkeleton,sectornums);
% 只获取一个步态周期内的角度特征
for nths = 1:sectornums
GaitFeatures(filnum).nthsectorPeriodFeatures(nths).PeriodaverageAngle = GaitFeatures(filnum).nthsectorFeatures(nths).averageAngle(GaitMessage(filnum).periodlocs(1):GaitMessage(filnum).periodlocs(2));
end
%%%% 画图部分:画出该人步态角度特征
figure('NumberTitle','off','Name','同一人整个过程-角度特征');
for i = 1:sectornums
plot(GaitFeatures(filnum).nthsectorFeatures(i).averageAngle - 270);title(['No.4-',num2str(filnum),'-1','同一人的1/2分区-角度均值变化曲线']) % 画出角度走势图
hold on
end
% 对应的周期角度特征曲线
figure('NumberTitle','off','Name','同一人步态周期内-角度特征');
for i = 1:sectornums
plot(GaitFeatures(filnum).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270);title(['No.4-',num2str(filnum),'-2','同一人的1/2分区-周期角度均值变化曲线']) % 画出角度走势图
hold on
end
%%%% 画图结束
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第四部分: 角度特征提取
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
注:个人觉得求均值效果不好,但是计算出的角度特征变化曲线也还能够不错的体现出步态的周期性;但是可以考虑如期望之类的其他数学方法,这里就由各位数学大佬来考虑考虑了,我这里暂时采用均值方式。
// An highlighted block
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 步态特征提取 宽高比特征以及角度特征
%
% 2019/6/18
% BinHeon
% https://blog.csdn.net/BinHeon
%
% 注意:如果选择测试的人数超过5个人,请注释掉部分显示图片/画图窗口,
% 显示窗口超过30个以上可能出现matlab报错,提示画图低级错误
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
close all;
clear;
clc;
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
Trainingfilenum = 3; % 训练人数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第一部分: 从不同文件夹导入图片
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% %%%% %%%% 第一步: 导入二值化步态图片,图片来自中科院CASIA数据库B库
% 导入图集为一个步态周期,且以步态跨度最大时为起始时刻
figure('NumberTitle','off','Name','数据库图集');
%%%% %%%% 从图集中读取所有图片
fileDir = ['gaitpic\Trainingset\cl',num2str(filnum),'\']; % 文件夹路径(这里指的图片文件)
filePattern = '*.png'; % 文件格式(图片格式)
dis = dir([fileDir,filePattern]); % 利用dir函数,返回fileDir路径下、filePattern
% 所有文件(文件名、文件路径、日期、字节等)
infilenames = {dis.name}; % 得到文件名
infilenums = length(infilenames); % 得到文件个数
for i=1:infilenums % 循环读取文件
filen = [fileDir infilenames{i}]; % '\gaitpic\Trainingset\cl-filnum\第i个文件'
gpic = imread(filen); % imread('gaitpic\Trainingset\cl-filnum\第i个文件')
GaitMessage(filnum).GaitPicture(:,:,i) = gpic;
imshow(GaitMessage(filnum).GaitPicture(:,:,i));title(['No.1-',num2str(i)]);
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第一部分 导入图片
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第二部分: 图像预处理
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% 1、形态学处理
figure('NumberTitle','off','Name','图像预处理-形态学处理');
% picnums获取第filnum个人的步态图片张数
[height,width,picnums] = size( GaitMessage(filnum).GaitPicture);
% 选取形态学处理的结构元素
close_se = strel('disk',4); % 边长为4的圆盘结构元素
open_se = strel('disk',4); % 边长为4的圆盘结构元素
%%%% 进行边长为4的八边形 先闭后开运算
for i=1:picnums % 对该人的所有步态图像进行形态学处理
clo = imclose( GaitMessage(filnum).GaitPicture(:,:,i) ,close_se); % 闭运算操作
ope = imopen(clo,open_se); % 开运算操作
GaitMessage(filnum).Morphology(:,:,i) = ope; % 形态学处理后的图片
imshow( GaitMessage(filnum).Morphology(:,:,i) );title(['No.2-',num2str(filnum),'-1-',num2str(i)]);
end
%%%% %%%% 2、人像轮廓提取(边缘检测) - 骨骼提取(细化函数) - 生成轮廓骨骼图像
figure('NumberTitle','off','Name','图像预处理-边缘检测');
for i=1:picnums
GaitMessage(filnum).Edgepic(:,:,i) = edge( GaitMessage(filnum).Morphology(:,:,i),'sobel'); % sobel算子
GaitMessage(filnum).Skeletonpic(:,:,i) = bwmorph( GaitMessage(filnum).Morphology(:,:,i),'thin',Inf); % 人体细化
GaitMessage(filnum).EdgeandSkeleton(:,:,i) = GaitMessage(filnum).Edgepic(:,:,i) + GaitMessage(filnum).Skeletonpic(:,:,i); % 生成轮廓骨骼图
% 保存下来,保存路径为:gaitpic/EdgeandSkeleton/all/filnum-es-i.png
imwrite( GaitMessage(filnum).EdgeandSkeleton(:,:,i) , strcat(['gaitpic/EdgeandSkeleton/all/',num2str(filnum),'es',num2str(i),'.png']));
% 画图部分
% imshow( GaitMessage(filnum).Edgepic(:,:,i) );title(['No.2-',num2str(filnum),'-2-',num2str(i)]); % 显示轮廓图 ;
% imshow( GaitMessage(filnum).Skeletonpic(:,:,i) );title(['No.2-',num2str(filnum),'-2-',num2str(i)]); % 显示骨骼图
imshow( GaitMessage(filnum).EdgeandSkeleton(:,:,i) );title(['No.2-',num2str(filnum),'-2-',num2str(i)]); % 显示轮廓骨骼图
% 画图结束
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第二部分: 图像预处理
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第三部分: 步态周期检测与提取
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% picnums获取第filnum个人的步态图片张数
[height,width,picnums] = size( GaitMessage(filnum).GaitPicture);
%%%% %%%% 获得每个轮廓的最小外接矩形 & 以其矩形的长宽作为人像高宽
for i=1:picnums
imbiEdgepic = imbinarize( GaitMessage(filnum).Morphology(:,:,i) ); % 步态图二值化
%%%% regionprops函数用于返回图片的属性,求各个轮廓的最小外接矩形
GaitMessage(filnum).BoundBs(1,i) = regionprops(imbiEdgepic,'BoundingBox'); % 利用函数度量图像区域属性,这里度量最小外接矩形
% 返回一个结构数据,其内是有关最小外接矩形的位置
% 长、宽信息,调用格式:s.BoundingBox
% s.BoundingBox = [x,y,w(△x),h(△y)]
%%%% 求各个对应的宽高比
rec_width = GaitMessage(filnum).BoundBs(i).BoundingBox(3); % 宽
rec_heigh = GaitMessage(filnum).BoundBs(i).BoundingBox(4); % 高
GaitFeatures(filnum).Aspectratio(1,i) = rec_width / rec_heigh; % 宽高比特征
end
% 画图部分:
figure('NumberTitle','off','Name','步态周期检测-宽高比');
plot(GaitFeatures(filnum).Aspectratio); title(['No.3-',num2str(filnum),'步态集-人像宽高比变化曲线']);% 画出面积走势图
% 画图结束
%%%% %%%% 取连续三个局部最小值之间为一个周期(也可以取得连续三个局部最大值之间为一个周期)
%%%% 利用寻找峰值函数找到局部极值
[peas,locs] = findpeaks( -GaitFeatures(filnum).Aspectratio );% 由于想寻找局部极小值,而该函数是寻找局部极大值,所以对其取负
peas = - peas; % 将值还原 % 由于本次未使用这个值,所以注释掉了;如果需要使用,则需要将注释去除,不然值是所需值的负数
%%%% 取连续三个局部最小值之间为一个周期,第一个极小为起点,第三个极小为终点
periodstart = 1;periodend = 3;
GaitMessage(filnum).periodlocs = [locs(periodstart) locs(periodend)];
%%%% 取宽高比周期
GaitMessage(filnum).mPeriod = GaitFeatures(filnum).Aspectratio(GaitMessage(filnum).periodlocs(1):GaitMessage(filnum).periodlocs(2));
% 画图部分:
figure('NumberTitle','off','Name','步态周期检测-周期提取');
plot(GaitMessage(filnum).mPeriod);title(['No.3-',num2str(filnum),'步态集-步态周期内人像宽高比变化曲线']);% 画出面积走势图
% 画图结束
%%%% 取周期内的步态图片
GaitMessage(filnum).GaitPeriod = GaitMessage(filnum).EdgeandSkeleton(:,:,GaitMessage(filnum).periodlocs(1):GaitMessage(filnum).periodlocs(2));
[height,width,picnums] = size( GaitMessage(filnum).GaitPeriod );
for i = 1:picnums
%保存下来,保存路径为:gaitpic/EdgeandSkeleton/period/filnum-es-i.png
imwrite( GaitMessage(filnum).GaitPeriod(:,:,i) , strcat(['gaitpic/EdgeandSkeleton/period/',num2str(filnum),'es',num2str(i),'.png']));
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第三部分: 步态周期检测
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 第四部分: 角度特征提取
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% %%%% %%%% 第四步: 步态特征提取
sectornums = 2; % 分区数,即将下半身分为两个分区,将人像以垂直轴(y轴)为分界线,左右分别为一个分区
%%%% %%%% 整个过程角度特征距离特征 以质心为原点,对下半身采用2分区,提取各个分区信息以及轮廓像素信息,
[GaitFeatures(filnum).nthsectorFeatures,Outlinepixelmessage,centroid] = test_Outlinepixel2Centroid_AngleDistance(GaitMessage(filnum).EdgeandSkeleton,sectornums);
% 只获取一个步态周期内的角度特征
for nths = 1:sectornums
GaitFeatures(filnum).nthsectorPeriodFeatures(nths).PeriodaverageAngle = GaitFeatures(filnum).nthsectorFeatures(nths).averageAngle(GaitMessage(filnum).periodlocs(1):GaitMessage(filnum).periodlocs(2));
end
%%%% 画图部分:画出该人步态角度特征
figure('NumberTitle','off','Name','同一人整个过程-角度特征');
for i = 1:sectornums
plot(GaitFeatures(filnum).nthsectorFeatures(i).averageAngle - 270);title(['No.4-',num2str(filnum),'-1','同一人的1/2分区-角度均值变化曲线']) % 画出角度走势图
hold on
end
% 对应的周期角度特征曲线
figure('NumberTitle','off','Name','同一人步态周期内-角度特征');
for i = 1:sectornums
plot(GaitFeatures(filnum).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270);title(['No.4-',num2str(filnum),'-2','同一人的1/2分区-周期角度均值变化曲线']) % 画出角度走势图
hold on
end
%%%% 画图结束
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 第四部分: 角度特征提取
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 画图部分-画出当前所有测试人员的角度特征曲线
% 注:这里给出最多画10人不同曲线的代码,由于曲线线条形状、颜色不同,采用switch语句来画
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% 画图部分: 画出当前所有测试人员的角度特征曲线
switch filnum
case 1
figure('NumberTitle','off','Name','所有人整个过程-角度特征');
title('不同行人左右分区角度特征比较');% 画出走势图
for i = 1:sectornums
plot(GaitFeatures(1).nthsectorFeatures(i).averageAngle - 270,'b-o','MarkerFaceColor','b');
hold on
end
case 2
for i = 1:sectornums
plot(GaitFeatures(2).nthsectorFeatures(i).averageAngle - 270,'g-x','MarkerFaceColor','g');
hold on
end
case 3
for i = 1:sectornums
plot(GaitFeatures(3).nthsectorFeatures(i).averageAngle - 270,'r-*','MarkerFaceColor','r');
hold on
end
case 4
for i = 1:sectornums
plot(GaitFeatures(4).nthsectorFeatures(i).averageAngle - 270,'c-p','MarkerFaceColor','c');
hold on
end
case 5
for i = 1:sectornums
title('不同行人左右分区角度特征比较');% 画出走势图
plot(GaitFeatures(5).nthsectorFeatures(i).averageAngle - 270,'k-s','MarkerFaceColor','k');
hold on
end
case 6
figure('NumberTitle','off','Name','步态角度特征');
title('不同行人左右分区角度特征比较');% 画出走势图
for i = 1:sectornums
plot(GaitFeatures(6).nthsectorFeatures(i).averageAngle - 270,'b-o','MarkerFaceColor','b');
hold on
end
case 7
for i = 1:sectornums
plot(GaitFeatures(7).nthsectorFeatures(i).averageAngle - 270,'g-x','MarkerFaceColor','g');
hold on
end
case 8
for i = 1:sectornums
plot(GaitFeatures(8).nthsectorFeatures(i).averageAngle - 270,'r-*','MarkerFaceColor','r');
hold on
end
case 9
for i = 1:sectornums
plot(GaitFeatures(9).nthsectorFeatures(i).averageAngle - 270,'c-p','MarkerFaceColor','c');
hold on
end
case 10
for i = 1:sectornums
title('不同行人左右分区角度特征比较');% 画出走势图
plot(GaitFeatures(10).nthsectorFeatures(i).averageAngle - 270,'k-s','MarkerFaceColor','k');
hold on
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 画图部分结束-画出当前所有测试人员的角度特征曲线
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
for filnum = 1:Trainingfilenum % 画图部分-画出当前所有测试人员的角度特征曲线
% 注:这里给出最多画10人不同曲线的代码,由于曲线线条形状、颜色不同,采用switch语句来画
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%% %%%% 对应的周期角度特征曲线
switch filnum
case 1
figure('NumberTitle','off','Name','不同行人步态周期内角度特征');
title('不同行人左右分区角度特征比较');% 画出走势图
for i = 1:sectornums
plot(GaitFeatures(1).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'b-o','MarkerFaceColor','b');
hold on
end
case 2
for i = 1:sectornums
plot(GaitFeatures(2).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'g-x','MarkerFaceColor','g');
hold on
end
case 3
for i = 1:sectornums
plot(GaitFeatures(3).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'r-*','MarkerFaceColor','r');
hold on
end
case 4
for i = 1:sectornums
plot(GaitFeatures(4).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'c-p','MarkerFaceColor','c');
hold on
end
case 5
for i = 1:sectornums
title('不同行人左右分区角度特征比较');% 画出走势图
plot(GaitFeatures(5).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'k-s','MarkerFaceColor','k');
hold on
end
case 6
figure('NumberTitle','off','Name','步态角度特征');
title('不同行人左右分区角度特征比较');% 画出走势图
for i = 1:sectornums
plot(GaitFeatures(6).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'b-o','MarkerFaceColor','b');
hold on
end
case 7
for i = 1:sectornums
plot(GaitFeatures(7).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'g-x','MarkerFaceColor','g');
hold on
end
case 8
for i = 1:sectornums
plot(GaitFeatures(8).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'r-*','MarkerFaceColor','r');
hold on
end
case 9
for i = 1:sectornums
plot(GaitFeatures(9).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'c-p','MarkerFaceColor','c');
hold on
end
case 10
for i = 1:sectornums
title('不同行人左右分区角度特征比较');% 画出走势图
plot(GaitFeatures(10).nthsectorPeriodFeatures(i).PeriodaverageAngle - 270,'k-s','MarkerFaceColor','k');
hold on
end
end
%%%% %%%% 画图结束
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
end % 画图部分结束-画出当前所有测试人员的角度特征曲线
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 图像处理函数 测试
%
% 从二值轮廓图像,获取其轮廓的质心位置;并以质心为中心,建立坐标轴,求轮廓
% 从x坐标轴与轮廓边缘相交的交点为起点,逆时针旋转360°,计算每一个像素到
% 质心方向与x坐标轴的夹角以及每个像素到质心的距离
% 函数:
% [angle,centroid] = Outlinepixel2Centroid_Angle(logicalpic,sampletime)
% 参数:
% logicalpic —— 二值化轮廓图像 轮廓点为白色,即“1”
% sampletime —— 划分区域个数(采样点数)
% angle —— 轮廓点-质心与水平轴夹角
% distance —— 距离
% centroid —— 质心,数据格式为[行heigh,列weigh]
% nthsector —— 对每张图的第nth个分区数据集合,用于分析步态过程中对应分区的数据变化情况
%
% 注意:
% 该函数应当考虑极限位置,即下肢垂直时的分析!!
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function [nthsector,Outlinepixel,centroid] = test_Outlinepixel2Centroid_AngleDistance(logicalpic,sampletime)
%%%% %%%% %%%% %%%% 预处理
[height,width,picnums] = size(logicalpic); % 获取图片大小、张数
%%%% %%%% %%%% %%%% 第一步:求得各个质心
center = zeros(picnums,2);
for pn = 1:picnums
% 初始化参数
sum_x=0;sum_y=0;area=0;
for i=1:height
for j=1:width
if logicalpic(i,j,pn) == 1 % 轮廓像素点
sum_x = sum_x + i; % 记录轮廓像素点位置的总和
sum_y = sum_y + j;
area = area + 1; % 轮廓像素点个数
Outlinepixel(pn).position(area,1) = i; % 记录该幅图轮廓像素点位置,用于第二步使用
Outlinepixel(pn).position(area,2) = j; % 记录该幅图轮廓像素点位置,用于第二步使用
end
end
end
% 记录该幅图的轮廓像素个数
Outlinepixel(pn).pixelnums = area;
% 质心坐标
center(pn,1) = fix(sum_x/area); % height
center(pn,2) = fix(sum_y/area); % width
end
%%%% 获得质心位置
centroid = center;
%%%% %%%% %%%% %%%% 第二步:以质心为中心,求得下半身轮廓到各个质心与水平轴夹角,以及距离;这里求下半身!!
% 计算下半身分区角度区域
sectorangle = 180 / sampletime; % 下半身180°,总共分为sampletime块区域,每块区域角度范围为sectorangle
% 对每张图片进行处理
for pn = 1:picnums
pixeln = Outlinepixel(pn).pixelnums; % 读取当前图片所具有的像素个数
% 第一步:对每个像素进行查询,然后将其质心作为中心,对各个像素点求得新的坐标
for i = 1:pixeln
% 获取该图片中,第i个轮廓像素点的中心化位置。
% 坐标轴垂直向上为正,水平向右为左;但是像素点为从上到下-从左到右为增,所以中心化时,y轴处理特殊
Outlinepixel(pn).centralizationposition(i,1) = center(pn,1) - Outlinepixel(pn).position(i,1); % height
Outlinepixel(pn).centralizationposition(i,2) = Outlinepixel(pn).position(i,2) - center(pn,2); % width
end
% 第二步-1:划分各个区域,并初始化必要参数;并将像素点分类
for secs = 1:sampletime % 划分各个区域的角度范围;总共将人体下半身分为sampletime个分区;下半身以低于中心点的像素点
% 建立分区,初始化分区相关参数
Outlinepixel(pn).sampsector(secs).anglerange = 180 + secs * sectorangle; % 根据下半身所划分块个数,对下半身像素标记分区
Outlinepixel(pn).sampsector(secs).pixelnums = 0; % 该分区的像素个数
end
% 第二步-2:将每个像素点分类
for i = 1:pixeln
% 判断该点是否属于下半身轮廓像素点
lowerflog = Outlinepixel(pn).centralizationposition(i,1);
if lowerflog <= 0 % 如果该点属于下半身
% 以质心为原点,得到该下半身轮廓像素点的夹角
pixelheight = Outlinepixel(pn).centralizationposition(i,1); % 该像素的y
pixelwidth = Outlinepixel(pn).centralizationposition(i,2); % 该像素的x
pixelangle = 2*pi - acos( pixelwidth / (sqrt(pixelheight^2 + pixelwidth^2)) ); % 反余弦获得夹角
Outlinepixel(pn).pixelpiAngle(i,1) = pixelangle;
Outlinepixel(pn).pixelAngle(i,1) = 180*pixelangle/pi;
% 根据所需采样块数目建立分区,并分类
for secs = 1:sampletime % 划分各个区域的角度范围
% 当前像素的角度、距离
nowangle = Outlinepixel(pn).pixelAngle(i,1);
nowdista = norm( Outlinepixel(pn).centralizationposition(i,:) );
% 对该像素进行分区,如果该像素角度小于当前的角度范围,将该像素分为该区域
if nowangle <= Outlinepixel(pn).sampsector(secs).anglerange
% 记录当前分区像素个数
Outlinepixel(pn).sampsector(secs).pixelnums = Outlinepixel(pn).sampsector(secs).pixelnums + 1;
pnums = Outlinepixel(pn).sampsector(secs).pixelnums;
% 以质心为原点,记录该像素角度
Outlinepixel(pn).sampsector(secs).samppixelangle(pnums,1) = nowangle; % 将该像素放置对应分区中
% 以质心为原点,得到该像素距离
Outlinepixel(pn).sampsector(secs).samppixeldistance(pnums,1) = nowdista;
break; % 如果该像素已经划分至某个分区中,则中断循环 !!! 非常重要,该步骤会避免重复将该像素点进行分区
end
end
end
end
% 求得各个分区角度、距离均值
for secs = 1:sampletime
Outlinepixel(pn).sampsector(secs).pixelAveAngle = mean(Outlinepixel(pn).sampsector(secs).samppixelangle);
Outlinepixel(pn).sampsector(secs).pixelAveDistance = mean(Outlinepixel(pn).sampsector(secs).samppixeldistance);
% 对整个图集的各个扇区进行集合,用于用于分析步态过程中对应分区的数据变化情况
nthsector(secs).averageAngle(pn,1) = Outlinepixel(pn).sampsector(secs).pixelAveAngle;
nthsector(secs).averageDistance(pn,1) = Outlinepixel(pn).sampsector(secs).pixelAveDistance;
end
end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% end %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%