步態能量圖生成主要有兩步,主要為:
-
在原始輪廓圖上對人的輪廓進行裁剪,在下面制作步態能量圖圖片疊加以什么為中心位置也是一個問題。一般有兩種方式,一種是中心位置為人體寬的一半。另一種是以頭頂為中心位置。如:下圖為原始圖像與裁剪后的圖像
為人體寬一般為中心位置
以頭頂為中心位置
-
對裁剪后圖像合成,一個步態周期的圖像合成一個步態能量圖,步態周期如何判斷,網上有一些方法,這里直接是手動指定的。如下圖為一個步態周期
以身寬一般為中心合成的步態能量圖為:
以頭頂為中心合成步態能量圖為:
可以看出以頭頂為中心效果比較好
代碼如下裁剪輪廓,存放到與原文件夾相同格式的文件目錄中,在通過裁剪的圖生成GEI
以CISIA-B數據集為例,原文件目錄格式為
生成的剪切圖
生成的一張步態能量圖
這里以一個整個步態序列作為周期
import os
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
def cut_image(path,cut_path,size):
'''
剪切圖片
:param path: 輸入圖片路徑
:param cut_path: 剪切圖片后的輸出路徑
:param size: 要剪切的圖片大小
:return:
'''
for (root,dirs,files) in os.walk(path):
temp = root.replace(path,cut_path)
if not os.path.exists(temp):
os.makedirs(temp)
for file in files:
image,flag = cut(Image.open(os.path.join(root,file)))
if not flag: Image.fromarray(image).convert('L').resize((size,size)).save(os.path.join(temp,file))
pass
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()
head_top = image[height_min,:].argmax()
# 設置切割后圖片的大小,為size*size,因為人的高一般都會大於寬
size=height_max-height_min
temp = np.zeros((size,size))
# 將width_max-width_min(寬)乘height_max-height_min(高,szie)的人的輪廓圖,放在size*size的圖片中央
# l = (width_max-width_min)//2
# r = width_max-width_min-l
# 以頭為中心,將將width_max-width_min(寬)乘height_max-height_min(高,szie)的人的輪廓圖,放在size*size的圖片中央
l1 = head_top-width_min
r1 = width_max-head_top
# 若寬大於高,或頭的左側或右側身子比要生成圖片的一般要大。則此圖片為不符合要求的圖片
flag = False
if size<=width_max-width_min or size//2<r1 or size//2<l1:
flag = True
return temp,flag
# centroid = np.array([(width_max+width_min)/2,(height_max+height_min)/2],dtype='int')
temp[:,(size//2-l1):(size//2+r1)] = image[height_min:height_max,width_min:width_max ]
return temp,flag
def GEI(cut_path,data_path,size):
'''
生成步態能量圖
:param cut_path: 剪切后的圖片路徑
:param data_path: 生成圖片的路徑
:param size: 生成能量圖大小
:return:
'''
for (root,dirs,files) in os.walk(cut_path):
temp = root.replace(cut_path,data_path)
if not os.path.exists(temp):
os.makedirs(temp)
GEI = np.zeros([size,size])
if len(files)!=0:
for file in files:
GEI += Image.open(os.path.join(root,file)).convert('L')
GEI /= len(files)
Image.fromarray(GEI).convert('L').resize((size,size)).save(os.path.join(temp,'1.png'))
pass
if __name__=='__main_':
cut_image("C:\\Users\\China\\Desktop\\GaitDatas","C:\\Users\\China\\Desktop\\CutImage",126)
GEI("C:\\Users\\China\\Desktop\\CutImage","C:\\Users\\China\\Desktop\\GEIData",126)