步态能量图生成主要有两步,主要为:
在原始轮廓图上对人的轮廓进行裁剪,在下面制作步态能量图图片叠加以什么为中心位置也是一个问题。。我这里采用的是中心位置为人体宽的一半。当然也可以以头为中心位置。如:下图为原始图像与裁剪后的图像
对裁剪后图像合成,一个步态周期的图像合成一个步态能量图,步态周期如何判断,网上有一些方法,这里直接是手动指定的。如下图为一个步态周期
合成的步态能量图为:
代码如下裁剪轮廓,存放到文件夹中,在通过裁剪的图生成GEI
原数据目录的格式为:
裁剪后的数据目录格式为:与原数据一样
生成步态能量图的数据的目录格式为:即同一个人的步态能量图放在一起。不管角度是多少
import os
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def cut_image(path,cut_path,size):
'''
将人的轮廓切割出来,并以相同的命名与目录格式存放到cut_path的文件夹中
:param path:原始图片的文件夹位置如"./silhoutettes"
:param cut_path:要存放切割后图片的文件夹位置如"./cut"
:param size:裁剪生成的图片大小
:return:
'''
# 若当前文件为.png或者.jpg图片,也可以为其他图片格式。需多加一个判断
if path.endswith('.png') or path.endswith('.jpg'):
# 获得切割后的图片,若图片不符合格式则跳过
image,flag = cut(Image.open(path))
if flag: return
# 存储图片
Image.fromarray(image).convert('L').resize((size,size)).save(cut_path)
return
for next_path in os.listdir(path):
# 递归,同时若要存放的目录不存在,则生成要存放的目录
if not os.path.exists(cut_path):
os.makedirs(cut_path)
cut_image(os.path.join(path,next_path),os.path.join(cut_path,next_path),size)
def cut(image):
'''
通过找到人的最小最大高度与宽度把人的轮廓分割出来,、
因为原始轮廓图为二值图,因此头顶为将二值图像列相加后,形成一列后第一个像素值不为0的索引。
同理脚底为形成一列后最后一个像素值不为0的索引。
人的宽度也同理。
:param image: 需要裁剪的图片 N*M的矩阵
:return: temp:裁剪后的图片 size*size的矩阵。flag:是否是符合要求的图片
'''
image = np.array(image)
# 找到人的最小最大高度与宽度
height_min = (image.sum(axis=1)!=0).argmax()
height_max = ((image.sum(axis=1)!=0).cumsum()).argmax()
width_min = (image.sum(axis=0)!=0).argmax()
width_max = ((image.sum(axis=0)!=0).cumsum()).argmax()
# 设置切割后图片的大小,为size*size,因为人的高一般都会大于宽
size=height_max-height_min
temp = np.zeros((size,size))
# 若宽大于高,则此图片为不符合要求的图片
flag = False
if size<=width_max-width_min:
flag = True
return temp,flag
# 将width_max-width_min(宽)乘height_max-height_min(高,szie)的人的轮廓图,放在size*size的图片中央
l = (width_max-width_min)//2
r = width_max-width_min-l
# centroid = np.array([(width_max+width_min)/2,(height_max+height_min)/2],dtype='int')
temp[:,(size//2-l):(size//2+r)] = image[height_min:height_max,width_min:width_max ]
return temp,flag
def GEI(cut_path,data_path,size,num=None):
"""
将切割后的轮廓图合成为步态能量图
:param cut_path:切割后的图片路径string如"./cut"
:param data_path:生成步态能量图的路径string如"./data"
:param size:步态能量图的大小,默认为整个文件夹
:param num:几张图片合成一张步态能量图
:return:
"""
# 获得人名
for name in os.listdir(cut_path):
cut_name_path = os.path.join(cut_path,name)
data_name_path = os.path.join(data_path,name)
k = 0;
if not os.path.exists(data_name_path):
os.makedirs(data_name_path)
# 读取角度文件夹中的图片
for degree in os.listdir(cut_name_path):
degree_path = os.path.join(cut_name_path,degree)
# 读取图片
imgs = [Image.open(os.path.join(degree_path,img)).convert('L') for img in os.listdir(degree_path)]
if num==None: num = len(imgs)
# 将图片以num个分组
imgs = [imgs[i:i+num] for i in range(0,len(imgs),num)]
# 合成一个步态能量图,记得除以每组图片的数量
for i in imgs:
GEI = np.zeros([size,size])
for j in i:
GEI +=j
GEI = GEI/len(i)
Image.fromarray(GEI).convert('L').resize((size,size)).save(os.path.join(data_name_path,str(k)+'.png'))
k = k+1
pass
if __name__=='__main__':
# 裁剪轮廓
cut_image('./silhouettes','./cut',64)
# 生成GEI
GEI('./cut','./data',64,num=16)
原文:https://www.cnblogs.com/lolybj/p/10914957.html