免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 6670 | 回复: 13

大量序列帧扫描 [复制链接]

论坛徽章:
0
发表于 2014-01-16 08:19 |显示全部楼层
20可用积分
本帖最后由 liaozd 于 2014-01-16 08:47 编辑

文件目录大致可能是这样:

folder1
    |-----name0000.jpg
    |-----name0000.tif
    |-----name0001.jpg
    |-----name0001.tif
    |-----....   
    |-----....
    |-----name2000.jpg
    |-----name2000.tif
    |-----name2004.tif
    |-----name2501.tif
    |-----....
    |-----name2845.tif
    |-----other_file.txt
    |-----folder2
                 |-----name0000.jpg
                 |-----name0000.tif
                 |-----name0001.jpg
                 |-----name0001.tif
                 |-----....   
                 |-----....
                 |-----name2000.jpg
                 |-----name2000.tif
                 |-----other_file2.sh
说明:

  序列帧不限于仅仅是jpg或tif,还可能有dpx或exr
  目录里面会有多级子目录
  总帧数可能会上万,所以扫描速度是个问题

我怎么能够得到这样输出结果?

输出结构:
  folder1: name0000-2000.jpg, 340MB
  folder1: name0000-2000.tif, 1GB
  folder1: name2004-2845.tif, 500MB
  folder1: other_file.txt, 1k
  folder1/folder2: name0000-2000.jpg, 340MB
  folder1/folder2: name0000-2000.tif, 1GB
  folder1/folder2: other_file2.sh, 45byte


最佳答案

查看完整内容

回复 1# liaozd 主要功能OK,代码的注释和文档说明了实现细节。另外,在程序正确运行之前,过早优化性能是多余且有害的。在safari/chrome里,CU的代码标签有问题,代码以我附件内容为准。保存为test.py,运行:

论坛徽章:
11
技术图书徽章
日期:2014-03-01 14:44:34天蝎座
日期:2014-05-21 22:11:59金牛座
日期:2014-05-30 17:06:14
发表于 2014-01-16 08:19 |显示全部楼层
本帖最后由 timespace 于 2014-01-17 10:46 编辑

回复 1# liaozd
主要功能OK,代码的注释和文档说明了实现细节。另外,在程序正确运行之前,过早优化性能是多余且有害的。
在safari/chrome里,CU的代码标签有问题,代码以我附件内容为准。
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-

  3. import itertools
  4. import os
  5. import re
  6. import sys
  7. from os.path import getsize, isdir, isfile, join, splitext

  8. class KeyTracker(object):
  9.     """有状态的KEY生成器。
  10.    
  11.     给定一个KEY,保存对应一组序列中的两个字段:
  12.      -- 第一个记录
  13.      -- 当前迭代的上一个记录
  14.     """
  15.     def __init__(self):
  16.         self.start = self.prev = None

  17.     def key(self, e):
  18.         if self.prev is not None and \
  19.                 self.prev[1] == e[1] and \
  20.                 self.prev[2] == e[2] and \
  21.                 self.prev[3] is not None and \
  22.                 int(self.prev[3]) + 1 == int(e[3]):
  23.             self.prev = e
  24.             return self.start[1:]
  25.         else:
  26.             self.start = self.prev = e
  27.             return e[1:]
  28. def main():
  29.     if len(sys.argv) != 2 or not isdir(sys.argv[1]):
  30.         sys.exit(sys.argv[0] + ' target_dir')

  31.     target = sys.argv[1]
  32.     # alphanum = ......  这行内容与CU的代码标签冲突,以附件内容为准。
  33.     for root, dirs, files in os.walk(target):
  34.         # 为了后续排序和分类方便,将文件名扩展为如下tuple数组
  35.         # dummy_files = [(完整文件名, 扩展名, 文件名前缀,文件名数字后缀), ...]
  36.         # 例如'name0012.jpg'会转换为('name0012.jpg', '.jpg', 'name', '0012')
  37.         # 例如'test.sh'会转换为('test.sh', '.sh', 'test', None)
  38.         dummy_files = []
  39.         for name in files:
  40.             prefix, ext = splitext(name)
  41.             res = alphanum.match(prefix)
  42.             if res is None:
  43.                 dummy_files.append(tuple([name, ext, prefix, None]))
  44.             else:
  45.                 dummy_files.append(tuple([name, ext, res.group(1), res.group(2)]))

  46.         # 以(扩展名, 文件名前缀,文件名数字后缀)为key进行排序,
  47.         # 而tuple隐含的排序规则就是按字段顺序优先级递减,正好符合需求。
  48.         dummy_files.sort(key=lambda e: e[1:])

  49.         # 对数组元素分类,‘文件名数字后缀’连续的文件需合并, 是一个有状态key,
  50.         # 此处groupby的key隐含的排序稳定性必须与上述的sort一致。
  51.         groupkey = KeyTracker()
  52.         for k,g in itertools.groupby(dummy_files, key=groupkey.key):
  53.             total_size = 0
  54.             for idx, item in enumerate(g):
  55.                 filename = join(root, item[0])
  56.                 if isfile(filename):
  57.                     total_size += getsize(filename)
  58.             name = item[0] if idx == 0 else '{}{}-{}{}'.format(k[1], k[2], item[3], k[0])
  59.             print '{}: {}, {} bytes'.format(root, name, total_size)

  60. if __name__ == '__main__':
  61.     main()
  62.                      
