Page 1 of 1

Manipulating pixels flow in optical flow.

PostPosted: Sat May 15, 2021 1:08 pm
by birdseye
I'm comparing optical flow with Avid's Fluidmotion which I'm a bit more familiar with. I have found Fluidmotion to be slightly faster (at least the first render) but optical flow is slightly less prone to artifacts in difficult regions of the frame and optical flow is much faster if the speed is re adjusted, as Fluidmotion needs to recalculate the vectors between each frame.
One feature I don't see in optical flow is the ability to correct/manipulate the flow of pixels. In Fluidmotion this is made possible by using a feature based on the position of colours in the colour wheel. In this mode all the pixels in a frame are coloured according to their change of position from one frame to the next. Regions in each frame can be isolated, which removes their colour (and so their motion) and then an eye dropper can be used to determine a new direction of travel for that region of pixels.
The only way I can think of to emulate this in Fusion, is using Gridwarps and masks. Is there a way to influence pixel flow in optical flow or a more suitable node or method than Gridwarps and masks.

Re: Manipulating pixels flow in optical flow.

PostPosted: Sat May 15, 2021 4:58 pm
by Bryan Ray
Interesting. The vectors are, of course, merely pixel values, so any manipulations you could do to RGB you can also do to vx and vy. To isolate a "vector region," for lack of better terminology, you could do something like CopyAux the vectors into RGB and then use your choice of keyer to select vectors matching that direction. Then you could use color corrections, or Merges with Backgrounds, or Paint, or whatever suits your fancy, to alter the selected region. Then ChannelBooleans back into the vector channel.

Looking for trouble in that workflow, I think it would be easiest if the vectors were normalized, so you'd need to offset and rescale them back to their original range when you're done. If this is something you do a lot, it would probably be a good idea to make a macro with some expression links between the Min and Max sliders in CopyAux and a CustomTool to un-remap the vectors.

This was a fun exercise, and I can see it being useful in the future. Thanks!

