Going from 2D to 3D

We start with:

  • For each velocity channel, a set (python dictionary) of pre-processed masks. We call the container for these masks and their corners nodes.

  • An overlap threshold.

  • We also reserve an empty dictionary to store the 3D trees built from these nodes.

We go through each velocity channel and its associated set of nodes in order:

  • On the first velocity channel we go through all of the nodes and initialize a new tree for each node (there are no existing tree as this moment).

  • For all subsequent velocity channels we:

    • Go through all of the nodes, for each node we try to match it to an existing tree:

      • To match, we take the dictionary of existing, non-terminated tree, for each tree, we:

        1. Compare the mask overlap between the current node and the last node on the tree (the “last node” on the tree has to be on the previous velocity channel). The comparison is a “two way” comparison - we first create a combined (bit-wise AND) overlap mask between the current node and the last node on the tree we’re trying to match to, then compute the overlap fraction for both the (combined mask, current node) pair and the (combined mask, last node on the tree) pair. If the overlap fraction for either pair is greater than our overlap threshold, we consider it to be a match and append the current node onto the tree.

        2. We do this for each existing tree, regardless if the current node has already matched with a tree - this means that a given node can match to multiple tree.

        3. This also means that multiple nodes can match to a given tree. If this does happen (we match the current node to a given tree that has already matched with another node on the current velocity channel), instead of appending the current node onto the given tree, we merge the current node with the other node on the current velocity channel that has also matched with the given tree before doing the append. This is so that, on each velocity channel of the tree, we have a “unified” mask.

  • If, after all of this, no match is found for the current node, we initialize a new tree from the node.

  • Delete all of the terminated trees of length 1 (trees that were initialized by an unmatched node but didn’t match with any node in the next immediate velocity channel). This is to minimize the running number of tree we are actively trying to match new nodes onto.