zoukankan      html  css  js  c++  java
  • GEI步态能量图生成

    步态能量图生成主要有两步,主要为:

    1. 在原始轮廓图上对人的轮廓进行裁剪,在下面制作步态能量图图片叠加以什么为中心位置也是一个问题。一般有两种方式,一种是中心位置为人体宽的一半。另一种是以头顶为中心位置。如:下图为原始图像与裁剪后的图像

      为人体宽一般为中心位置

      以头顶为中心位置

    2. 对裁剪后图像合成,一个步态周期的图像合成一个步态能量图,步态周期如何判断,网上有一些方法,这里直接是手动指定的。如下图为一个步态周期

      以身宽一般为中心合成的步态能量图为:

      以头顶为中心合成步态能量图为:

      可以看出以头顶为中心效果比较好

    代码如下裁剪轮廓,存放到与原文件夹相同格式的文件目录中,在通过裁剪的图生成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)
    

    更新:以重心为中心合成GEI(论文常用方式)

    import os
    from PIL import Image
    import numpy as np
    
    
    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[1],size[0])).save(os.path.join(temp,file))
    
        pass
    def cut(image):
        '''
        以重心为中心合成GEI
        通过找到人的最小最大高度与宽度把人的轮廓分割出来,、
        因为原始轮廓图为二值图,因此头顶为将二值图像列相加后,形成一列后第一个像素值不为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))
        #计算质心
        N = np.sum(image!=0)
        Xy = 0
        for i in range(image.shape[0]):
            Xy += np.sum(image[i,:]!=0)*i
        Xy = Xy//N
        Xc = 0
        for i in range(image.shape[1]):
            Xc += np.sum(image[:, i] != 0) * i
        Xc = Xc // N
        centroid = (Xc,Xy)
        l1 = Xc-int(size*11/16/2)
        r1 = Xc+int(size*11/16/2)
        # 若宽大于高,或头的左侧或右侧身子比要生成图片的一般要大。则此图片为不符合要求的图片
        flag = False
        if l1>width_min or l1<0 or r1<width_max or r1>image.shape[1]:
            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 ]
        temp = image[height_min:height_max,l1:r1]
        #print((r1-l1)/size,temp.shape[1]/temp.shape[0],11/16)
        #若图片像素值过少,则图片也不合格
        print(image.sum())
        if image.sum()<5000:
            flag = False
        return temp,flag
    
    def GEI(cut_path,data_path,size,batch=None,strides=None):
        '''
        生成步态能量图,若batch或strides为None则将整个序列合成一GEI
        :param cut_path: 剪切后的图片路径
        :param data_path: 生成图片的路径
        :param size: 生成能量图大小
        :param batch: 多少张图片合成一张步态能量图
        :param strides: 合成GEI的步长
        :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)
            if batch==None or strides==None:
                batch_ = len(files)
                strides_ = len(files)
            else:
                batch_ = batch
                strides_ = strides
            #图片多余10张才生成GEI
            if len(files)>10:
                print(len(files))
                files.sort()
                k = len(os.listdir(temp))
                for i in range(0,len(files),strides_):
                    if i+batch_>len(files):
                        break
                    GEI = np.zeros(size)
                    for file in files[i:i+batch_]:
                        GEI += Image.open(os.path.join(root, file)).convert('L')
                    GEI /= batch_
                    Image.fromarray(GEI).convert('L').save(os.path.join(temp, str(k)+'.png'))
                    k += 1
        pass
    
    
    # cut_image(r'D:gaitDatasetsGaitDatas08',r'D:gaitDataCut_Caps_64_44_',(126,126))
    GEI(r'D:gaitDataCut_Caps_64_44_',r'D:oke_GEI',(64,44))
    
  • 相关阅读:
    利用Java脚本实现弹出窗口后,按确定实现跳转
    客服利用QQ实现即时聊天
    获取页面可见区域,屏幕区域的尺寸
    圆角模板百度知道
    利用javascript实现web页面刷新的方法
    论:命名空间,程序集和类
    我从少年时候就非常喜欢的诗歌:雨巷
    魔兽世界 圣骑士唯一的远程武器任务
    又想起我年少时候熟记的抒情诗致海伦
    System.Text.Encoding.UTF8 字符串和字节数组的互相转换
  • 原文地址:https://www.cnblogs.com/lolybj/p/10914957.html
Copyright © 2011-2022 走看看