Code: Select all
{
   Tools = ordered() {
      OpticalFlow1 = Dimension.OpticalFlow {
         Inputs = {
            Method = Input { Value = FuID { "Advanced" }, },
         },
         ViewInfo = OperatorInfo { Pos = { 275, 16.5 } },
      },
      CopyAux1 = Dimension.CopyAux {
         Inputs = {
            Channel = Input { Value = FuID { "Vector" }, },
            ["Vector.Remap.Enable"] = Input { Value = 1, },
            ["Vector.Remap.From.MinX"] = Input { Value = -11.672646522522, },
            ["Vector.Remap.From.MaxX"] = Input { Value = 18.7788524627686, },
            ["Vector.Remap.From.MinY"] = Input { Value = -6.4090633392334, },
            ["Vector.Remap.From.MaxY"] = Input { Value = 11.1418828964233, },
            Input = Input {
               SourceOp = "OpticalFlow1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 385, 16.5 } },
      },
      ChromaKeyer1 = ChromaKeyer {
         Inputs = {
            RedLow = Input { Value = 0.567502379417419, },
            RedHigh = Input { Value = 0.617468476295471, },
            GreenLow = Input { Value = 0.481564193964005, },
            GreenHigh = Input { Value = 0.520915150642395, },
            BlueLow = Input { Value = 0.296968758106232, },
            BlueHigh = Input { Value = 0.334112018346786, },
            LuminanceLow = Input { Value = 0.36242687702179, },
            LuminanceHigh = Input { Value = 0.443495869636536, },
            SoftRange = Input { Value = 0.0142, },
            FringeSize = Input { Value = 0, },
            Filter = Input { Value = FuID { "Fast Gaussian" }, },
            InvertMatte = Input { Value = 1, },
            Input = Input {
               SourceOp = "CopyAux1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 550, -16.5 } },
      },
      ColorCorrector1 = ColorCorrector {
         Inputs = {
            Channel = Input { Value = 1, },
            MasterRedBrightness = Input { Value = -0.14, },
            ColorRanges = Input {
               Value = ColorCurves {
                  Curves = {
                     {
                        Points = {
                           { 0, 1 },
                           { 0.4, 0.2 },
                           { 0.6, 0 },
                           { 1, 0 }
                        }
                     },
                     {
                        Points = {
                           { 0, 0 },
                           { 0.4, 0 },
                           { 0.6, 0.2 },
                           { 1, 1 }
                        }
                     }
                  }
               },
            },
            HistogramIgnoreTransparent = Input { Value = 1, },
            Input = Input {
               SourceOp = "CopyAux1",
               Source = "Output",
            },
            EffectMask = Input {
               SourceOp = "ChromaKeyer1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 550, 16.5 } },
      },
      CustomTool1 = Custom {
         Inputs = {
            NumberIn1 = Input {
               Value = -11.672646522522,
               Expression = "CopyAux1.Vector.Remap.From.MinX",
            },
            NumberIn2 = Input {
               Value = 18.7788524627686,
               Expression = "CopyAux1.Vector.Remap.From.MaxX",
            },
            NumberIn3 = Input {
               Value = -6.4090633392334,
               Expression = "CopyAux1.Vector.Remap.From.MinY",
            },
            NumberIn4 = Input {
               Value = 11.1418828964233,
               Expression = "CopyAux1.Vector.Remap.From.MaxY",
            },
            LUTIn1 = Input {
               SourceOp = "CustomTool1LUTIn1",
               Source = "Value",
            },
            LUTIn2 = Input {
               SourceOp = "CustomTool1LUTIn2",
               Source = "Value",
            },
            LUTIn3 = Input {
               SourceOp = "CustomTool1LUTIn3",
               Source = "Value",
            },
            LUTIn4 = Input {
               SourceOp = "CustomTool1LUTIn4",
               Source = "Value",
            },
            Intermediate1 = Input { Value = "n2 - n1", },
            Intermediate2 = Input { Value = "n4 - n3", },
            AuxChannelNest = Input { Value = 1, },
            XVectorExpression = Input { Value = "r1*i1+n1", },
            YVectorExpression = Input { Value = "g1*i2+n3", },
            NumberControls = Input { Value = 1, },
            NameforNumber1 = Input { Value = "Min X", },
            NameforNumber2 = Input { Value = "Max X", },
            NameforNumber3 = Input { Value = "Min Y", },
            NameforNumber4 = Input { Value = "Max Y", },
            ShowNumber5 = Input { Value = 0, },
            ShowNumber6 = Input { Value = 0, },
            ShowNumber7 = Input { Value = 0, },
            ShowNumber8 = Input { Value = 0, },
            ShowPoint1 = Input { Value = 0, },
            ShowPoint2 = Input { Value = 0, },
            ShowPoint3 = Input { Value = 0, },
            ShowPoint4 = Input { Value = 0, },
            LUTControls = Input { Value = 1, },
            ShowLUT1 = Input { Value = 0, },
            ShowLUT2 = Input { Value = 0, },
            ShowLUT3 = Input { Value = 0, },
            ShowLUT4 = Input { Value = 0, },
            Image1 = Input {
               SourceOp = "ColorCorrector1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 660, 16.5 } },
      },
      CustomTool1LUTIn1 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 0, Blue = 0 },
         NameSet = true,
      },
      CustomTool1LUTIn2 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 204, Blue = 0 },
         NameSet = true,
      },
      CustomTool1LUTIn3 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 0, Blue = 204 },
         NameSet = true,
      },
      CustomTool1LUTIn4 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 204, Blue = 204 },
         NameSet = true,
      },
      CustomTool2 = Custom {
         CtrlWZoom = false,
         Inputs = {
            LUTIn1 = Input {
               SourceOp = "CustomTool2LUTIn1",
               Source = "Value",
            },
            LUTIn2 = Input {
               SourceOp = "CustomTool2LUTIn2",
               Source = "Value",
            },
            LUTIn3 = Input {
               SourceOp = "CustomTool2LUTIn3",
               Source = "Value",
            },
            LUTIn4 = Input {
               SourceOp = "CustomTool2LUTIn4",
               Source = "Value",
            },
            RedExpression = Input { Value = "if(vx1 == vx2, 0, abs(vx1-vx2))", },
            GreenExpression = Input { Value = "if(vy1 == vy2, 0, abs(vy1-vy2))", },
            Image1 = Input {
               SourceOp = "CustomTool1",
               Source = "Output",
            },
            Image2 = Input {
               SourceOp = "OpticalFlow1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 660, 82.5 } },
      },
      CustomTool2LUTIn1 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 0, Blue = 0 },
         NameSet = true,
      },
      CustomTool2LUTIn2 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 204, Blue = 0 },
         NameSet = true,
      },
      CustomTool2LUTIn3 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 0, Blue = 204 },
         NameSet = true,
      },
      CustomTool2LUTIn4 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 204, Blue = 204 },
         NameSet = true,
      }
   }
}


