【问题标题】:a lil bit of programming math一点编程数学
【发布时间】:2012-05-22 00:08:13
【问题描述】:

只是想知道是否有人可以帮助我解决一些我遇到问题的编程数学问题。

我正在尝试为 Nuke (vfx) 创建一个提交脚本(使用 python 和 .bat)。我遇到的问题是我无法弄清楚如何将剩余的帧添加到已计算的堆栈中。

为了更清楚...

在 Nuke 中,我必须渲染 20 帧。我有 16 个线程。 Nuke 仅使用 1 个线程。我想编写一个脚本,它需要帧数并将其除以线程数,然后使用 python 写出一个 bat 文件。问题来了,当我有剩余时。我想取出剩余部分并将其应用回渲染堆栈。

示例(第一个循环)

thread1 = 1 frame
thread2 = 1 frame
thread3 = 1 frame
thread4 = 1 frame
thread5 = 1 frame
thread6 = 1 frame
...
thread16 = 1 frame

完成此操作后...余数为 4。我希望将余数分配给线程。 所以...

示例(第二个循环)

thread1 = 2 frame
thread2 = 2 frame
thread3 = 2 frame
thread4 = 2 frame
thread5 = 1 frame
thread6 = 1 frame
...
thread16 = 1 frame

这 4 个被添加到前几个线程中,总共 20 帧。

我将非常感谢任何人提供的任何帮助、提示和 cmets。 :)

谢谢

【问题讨论】:

    标签: python animation math nuke


    【解决方案1】:

    这是Bresenham algorithm的经典用法:

    def partition(lst, n):
        increment = len(lst) / float(n)
        last = 0
        i = 1
        results = []
        while last < len(lst):
            idx = int(round(increment * i))
            results.append(lst[last:idx])
            last = idx
            i += 1
        return results
    
    
    for i, frames in enumerate(partition(range(20),16)):
        if len(frames)>1:
            print 'thread'+str(i+1),'=', len(frames),'frames'
        else:
            print 'thread'+str(i+1),'=', len(frames),'frame'
    

    分区位来自this answer

    打印出来:

    thread1 = 1 frame
    thread2 = 2 frames
    thread3 = 1 frame
    thread4 = 1 frame
    thread5 = 1 frame
    thread6 = 2 frames
    thread7 = 1 frame
    thread8 = 1 frame
    thread9 = 1 frame
    thread10 = 2 frames
    thread11 = 1 frame
    thread12 = 1 frame
    thread13 = 1 frame
    thread14 = 2 frames
    thread15 = 1 frame
    thread16 = 1 frame
    

    如果您不介意前面加载两个框架线程,也可以使用Mark Dickinson's solution

    那么你有:

    def partition(lst, n):
        q, r = divmod(len(lst), n)
        indices = [q*i + min(i, r) for i in xrange(n+1)]
        return [lst[indices[i]:indices[i+1]] for i in xrange(n)]
    

    哪个打印:

    thread1 = 2 frames
    thread2 = 2 frames
    thread3 = 2 frames
    thread4 = 2 frames
    thread5 = 1 frame
    thread6 = 1 frame
    thread7 = 1 frame
    thread8 = 1 frame
    thread9 = 1 frame
    thread10 = 1 frame
    thread11 = 1 frame
    thread12 = 1 frame
    thread13 = 1 frame
    thread14 = 1 frame
    thread15 = 1 frame
    thread16 = 1 frame
    

    【讨论】:

      【解决方案2】:

      frames 可以是任何对象的列表,例如dict 或“Frame”对象。这里我刚刚使用了ints

      >>> frames = range(20)
      >>> threads = 16
      >>> [frames[x::threads] for x in range(threads)]
      [[0, 16], [1, 17], [2, 18], [3, 19], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15]]
      

      我认为您最好将帧放在 Queue 中,因为有些帧可能比其他帧渲染得更快

      【讨论】:

      • 我很想设置一个队列,但我不知道如何:(。
      • 我从未见过以这种格式编写的 python。 [frames[x::threads] for x in range(threads)].
      • @に か,这只是一个列表理解。你不明白哪一部分?
      • 哦..我的意思是我不知道如何排队。我想要做的是让 Nuke 一次渲染多个帧。 Nuke 只使用 1 个线程……我想……所以我正在创建这个脚本,它将在 nuke 中使用一个“写入”节点并进行数学运算……并写出 bat 文件并立即执行它们。它是一个黑客,但....我没有更好的方法。
      • 您介意用另一种方式重写您的示例吗...我无法阅读它...请:)
      【解决方案3】:
      frames=20
      tPos=16
      Ts=divmod(frames,tPos)
      threads=[Ts[0]+1 if i < Ts[1] else Ts[0] for i in range(tPos)]
      
      >>> threads    
      >>> [2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
      

      如果您在列表推导方面遇到问题,可以这样写:

      threads=[]
      for i in range(tPos):
          threads.append(Ts[0]+1 if i<Ts[1] else Ts[0])
      

      然后要格式化它,请执行以下操作:

      for i,e in enumerate(threads):
          print 'thread{} {}frames'.format(i,e)
      

      【讨论】:

      • 就像一个插件......我如何将结果格式化为渲染标志......意思是......渲染使用格式“-f帧范围”。例如:
        thread1 2frames~ "1-2" thread2 2frames~ "3-4" thread3 2frames~ "5-6" thread4 2frames~ "7-8" thread5 1frames~ "9-9" thread6 1frames~ "10-10" thread7 1frames~ "11-11" thread8 1frames~ "12-12" ...
      • @に か: Google python string concatenationpython string templatepython string format 您将遍历我创建的列表threads,并使用列表中的值创建每个字符串。我无法从您的评论中更具体地告诉您您想要什么。
      【解决方案4】:

      这就是我最终使用的......谢谢大家的帮助。

      frames=20 
      tPos=16 
      Ts=divmod(frames,tPos) 
      threads=[] 
      for i in range(tPos): 
          threads.append(Ts[0]+1 if i<Ts[1] else Ts[0])
      
      start = 1
      end = 0
      x=1
      while x <= (tPos):
          end = start +(threads[x-1]-1)
          print (start, "-", end)
          start = end + 1
          x+=1
      
      
      prints:
      1 - 2
      3 - 4
      5 - 6
      7 - 8
      9 - 9
      10 - 10
      11 - 11
      12 - 12
      13 - 13
      14 - 14
      15 - 15
      16 - 16
      17 - 17
      18 - 18
      19 - 19
      20 - 20
      

      【讨论】:

        猜你喜欢
        • 2012-03-15
        • 2021-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-22
        • 1970-01-01
        相关资源
        最近更新 更多