zoukankan      html  css  js  c++  java
  • NDK学习笔记(四):OutputContext机制

    首先NDK文档中的Op.h头文件中已经有了相关概念的解释,摘录翻译如下:

          /*! fn const OutputContext& Op::outputContext() const;
             The current context that this Op is supposed to produce a picture
             for. This includes the frame number, the view, etc.
           */
          const OutputContext& outputContext() const { return outputContext_; }
    

     即当前Op进行图像处理的一个实时环境,这个环境包括了帧数,视角(包括main视角,left视角,right视角,等)。

    Op会对当前帧的画面进行处理,通过_validate()方法去确认图像相关信息,通过Knobs机制去读取工程文件中的属性参数并存储到knobs中,通过_requenst()去逐行请求图像信息,继而通过engine()方法综合现有数据进行图像处理。这是Op的一个简单的机制,一个Op实例只能处理一幅画面。那么Op该处理哪一帧图像呢?处理这一帧图像的哪一个视角呢(exr图像的header表中会记录视角信息)?这一切都由OutputContext机制决定。该机制会更早于Op属性实例化。OutputContext()机制启动后确定处理环境后才会实例化Op来进行下一步工作。

    下面分析几个案例来解释这个机制:

    默认的split_input()和OutputContext()方法是这样的:

    virtual int split_input(int inputNo) const
    {
      return 1;
    }
    
    virtual const OutputContext& inputContext(int n, int offset, OutputContext& oc) const
    {
      return outputContext();
    }
    

    一:

    如果你希望input arrow在时间轴上的任何帧上都只进入第一帧(例如FrameHold),那么你需要这样重定义:

    virtual const OutputContext& inputContext(int n, int offset, OutputContext& oc) const {
      oc = outputContext();
      oc.frame(1);
      return oc;
    }
    

     第二行表示oc指向当前已经存在outputContext(),inputContext()方法中这样指认实际上表示inputContext()与outputContext()一致,即:输入哪一帧,处理哪一帧。第三行显式的为oc赋值1,表示无论何时只输入第一帧。第四行返回修改后的oc对象。

    通过这种方式即可实现framehold的效果,无论时间轴怎样拖动,只显示指定的某一帧。

    二:

    如果你有一个Op想使用两个以上的输入帧来进行操作(比如FrameBlend),那你就需要重新定义split_input()。

    virtual int split_input(int inputNo) const
    {
      if (inputNo == 0)
        return 2;
      return 1;
    }
    
    virtual const OutputContext& inputContext(int n, int offset, OutputContext& oc) const
    {
      oc = outputContext();
      if (inputNo == 0 && offset == 1)
        oc.frame(oc.frame() + 1);
      return oc;
    }
    

     第一个方法表示将第一个input arrow分出两个子input,每个input对应一个独立Op;第二个方法表示在第二个子input上输入下一帧的内容。即input(0,1)对应的Op处理input(0,0)应对Op处理帧的下一帧。这样就是在input(0)上同时处理生成两个Op来进行串帧处理了。inputContext(int n,int offset,OutputContext&oc)中n代表当前帧,offset代表当前input下的子input,oc表示当前outputContext()对象。

    三:

    virtual int split_input(int inputNo) const
    {
      return 11;
    }
    
    virtual const OutputContext& inputContext(int n, int offset, OutputContext& oc) const
    {
      oc = outputContext();
      oc.frame(oc.frame() - 5 + offset);
      return oc;
    }
    

     在这个案例中通过split_input()方法为每个input定义了11个子inputs,目的是为每一个input都生成11个op,在每一帧都调用附近的11帧来生成图像。之后又定义了inputContext()方法,该方法继承了outputContext()方法,之后将当前帧向前偏移5帧,以oc.frame()-5为基准来添加offset,offset范围为0-10,这样就会生成oc.frame()-5到oc.frame()+5这个范围的input。每一帧的计算都会调用这个范围的input数据。通过这种结构,engine机制能够很容易的生成多帧混合图像。

    但是这个机制有个缺陷,我们的原素材范围framerange假设为[1-100],经过这个机制之后framerange就变成[-4,105]了,这样会造成不必要的读写,于是nuke引入一个新的机制inputUIcontext().该机制同样继承自outputContext(),目的是在修复inputContext产生的帧数范围错误。我们只需要重新定义一下该函数即可:

    virtual const OutputContext* inputUIContext(int n, OutputContext&) const
    {
      return &outputContext();
    }
    

     这样就可以将错误的范围重新指认回原来的应该的帧数范围了。

    通过这OutputContext机制的这三个方法可以很轻松的解决时间线上多帧操作的问题,nuke的程序思路非常明确:

    一个input对应一个op,多帧运算就实例化多个op,在engine方法中构建对应于多个input的row即可。

    例如:

    void TemporalMedian::engine ( int y, int x, int r,
                                  ChannelMask channels, Row& row )
    {
      row.get(input0(), y, x, r, channels);
      Row prevrow(x, r);
      Row nextrow(x, r);
      prevrow.get(input1(), y, x, r, channels);
      nextrow.get(*input(2), y, x, r, channels);
    

     该例子中就实例化了三个input,即:input0(),input1(),*input(2),每一个input的读写row实例即:row,preview,nextrow。

    总结一下:

    学习到这里Nuke的读写运算机制就很清晰了,剩下的就是算法移植了。希望自己的数学底子不要拖后腿。勤能补拙,再接再厉。

  • 相关阅读:
    Spring MVC 3.0.5+Spring 3.0.5+MyBatis3.0.4全注解实例详解(四)
    中国B2B行业将进入后平台时代
    做产品经理 而不是功能经理(转淘宝鬼脚七)
    全球最值的学习的100个网站
    gridview 内的button 用法
    框架内 FRAME的源src如何根据条件而变化?C#解决方案
    一般中小企网络出口的后备线路(adsl做后备)
    Windows server 2012_远程_没有远程桌面授权服务器可以提供许可证
    访问网站返回常见的状态码200,404等表示什么意思(转)
    站长学习 一 Robots简单认识
  • 原文地址:https://www.cnblogs.com/hksac/p/5052099.html
Copyright © 2011-2022 走看看