Capture.JPG
Capture.JPG (183.64 KiB) Viewed 2587 times


Above, I sampled an area of the vectors using a ChromaKeyer, then used the CC to reverse the x displacement of those pixels. CustomTool1 writes the modified vectors into the vector channel, and CustomTool2 is a utility viewer to verify that the original and new vectors are the same except for my change.

Re: Manipulating pixels flow in optical flow.

PostPosted: Mon May 17, 2021 4:46 am
by birdseye
I understood a bit of what you are saying but I don't think I'm familiar enough with Fusion to get something useful happening. The tool as it is in Media Composer is used to prevent or lessen unwanted artifacts in Fluidmotion renders. To that end I suspect any pixel manipulation would need to be merged over a monochrome layer so that the position of artifacts can be seen. In MC this uses a Paint like interface. I'll describe the method as I know it to give an idea of one use.
The method uses masks drawn around areas of pixels, that are moving in the wrong direction for one reason or another. Let's say we have a video, the camera is locked down and there is one foreground object moving left to right, in front of a second object moving right to left . Let's say the second object is dragging pixels from the foreground object as they pass each other and pixels from the backround as it moves over a static background.
In this scenario the background pixels will be monochrome, the foregrond object pixels will be red and the second object will be blue/green, except for the pixels that are being incorrectly dragged by the second object. To correct the pixels of the background that are being dragged, a mask is drawn around them which removes the colour and so removes the movement in those pixels. In the case of the foreground object, a mask can be drawn around those pixels being dragged by the second object, which removes the colour and then with that mask selected, an eyedropper can be used, to pick and transfer the colour from the foregrond object to the mask area, thus transfering the colour/motion to those pixels. Colours relate to the colour wheel, so red equates to movement to the right, yellow upwards etc. Each frame is corrected individually and are keyframed.
Your example comp gave me an idea, so I merged a layer of video, that had a static area of pixels keyed out using Delta Keyer, over a monochrome layer and got more or less the same result as in Media Composer, pixels that take colour corresponding to colours in colour wheel. I didn't have time but I guess the same effect as in MC would not be difficult to achieve using masks and an eyedroper. I guess using colours to shove pixels around is already used by many tools.

Code: Select all
{
   Tools = ordered() {
      OpticalFlow1 = Dimension.OpticalFlow {
         ViewInfo = OperatorInfo { Pos = { 144.667, 33.4242 } },
      },
      CopyAux1 = Dimension.CopyAux {
         Inputs = {
            Channel = Input { Value = FuID { "Vector" }, },
            ["Vector.Remap.Enable"] = Input { Value = 1, },
            ["Vector.Remap.From.MinX"] = Input { Value = -11.672646522522, },
            ["Vector.Remap.From.MaxX"] = Input { Value = 18.7788524627686, },
            ["Vector.Remap.From.MinY"] = Input { Value = -6.4090633392334, },
            ["Vector.Remap.From.MaxY"] = Input { Value = 11.1418828964233, },
            Input = Input {
               SourceOp = "OpticalFlow1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 282, 34.6364 } },
      },
      ColorCorrector3 = ColorCorrector {
         Inputs = {
            WheelSaturation1 = Input { Value = 0, },
            ColorRanges = Input {
               Value = ColorCurves {
                  Curves = {
                     {
                        Points = {
                           { 0, 1 },
                           { 0.4, 0.2 },
                           { 0.6, 0 },
                           { 1, 0 }
                        }
                     },
                     {
                        Points = {
                           { 0, 0 },
                           { 0.4, 0 },
                           { 0.6, 0.2 },
                           { 1, 1 }
                        }
                     }
                  }
               },
            },
            HistogramIgnoreTransparent = Input { Value = 1, },
         },
         ViewInfo = OperatorInfo { Pos = { 285.333, 143.121 } },
      },
      DeltaKeyer1 = DeltaKeyer {
         CtrlWZoom = false,
         Inputs = {
            BackgroundRed = Input { Value = 0.383817493915558, },
            BackgroundGreen = Input { Value = 0.365270674228668, },
            BackgroundBlue = Input { Value = 0, },
            TuningRanges = Input {
               Value = ColorCurves {
                  Curves = {
                     {
                        Points = {
                           { 0, 1 },
                           { 0.4, 0.2 },
                           { 0.6, 0 },
                           { 1, 0 }
                        }
                     },
                     {
                        Points = {
                           { 0, 0 },
                           { 0.4, 0 },
                           { 0.6, 0.2 },
                           { 1, 1 }
                        }
                     }
                  }
               },
            },
            Input = Input {
               SourceOp = "CopyAux1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 383.667, 103.121 } },
      },
      Merge1 = Merge {
         Inputs = {
            Background = Input {
               SourceOp = "ColorCorrector3",
               Source = "Output",
            },
            Foreground = Input {
               SourceOp = "DeltaKeyer1",
               Source = "Output",
            },
            PerformDepthMerge = Input { Value = 0, },
         },
         ViewInfo = OperatorInfo { Pos = { 405.333, 143.727 } },
      },
      ChromaKeyer1 = ChromaKeyer {
         Inputs = {
            RedLow = Input { Value = 0.151556819677353, },
            RedHigh = Input { Value = 0.656691014766693, },
            GreenLow = Input { Value = 0.420021325349808, },
            GreenHigh = Input { Value = 0.879898250102997, },
            BlueLow = Input { Value = 0.0112453997135162, },
            BlueHigh = Input { Value = 0.443919777870178, },
            LuminanceLow = Input { Value = 0.122546270489693, },
            LuminanceHigh = Input { Value = 1.06767308712006, },
            SoftRange = Input { Value = 0.0126, },
            FringeSize = Input { Value = 0, },
            Filter = Input { Value = FuID { "Fast Gaussian" }, },
            InvertMatte = Input { Value = 1, },
            Input = Input {
               SourceOp = "CopyAux1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 400.333, -2 } },
      },
      ColorCorrector1 = ColorCorrector {
         CtrlWZoom = false,
         Inputs = {
            EffectMask = Input {
               SourceOp = "ChromaKeyer1",
               Source = "Output",
            },
            Channel = Input { Value = 1, },
            ColorRanges = Input {
               Value = ColorCurves {
                  Curves = {
                     {
                        Points = {
                           { 0, 1 },
                           { 0.4, 0.2 },
                           { 0.6, 0 },
                           { 1, 0 }
                        }
                     },
                     {
                        Points = {
                           { 0, 0 },
                           { 0.4, 0 },
                           { 0.6, 0.2 },
                           { 1, 1 }
                        }
                     }
                  }
               },
            },
            HistogramIgnoreTransparent = Input { Value = 1, },
            Input = Input {
               SourceOp = "CopyAux1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 493, 34.6364 } },
      },
      CustomTool2 = Custom {
         Inputs = {
            LUTIn1 = Input {
               SourceOp = "CustomTool2LUTIn1",
               Source = "Value",
            },
            LUTIn2 = Input {
               SourceOp = "CustomTool2LUTIn2",
               Source = "Value",
            },
            LUTIn3 = Input {
               SourceOp = "CustomTool2LUTIn3",
               Source = "Value",
            },
            LUTIn4 = Input {
               SourceOp = "CustomTool2LUTIn4",
               Source = "Value",
            },
            RedExpression = Input { Value = "if(vx1 == vx2, 0, abs(vx1-vx2))", },
            GreenExpression = Input { Value = "if(vy1 == vy2, 0, abs(vy1-vy2))", },
            Image1 = Input {
               SourceOp = "CustomTool1",
               Source = "Output",
            },
            Image2 = Input {
               SourceOp = "OpticalFlow1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 534.334, 70.9395 } },
      },
      CustomTool2LUTIn1 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 0, Blue = 0 },
      },
      CustomTool2LUTIn2 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 204, Blue = 0 },
      },
      CustomTool2LUTIn3 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 0, Blue = 204 },
      },
      CustomTool2LUTIn4 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 204, Blue = 204 },
      },
      CustomTool1 = Custom {
         Inputs = {
            NumberIn1 = Input {
               Value = -11.672646522522,
               Expression = "CopyAux1.Vector.Remap.From.MinX",
            },
            NumberIn2 = Input {
               Value = 18.7788524627686,
               Expression = "CopyAux1.Vector.Remap.From.MaxX",
            },
            NumberIn3 = Input {
               Value = -6.4090633392334,
               Expression = "CopyAux1.Vector.Remap.From.MinY",
            },
            NumberIn4 = Input {
               Value = 11.1418828964233,
               Expression = "CopyAux1.Vector.Remap.From.MaxY",
            },
            LUTIn1 = Input {
               SourceOp = "CustomTool1LUTIn1",
               Source = "Value",
            },
            LUTIn2 = Input {
               SourceOp = "CustomTool1LUTIn2",
               Source = "Value",
            },
            LUTIn3 = Input {
               SourceOp = "CustomTool1LUTIn3",
               Source = "Value",
            },
            LUTIn4 = Input {
               SourceOp = "CustomTool1LUTIn4",
               Source = "Value",
            },
            Intermediate1 = Input { Value = "n2 - n1", },
            Intermediate2 = Input { Value = "n4 - n3", },
            AuxChannelNest = Input { Value = 1, },
            XVectorExpression = Input { Value = "r1*i1+n1", },
            YVectorExpression = Input { Value = "g1*i2+n3", },
            NumberControls = Input { Value = 1, },
            NameforNumber1 = Input { Value = "Min X", },
            NameforNumber2 = Input { Value = "Max X", },
            NameforNumber3 = Input { Value = "Min Y", },
            NameforNumber4 = Input { Value = "Max Y", },
            ShowNumber5 = Input { Value = 0, },
            ShowNumber6 = Input { Value = 0, },
            ShowNumber7 = Input { Value = 0, },
            ShowNumber8 = Input { Value = 0, },
            ShowPoint1 = Input { Value = 0, },
            ShowPoint2 = Input { Value = 0, },
            ShowPoint3 = Input { Value = 0, },
            ShowPoint4 = Input { Value = 0, },
            LUTControls = Input { Value = 1, },
            ShowLUT1 = Input { Value = 0, },
            ShowLUT2 = Input { Value = 0, },
            ShowLUT3 = Input { Value = 0, },
            ShowLUT4 = Input { Value = 0, },
            Image1 = Input {
               SourceOp = "ColorCorrector1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 603, 34.6364 } },
      },
      CustomTool1LUTIn1 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 0, Blue = 0 },
      },
      CustomTool1LUTIn2 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 204, Blue = 0 },
      },
      CustomTool1LUTIn3 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 0, Green = 0, Blue = 204 },
      },
      CustomTool1LUTIn4 = LUTBezier {
         KeyColorSplines = {
            [0] = {
               [0] = { 0, RH = { 0.333333333333333, 0.333333333333333 }, Flags = { Linear = true } },
               [1] = { 1, LH = { 0.666666666666667, 0.666666666666667 }, Flags = { Linear = true } }
            }
         },
         SplineColor = { Red = 204, Green = 204, Blue = 204 },
      }
   },
   ActiveTool = "ColorCorrector1"
}

Re: Manipulating pixels flow in optical flow.

PostPosted: Mon May 17, 2021 5:14 am
by Bryan Ray
I think you're going to confuse yourself thinking about the color wheel—optical flow is not hue-related at all.

The vectors are a two-channel image. Fusion stores them in auxiliary sub-channels, but when visualized, X is usually red and Y is green. Blue is not involved. In the actual vector channels, negative values indicate that the pixels are moving left or down and positive values right or up. The actual value is how many pixels of displacement there are. That is, an x-vector value of -3 for a given pixel means that in the next frame, that pixel will move three pixels to the left. A value of 2 means it will move two pixels to the right.

When the vectors are remapped using CopyAux, the "center" value becomes 0.5 and the logical relationship between value and displacement is removed—it's all been scaled down to fit inside the renderable range of 0-1. You can do whatever manipulations you like to this data—mask it, change its color, paint on it, whatever—as long as its returned to the original range at the end so that your retimer or blur works correctly.

You'd probably want to view your output in one Viewer, so you can see where the artifacts are, and the normalized vectors in the other, where you'd be doing your paint work. Trouble is, the two images probably aren't in sync because you're likely doing a retime. So you might also need to look at the output view through a TimeStretcher in order to keep that frame available, and it would probably be a good idea to have some kind of method of keeping track of which frame's vectors you need to manipulate. That gets a little tricky and confusing.

I've done quite a bit of Optical Flow cleanup, but I've never tried to do it by manipulating the vectors themselves. Thus, this is all speculative.

Re: Manipulating pixels flow in optical flow.

PostPosted: Mon May 17, 2021 9:29 am
by birdseye
The weird thing is when I connect a video clip and veiw the merge I get all the colours including shades of blue that correspond to the direction of the colours in the colour wheel, so there may be something going on relating to those 0.5 values, the vectors and the display. Maybe one day I will know enough to do something useful to those artifacts. It's no biggy, curiosity just gets the better of me from time to time.

Re: Manipulating pixels flow in optical flow.

PostPosted: Mon May 17, 2021 4:31 pm
by Bryan Ray
The Media Composer tool must be doing something weird in the visualization, then, instead of showing you a representation of the actual vectors. My technical artist's brain hurts just thinking about that, since it's not how the vectors themselves work.

Re: Manipulating pixels flow in optical flow.

PostPosted: Tue May 18, 2021 7:27 am
by birdseye
I wasn't referring to Media Composer in that example, it is in Fusion. Connect a sample video to the nodes and look at the result with the merge node in the viewer. When pixels move up they are yellow, red when they move right, blue/purple when they move down and green when move to the left. That is also what happens in MC's viewer.

Re: Manipulating pixels flow in optical flow.

PostPosted: Tue May 18, 2021 6:38 pm
by Bryan Ray
I think I need a screenshot of what you're doing. It sounds like you're merging the vectors on top of the RGB of the source video? If so, that will absolutely corrupt the vectors. I can say with certainty that optical flow vectors have only two channels. It is impossible for them to produce blue, magenta or cyan when visualized in the typical fashion.

Re: Manipulating pixels flow in optical flow.

PostPosted: Tue May 18, 2021 7:18 pm
by birdseye
The nodes are in a post above, I just conected a video clip to a colour corrector and the Optical flow, so the blue is probable coming in that way. It only shows up in the merge in pixel that are moving downwards. I've noticed that whatever is happening is quite sensitive to the setting in the CopyAux MinX Maxx MinY MaxY, particularly the MinY. Whether it's any use for anything you might be able to tell but it is a similar look to the MC node. As you say, there is only red and green coming from the CopyAux.

Re: Manipulating pixels flow in optical flow.

PostPosted: Tue May 18, 2021 8:34 pm
by birdseye
Actually I have just checked with another video clip, there was nothing really moving to the right in my first clip, so I found a clip with something moving to the right and there is no red at the settings that show blue and as far as I can see and no blue at the settings that shoe red. No in that clip what should be red has no colour, so that's not the same as MC, oh well, it's still better not to get the artifacts that waste time trying to fix them.