Jump to: Board index » General » Fusion

Best practice for cutting an image into separate pieces?

Learn about 3D compositing, animation, broadcast design and VFX workflows.
  • Author
  • Message
Offline

Umberto Uderzo

  • Posts: 263
  • Joined: Fri Mar 13, 2015 12:19 am

Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 7:53 am

I need to mask different parts of an image and separate them in different pipelines.

The only way i found is by using a Channel booleans by copying original image in the Background RGB and the mask in the Foreground alpha. But it's not enough because i get a semi/transparent result. I need to pipe a Matte Control node and perform a Post multiply image, which i didn't fully understand.

Is there a more dedicated/elegant way?

Thanks!
Offline

Frank Feijen

  • Posts: 167
  • Joined: Tue Dec 13, 2016 10:04 am
  • Location: Vilvoorde, Belgium

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 8:57 am

Something like this?

Code: Select all
{
   Tools = ordered() {
      Ellipse1 = EllipseMask {
         CtrlWZoom = false,
         Inputs = {
            MaskWidth = Input { Value = 1920, },
            MaskHeight = Input { Value = 1080, },
            PixelAspect = Input { Value = { 1, 1 }, },
            ClippingMode = Input { Value = FuID { "None" }, },
            Center = Input { Value = { 0.297953964194373, 0.543181818181818 }, },
            Width = Input { Value = 0.171489049762048, },
            Height = Input { Value = 0.171489049762048, },
         },
         ViewInfo = OperatorInfo { Pos = { 440, 16.5 } },
      },
      Background1 = Background {
         Inputs = {
            Width = Input { Value = 1920, },
            Height = Input { Value = 1080, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            Type = Input { Value = FuID { "Gradient" }, },
         },
         ViewInfo = OperatorInfo { Pos = { 330, 148.5 } },
      },
      MatteControl1 = MatteControl {
         Inputs = {
            ["Garbage.Matte"] = Input {
               SourceOp = "Ellipse1",
               Source = "Mask",
            },
            ["Garbage.MaskNest"] = Input { Value = 1, },
            ["Garbage.MaskInverted"] = Input { Value = 1, },
            PostMultiplyImage = Input { Value = 1, },
            MultiplyGarbageMatte = Input { Value = 0, },
            Background = Input {
               SourceOp = "Background1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 495, 82.5 } },
      },
      MatteControl1_1 = MatteControl {
         Inputs = {
            ["Garbage.Matte"] = Input {
               SourceOp = "Rectangle1",
               Source = "Mask",
            },
            ["Garbage.MaskNest"] = Input { Value = 1, },
            ["Garbage.MaskInverted"] = Input { Value = 1, },
            PostMultiplyImage = Input { Value = 1, },
            Background = Input {
               SourceOp = "Background1",
               Source = "Output",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 495, 181.5 } },
      },
      Merge1 = Merge {
         Inputs = {
            Background = Input {
               SourceOp = "MatteControl1_1",
               Source = "Output",
            },
            Foreground = Input {
               SourceOp = "MatteControl1",
               Source = "Output",
            },
            PerformDepthMerge = Input { Value = 0, },
         },
         ViewInfo = OperatorInfo { Pos = { 605, 181.5 } },
      },
      Rectangle1 = RectangleMask {
         Inputs = {
            MaskWidth = Input { Value = 1920, },
            MaskHeight = Input { Value = 1080, },
            PixelAspect = Input { Value = { 1, 1 }, },
            ClippingMode = Input { Value = FuID { "None" }, },
            Center = Input { Value = { 0.739130434782609, 0.534090909090909 }, },
            Width = Input { Value = 0.140493606138107, },
            Height = Input { Value = 0.281818181818182, },
         },
         ViewInfo = OperatorInfo { Pos = { 495, 247.5 } },
      }
   }
}
Offline

Umberto Uderzo

  • Posts: 263
  • Joined: Fri Mar 13, 2015 12:19 am

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 9:33 am

Yay! Yes, this one!

One more thing i need to understand (i'm a newbie and i need to nail some alpha concepts).
I understand that i need to post multiply the image with the alpha channel to get my result. What i don't understand is why i get a semi transparent cutout if i uncheck "Post multiply image" instead of a fully opaque result. Is it due to Fusion mixing RGB and alpha in such a way to let me see that there is an alpha or what? I don't get it.

Thanks!
Offline

Sander de Regt

  • Posts: 3500
  • Joined: Thu Nov 13, 2014 10:09 pm

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 9:59 am

I'll try to explain it a little, but I may make some mistakes in doing so. I'm sure people will correct me.

If you create an alpha channel - in this case by adding a garbage mask in the matte control tool - you only tell Fusion: I want this part of the image to be transparent and this part opaque. This does not yet change the actual colors of the image. So you can have a pixel that's pure white (RGB 255,255,255) with an alpha channel of 0. What post multiply does is ... multiply the RGB values with the alpha channel, resulting in RGB 0,0,0 with alpha 0.
This is important because by default Fusion merges additively, which means that if your background is for example 128,128,128 and you merge an image on top of it that's 127,127,127 the end result will be 255,255,255 i.e. full white if you use an alpha of 0.
It's a bit more complicated than this, but the bottom line is that the post multiplication makes sure that the merges work correctly.
By default in the matte control the 'multiply garbage matte' is checked, so there's nothing more you need to do.
Sander de Regt

ShadowMaker SdR
The Netherlands
Offline

Umberto Uderzo

  • Posts: 263
  • Joined: Fri Mar 13, 2015 12:19 am

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 10:35 am

In my composition there is no merge yet. Well, there is a merge between two shapes but checking the result i get an alpha = 1 where i see white and alpha = 0 where i see black (picture 2).
What puzzles me is that the default behavior of the "Matte Control" tool gives me (picture 3) which i don't really understand.
By selecting "Post multiply image" i get (picture 4), which is the desired result.
I don't get why the background looks like it has an alpha of 0.5 in (picture 3).

matte.jpg
matte.jpg (139.66 KiB) Viewed 2251 times
Offline

Sander de Regt

  • Posts: 3500
  • Joined: Thu Nov 13, 2014 10:09 pm

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 10:39 am

It's difficult to see on your picture, since it's very small, but it's most likely because you put a merge between the shapes. Don't do that. There is no need for it. Masks are special tools, that are not actually images as far as Fusion is concerned. You can just put one shape after the other and do the merging/subtracting/adding etc right in the mask tools.
Also: make sure that the shapes go into the 'garbage matte' input of the matte control. If you do this, there is no need to post multiply the image.
Sander de Regt

ShadowMaker SdR
The Netherlands
Offline

Umberto Uderzo

  • Posts: 263
  • Joined: Fri Mar 13, 2015 12:19 am

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 11:02 am

Got it!

My matte were going into the "Solid matte" input instead of the "Garbage matte".
And now i see also the paint mode in the shapes, which indeed make the merge useless.

Thank you!
Offline
User avatar

Bryan Ray

  • Posts: 2478
  • Joined: Mon Nov 28, 2016 5:32 am
  • Location: Los Angeles, CA, USA

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 5:02 pm

Sander, your description of post-multiplication (pre-multiplication in the Other Compositors) is pretty good, but I think you're going to confuse yourself and others by using integer 0-255 values instead of normalized 0-1 values.

For instance, if you multiply 128 * 128, your math education suggests you should get 16,384, right? But instead you get 64. What gives? In fact, the imaging software is always doing its math in normalized 0-1 values, so what you're actually doing is 0.5 * 0.5 = 0.25. (0.25 * 255 = 64.75) That's why the image gets darker when you multiply instead of brighter.

Train yourself to think in these normalized terms, and you'll have a much easier time understanding and communicating the image processing math.

--

Now, Umberto, the reason your image looks translucent in picture three is exactly as Sander said: The RGB pixels still have their original values, but since the Alpha is 0, they get added to whatever's in the background. In this case, the checkerboard pattern of the canvas. If you were to turn off Show Checker Underlay in the viewer, then picture 3 would look exactly like picture 1 because it would be adding the 0 of the black canvas to those pixels instead of greys and whites.

Sometimes that might be exactly what you want to happen. If you need to composite a light source into an image, it's common to do it by setting the alpha to 0 without post-multiplying. When you then perform an additive Merge, the light is simply added instead to the background instead of having its alpha channel carved out of the background first.

Another way to get the result you were after is to set the ChannelBooleans node to Clear and put your matte in the Mask input. Or if you wanted to do it really explicitly, you could set the ChannelBooleans up to Multiply or And (they're functionally the same operation) the image by the matte, which you would have to put into the Foreground input.

Code: Select all
{
   Tools = ordered() {
      Polygon1 = PolylineMask {
         DrawMode = "InsertAndModify",
         DrawMode2 = "InsertAndModify",
         Inputs = {
            MaskWidth = Input { Value = 1920, },
            MaskHeight = Input { Value = 1080, },
            PixelAspect = Input { Value = { 1, 1 }, },
            ClippingMode = Input { Value = FuID { "None" }, },
            Polyline = Input {
               SourceOp = "Polygon1Polyline",
               Source = "Value",
            },
            Polyline2 = Input {
               Value = Polyline {
               },
               Disabled = true,
            },
         },
         ViewInfo = OperatorInfo { Pos = { 746, 123 } },
      },
      Polygon1Polyline = BezierSpline {
         SplineColor = { Red = 173, Green = 255, Blue = 47 },
         NameSet = true,
         KeyFrames = {
            [0] = { 0, Flags = { Linear = true, LockedY = true }, Value = Polyline {
                  Closed = true,
                  Points = {
                     { X = -0.0364583320915699, Y = 0.0379629619419575, LX = -0.030170509912323, LY = -0.0177670786938803, RX = 0.0277777773638566, RY = 0.0163580250316932 },
                     { X = 0.046875, Y = 0.0870370343327522, LX = -0.0130208333333334, LY = 0.00277777507349298, RX = 0.0289917223614211, RY = -0.00618489474917253 },
                     { X = 0.126041665673256, Y = 0.0203703697770834, LX = -0.00208333432674412, LY = 0.0157407401474538, RX = 0.00538208463188556, RY = -0.0406646185178131 },
                     { X = 0.103124998509884, Y = -0.0981481447815895, LX = 0.0296874985098838, LY = 0.0194444478110031, RX = -0.0397789549768681, RY = -0.0260540582011798 },
                     { X = -0.0234375, Y = -0.120370373129845, LX = -0.00989583333333334, LY = -0.0259259286854002, RX = 0.0202203555300076, RY = 0.0529749721732462 },
                     { X = 0.0770833343267441, Y = -0.0500000007450581, LX = -0.00312499900658928, LY = -0.0194444451895025, RX = 0.00505315494664761, RY = 0.0314418642012283 },
                     { X = 0.058854166418314, Y = 0.0425925925374031, LX = 0.010416666418314, LY = -0.00370370375889318, RX = -0.0311654909142683, RY = 0.0110810638654981 }
                  }
               } }
         }
      },
      ChannelBooleans1_1 = ChannelBoolean {
         CustomData = {
            Settings = {
               [1] = {
                  Tools = ordered() {
                     ChannelBooleans1_1 = ChannelBoolean {
                        Inputs = {
                           Background = Input {
                              SourceOp = "RsAmbientOcclusion_090_MonumentValley_Car_BTY_",
                              Source = "Output"
                           }
                        },
                        Name = "ChannelBooleans1_1",
                        CtrlWZoom = false,
                        ViewInfo = OperatorInfo { Pos = { 440, -313.5 } },
                        CustomData = {
                        }
                     }
                  }
               },
               [2] = {
                  Tools = ordered() {
                     ChannelBooleans1 = ChannelBoolean {
                        Inputs = {
                           Operation = Input { Value = 1 },
                           ToAlpha = Input { Value = 4 }
                        },
                        CtrlWZoom = false,
                        ViewInfo = OperatorInfo { Pos = { 1265, 181.5 } },
                        CustomData = {
                        }
                     }
                  }
               },
               [3] = {
                  Tools = ordered() {
                     ChannelBooleans1 = ChannelBoolean {
                        Inputs = {
                           Operation = Input { Value = 2 },
                           ToAlpha = Input { Value = 4 }
                        },
                        CtrlWZoom = false,
                        ViewInfo = OperatorInfo { Pos = { 1265, 181.5 } },
                        CustomData = {
                        }
                     }
                  }
               },
               [4] = {
                  Tools = ordered() {
                     ChannelBooleans1 = ChannelBoolean {
                        Inputs = {
                           Operation = Input { Value = 6 },
                           ToAlpha = Input { Value = 4 }
                        },
                        CtrlWZoom = false,
                        ViewInfo = OperatorInfo { Pos = { 1265, 181.5 } },
                        CustomData = {
                        }
                     }
                  }
               },
               [5] = {
                  Tools = ordered() {
                     ChannelBooleans1_1 = ChannelBoolean {
                        Inputs = {
                           ToRed = Input { Value = 3 },
                           ToGreen = Input { Value = 3 },
                           Operation = Input { Value = 7 },
                           Background = Input {
                              SourceOp = "RsAmbientOcclusion_090_MonumentValley_Car_BTY_",
                              Source = "Output"
                           },
                           ToBlue = Input { Value = 3 },
                           ToAlpha = Input { Value = 4 }
                        },
                        CtrlWZoom = false,
                        ViewInfo = OperatorInfo { Pos = { 440, -313.5 } },
                        CustomData = {
                        }
                     }
                  }
               },
            }
         },
         Inputs = {
            Operation = Input { Value = 6, },
            ToRed = Input { Value = 3, },
            ToGreen = Input { Value = 3, },
            ToBlue = Input { Value = 3, },
            Background = Input {
               SourceOp = "Background1",
               Source = "Output",
            },
            Foreground = Input {
               SourceOp = "Polygon1",
               Source = "Mask",
            },
         },
         ViewInfo = OperatorInfo { Pos = { 788, 240 } },
      },
      Background1 = Background {
         CtrlWZoom = false,
         Inputs = {
            Width = Input { Value = 1920, },
            Height = Input { Value = 1080, },
            ["Gamut.SLogVersion"] = Input { Value = FuID { "SLog2" }, },
            TopLeftRed = Input { Value = 0.225, },
            TopLeftGreen = Input { Value = 0.538, },
            TopLeftBlue = Input { Value = 0.731, },
         },
         ViewInfo = OperatorInfo { Pos = { 620, 239 } },
      }
   }
}
Bryan Ray
http://www.bryanray.name
http://www.sidefx.com
Offline

Sander de Regt

  • Posts: 3500
  • Joined: Thu Nov 13, 2014 10:09 pm

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 9:13 pm

Sander, your description of post-multiplication (pre-multiplication in the Other Compositors) is pretty good, but I think you're going to confuse yourself and others by using integer 0-255 values instead of normalized 0-1 values.


Good point, Bryan. I'll keep that in mind in the future.
Sander de Regt

ShadowMaker SdR
The Netherlands
Offline

Umberto Uderzo

  • Posts: 263
  • Joined: Fri Mar 13, 2015 12:19 am

Re: Best practice for cutting an image into separate pieces?

PostFri Oct 13, 2017 9:33 pm

Thank you Bryan and Sander!
It's not easy to get it fluent in alpha math... but to try nailing it in my mind:

Non premultiplied image:
RedOutput = RedBG * ( 1.0 - AlphaFG ) + RedFG

Premultiplied image:
RedOutput = RedBG * ( 1.0 - AlphaFG ) + RedFG * AlphaFG

And so on for Green and Blue channels?
Offline
User avatar

Bryan Ray

  • Posts: 2478
  • Joined: Mon Nov 28, 2016 5:32 am
  • Location: Los Angeles, CA, USA

Re: Best practice for cutting an image into separate pieces?

PostSat Oct 14, 2017 1:58 am

The first formula you give is the Additive Merge, which is generally used with a premultiplied image.

The second is the Subtractive Merge mode, which is used with unpremulted images.

Fusion's Merge node has a slider that does a weighted average between the two modes, so if you wanted to, you could expand the formula to this:

RedOut = RedBG * (1 - AlphaFG) + RedFG * S + RedFG * AlphaFG * (1 - S)

Where S is the value of the Subtractive - Additive slider.

And then you get into the Alpha Gain slider, which is a multiplier on the AlphaFG, and the Blend control, which is a multiplier on the entire FG portion of the equation. I haven't yet worked out what Burn In does.
Last edited by Bryan Ray on Mon Oct 16, 2017 6:45 pm, edited 4 times in total.
Bryan Ray
http://www.bryanray.name
http://www.sidefx.com
Offline

Umberto Uderzo

  • Posts: 263
  • Joined: Fri Mar 13, 2015 12:19 am

Re: Best practice for cutting an image into separate pieces?

PostSun Oct 15, 2017 9:27 pm

Guess that the Alpha should stay also somewhere in the S part of the expression, anyway i got the overall idea. And i understand that the merge node gives so much freedom over the standard additive/subtractive technique. Sure this will help in certain situation. The most important thing for me now is having understood which is which.

I'm happy i did cross this "happy accident", this let me nail some concepts that otherwise would stay in my "romantic ideas" room. And alpha channel was one of those ideas :lol:

Thank you again!
Offline
User avatar

Bryan Ray

  • Posts: 2478
  • Joined: Mon Nov 28, 2016 5:32 am
  • Location: Los Angeles, CA, USA

Re: Best practice for cutting an image into separate pieces?

PostMon Oct 16, 2017 6:42 pm

Whoops! You're right. I'll edit my reply above to fix the equation.
Bryan Ray
http://www.bryanray.name
http://www.sidefx.com

Return to Fusion

Who is online

Users browsing this forum: No registered users and 41 guests