复制代码
保存为test.py,运行:
  1. bash-3.2 $python --version
  2. Python 2.7.5
  3. bash-3.2 $./test.py folder1/
  4. folder1/: name01-02.jpg, 69 bytes
  5. folder1/: name01-02.tif, 16 bytes
  6. folder1/: name10-12.tif, 36 bytes
  7. folder1/: file.txt, 16 bytes
复制代码

test.py.gz

1.23 KB, 下载次数: 1763

论坛徽章:
33
荣誉会员
日期:2011-11-23 16:44:17天秤座
日期:2014-08-26 16:18:20天秤座
日期:2014-08-29 10:12:18丑牛
日期:2014-08-29 16:06:45丑牛
日期:2014-09-03 10:28:58射手座
日期:2014-09-03 16:01:17寅虎
日期:2014-09-11 14:24:21天蝎座
日期:2014-09-17 08:33:55IT运维版块每日发帖之星
日期:2016-04-17 06:23:27操作系统版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-24 06:20:0015-16赛季CBA联赛之天津
日期:2016-05-06 12:46:59
发表于 2014-01-16 09:42 |显示全部楼层
基本上就是个 目录的 io 操作, 能不能快, 看你的硬盘了.

论坛徽章:
0
发表于 2014-01-16 09:46 |显示全部楼层
用GO语言吧。。。。嘿嘿

论坛徽章:
4
白羊座
日期:2013-11-05 10:26:09冥斗士
日期:2015-11-17 14:19:55白银圣斗士
日期:2015-11-17 15:13:0815-16赛季CBA联赛之新疆
日期:2016-04-01 09:10:58
发表于 2014-01-16 09:57 |显示全部楼层
回复 1# liaozd


    可以考虑使用 os.walk() 来得到所有项进行遍历。
    这时需要做的就是:
    1. 根据你需要的文件扩展名进行过滤
    2. 记录文件的路径、文件、大小信息。

论坛徽章:
0
发表于 2014-01-16 10:16 |显示全部楼层
我想过难度可能在这里:“文件名.扩展名”,先进性一次排序,文件名相同但扩展名不同的会混在一起,我可能还需要对扩展名进行二次排序,这样好像非常影响速度。

论坛徽章:
4
白羊座
日期:2013-11-05 10:26:09冥斗士
日期:2015-11-17 14:19:55白银圣斗士
日期:2015-11-17 15:13:0815-16赛季CBA联赛之新疆
日期:2016-04-01 09:10:58
发表于 2014-01-16 10:39 |显示全部楼层
本帖最后由 icymirror 于 2014-01-16 10:41 编辑

回复 5# liaozd


    可以考虑把允许的扩展名写入到一个 dict 或者 set, 然后用 index 等方法来确定是否存在来(写成一个函数对一个文件名进行扩展名过滤)。
    然后,把这个方法用 map 或者 filter 来映射到数据集上进行过滤。
    同时,这种方式决定了不需要排序之类的过程。

论坛徽章:
4
金牛座
日期:2013-10-11 16:12:50卯兔
日期:2014-07-31 09:17:19辰龙
日期:2014-08-08 09:28:02狮子座
日期:2014-09-14 20:32:05
发表于 2014-01-16 10:39 |显示全部楼层
回复 5# liaozd


    不太明白,为什么要对扩展名进行二次排序呢?先排序,然后以扩展名为键值作一个字典,记录文件名,文件名自然就是已经排好的顺序。而且排序又很快,跟读取文件信息花的时间相比,排序还是比较快的。

论坛徽章:
33
荣誉会员
日期:2011-11-23 16:44:17天秤座
日期:2014-08-26 16:18:20天秤座
日期:2014-08-29 10:12:18丑牛
日期:2014-08-29 16:06:45丑牛
日期:2014-09-03 10:28:58射手座
日期:2014-09-03 16:01:17寅虎
日期:2014-09-11 14:24:21天蝎座
日期:2014-09-17 08:33:55IT运维版块每日发帖之星
日期:2016-04-17 06:23:27操作系统版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-24 06:20:0015-16赛季CBA联赛之天津
日期:2016-05-06 12:46:59
发表于 2014-01-16 10:40 |显示全部楼层
回复 5# liaozd


不需要排两次.

以目录为单位来处理, glob 就可以拿到所有的当前目录下的目录和文件, 只处理目录下的文件, 子目录调用函数继续处理.

每个文件名存入以扩展名为名的数组, 然后, 排序一次这个数组就可以了. 之后对排序后的数组做处理, stat 每个文件的大小, 把名字连续的文件的大小加起来就行了.

效率还真是说不上怎么快.  如果你的硬盘够好, 建议用多进程来处理吧. 使用中间文件来交换信息.

论坛徽章:
0
发表于 2014-01-16 11:06 |显示全部楼层
回复 3# xmchenb

go做这个会容易一些么?

   
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP