Jump to content


Photo

Gaussuan Blur In An Xy Fashion


  • Please log in to reply
15 replies to this topic

#1 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 11 August 2010 - 04:09 PM

Imagine you're comping a plate where there's no separate layers--typical background scene and no separated characters, with matte for the characters--but you need to defocus the background heavily. You'd always have to compromise the edge of the characters and it will become soft too. Too avoid this, you could cut out the characters using the matte and displace the edge of the cutout inwards (and ever so slightly outwards) so you can defocus the background and merge the characters back on top using the matte as en effect mask. Nice crisp edge on the foreground element and a beautiful defocused background.

The image attached shows an abstract representation of this kind of situation. The background is red, the characters are green and the blue edge is the edge I want to displace. Notice that this needs to happen in a perpendicular fashion along the edge of the matte and not from the center of the canvas. Think of controlling the amount of displace just like Stefan Ihringer's excellent Soft Edge Detection macro, but different in that sense that it generates XY vectors to be used in a displace node in XY mode.

Is there such a tool already out there? And how to achieve a Gaussian blur in an XY motion vector world?

#2 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 11 August 2010 - 04:11 PM

Forgot to add the image...Attached File  BlurInXYSpace.jpg   50.68KB   129 downloads

#3 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 11 August 2010 - 04:19 PM

Hmmm, Gaussian blur is not really what I mean. Tomáto-tomŕto. It's more like a smearing effect, but I hope you understand what I'm trying to explain.

#4 karahana

karahana

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 101 posts

Posted 11 August 2010 - 11:49 PM

Sometimes I do this in fact I believe I did it today and I use a dilate erode node to dilate the edges. use a dilate erode and a merge node, the dilated in the back the one with the whole on top defocus both. on top of those, your character of thingy. That's one of the ways i work around this. Sometimes like today i had the background pic and used it to fill the whole instead.

Is that what u mean?

#5 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 12 August 2010 - 01:08 AM

Hi karahana,


That could work too, I'll check. I have an After Effects plugin that is more sophisticated which extrudes the edge pixels in a perpendicular fashion. But dilating the pixels could do the trick.

This sort of situation was just an practical example of what I would like to do. A more hands on trick for smearing pixels using the XY color values which are being triggered in similar fashion as the Soft Edge Detection. Standard displace is always from the center of the canvas, so XY has more control. I just lack the tools to generate them intuitively.

#6 Tilt

Tilt

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 2,137 posts

Posted 12 August 2010 - 02:52 AM

Cut out your foreground so you have a black hole in all 4 channels. Blur the plate, then divide RGB by alpha. This will prevent a feathered edge and fill the hole. Do this multiple times with small blur amounts instead of one big blur if necessary.

If you just want to fill the hole without blurring, just merge the plate with the hole on top.

There's also the great bzpixelextend Plugin on vfxpedia, but it might be 32bit only.

#7 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 12 August 2010 - 05:08 PM

Found it! Will try to turn it into a macro and I will post it here. Thanks for all the input (will need to checkout that bzpixelextend Plugin, tilt.)

#8 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 13 August 2010 - 04:49 PM

It works pretty fast and gives better results than using an erode / dilate trick (gives you a halo on some areas, depending on the pixel value.)

Copy / Paste

Make sure to use this in HiQ mode

{
	Tools = ordered() {
		Polygon1 = PolylineMask {
			DrawMode = "InsertAndModify",
			DrawMode2 = "InsertAndModify",
			Inputs = {
				MaskWidth = Input {
					Value = 500,
				},
				MaskHeight = Input {
					Value = 500,
				},
				PixelAspect = Input {
					Value = { 1, 1, },
				},
				ClippingMode = Input {
					Value = FuID { "None", },
				},
				Center = Input {
					Value = { 0.5, 0.42, },
				},
				Polyline = Input {
					SourceOp = "Polygon1Polyline",
					Source = "Value",
				},
				Polyline2 = Input {
					Value = Polyline {
						Points = {
						},
					},
					Disabled = true,
				},
			},
			ViewInfo = OperatorInfo {
				Pos = { 495, 148.5, },
			},
		},
		Polygon1Polyline = BezierSpline {
			SplineColor = { Red = 0, Green = 0, Blue = 0, },
			NameSet = true,
			KeyFrames = {
				[0] = { 0, Flags = { Linear = true, LockedY = true, }, Value = Polyline {
						Closed = true,
						Points = {
							{ X = -0.0469808209925531, Y = 0.459812230507934, LX = -0.0349329348727638, LY = -0.0394115164948654, RX = 0.033114847045319, RY = 0.0373603404725402, },
							{ X = 0.0824618476745675, Y = 0.384472408741055, LX = -0.0371797487414937, LY = 0.0333174791750276, RX = 0.0184725998136505, RY = -0.0165536476289591, },
							{ X = 0.136573805523194, Y = 0.333391710223125, LX = -0.0247697003734468, LY = 0.00131230221698121, RX = 0.0511218766570233, RY = -0.00270844423072512, },
							{ X = 0.168074252781596, Y = 0.483707242721607, LX = -0.0408444430421312, LY = -0.0308628160682877, RX = 0.0581965347890457, RY = 0.0439743773015423, },
							{ X = 0.242945277428008, Y = 0.27808727201595, LX = -0.0378648418955864, LY = 0.0623444966996546, RX = 0.0197365388134228, RY = -0.0324962291486412, },
							{ X = 0.365819603413786, Y = 0.271249098452907, LX = -0.0047911393648942, LY = 0.0400506482449249, RX = 0.00709269868249921, RY = -0.0592902014858317, },
							{ X = 0.344442186660467, Y = 0.107076384241161, LX = 0.0323708496301605, LY = 0.0460440926209256, RX = -0.0492776582035336, RY = -0.0700922306454324, },
							{ X = 0.127011246721734, Y = 0.244170008860433, LX = 0.0848804670337613, LY = 0.0116839510015806, RX = -0.161006098760166, RY = -0.0221627829653813, },
							{ X = -0.214451247338822, Y = -0.103868408890531, LX = 0.0764043264387076, LY = -0.143445221907829, RX = -0.0513125032426485, RY = 0.096336604972137, },
							{ X = -0.43964151058992, Y = 0.133855749234302, LX = 0.0842953893960334, LY = -0.0693397560794344, RX = -0.102807473003845, RY = 0.0845674378196191, },
							{ X = -0.078840841708462, Y = 0.305063604597297, LX = 0.0926082718583341, LY = -0.0956281131687978, RX = -0.0366374705136993, RY = 0.0378321731547055, },
						},
					}, },
			},
		},
		EdgeExtrude = MacroOperator {
			Inputs = ordered() {
				Comments = Input {
					Value = "Preview this node",
				},
				MainInput1 = InstanceInput {
					SourceOp = "CutOut",
					Source = "Background",
				},
				Input1 = InstanceInput {
					SourceOp = "MultiplyOffset",
					Source = "Gain",
					Name = "Scale",
					Default = 15000,
				},
				MainInput2 = InstanceInput {
					SourceOp = "Matte",
					Source = "Image",
					Name = "Matte",
				},
				Input2 = InstanceInput {
					SourceOp = "Matte",
					Source = "Invert",
				},
			},
			Outputs = {
				MainOutput1 = InstanceOutput {
					SourceOp = "SolidAlpha",
					Source = "Output",
				},
			},
			ViewInfo = GroupInfo {
				Pos = { 605, 280.5, },
			},
			Tools = ordered() {
				RemoveBorder = Crop {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						XOffset = Input {
							Value = 1,
						},
						YOffset = Input {
							Value = 1,
						},
						XSize = Input {
							Value = 498,
							Expression = "ScreenXY.Width-2",
						},
						YSize = Input {
							Value = 498,
							Expression = "ScreenXY.Height-2",
						},
						KeepCentered = Input {
							Value = 1,
						},
						Input = Input {
							SourceOp = "CreateEdge",
							Source = "Output",
						},
						Comments = Input {
							Value = "Removing the side effects of the Laplacian filter.",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 76.15, },
					},
				},
				RestoreSize = Crop {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						XOffset = Input {
							Value = -1,
						},
						YOffset = Input {
							Value = -1,
						},
						XSize = Input {
							Value = 500,
							Expression = "ScreenXY.Width",
						},
						YSize = Input {
							Value = 500,
							Expression = "ScreenXY.Height",
						},
						KeepCentered = Input {
							Value = 1,
						},
						Input = Input {
							SourceOp = "RemoveBorder",
							Source = "Output",
						},
						Comments = Input {
							Value = "Restoring the canvas size.",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 109.15, },
					},
				},
				CreateEdge = Filter {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						FilterType = Input {
							Value = 4,
						},
						Power = Input {
							Disabled = true,
						},
						Angle = Input {
							Disabled = true,
						},
						Randomize = Input {
							Disabled = true,
						},
						Seed = Input {
							Disabled = true,
						},
						Animated = Input {
							Disabled = true,
						},
						Input = Input {
							SourceOp = "CutOut",
							Source = "Output",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 43.15, },
					},
				},
				MapEdge = ChannelBoolean {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						ApplyMaskInverted = Input {
							Value = 1,
						},
						Operation = Input {
							Value = 12,
						},
						Background = Input {
							SourceOp = "ScreenXY",
							Source = "Output",
						},
						Comments = Input {
							Value = "Inserting coordinates to the edge.",
						},
						EffectMask = Input {
							SourceOp = "RestoreSize",
							Source = "Output",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 142.15, },
					},
				},
				CutOut = ChannelBoolean {
					CtrlWZoom = false,
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Operation = Input {
							Value = 12,
						},
						Background = Input {
							SourceOp = "CutOutPoly",
							Source = "Output",
						},
						EffectMask = Input {
							SourceOp = "Matte",
							Source = "Mask",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { 0, 10.15, },
					},
				},
				ExpandEdge = Blur {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						YBlurSize = Input {
							Disabled = true,
						},
						Input = Input {
							SourceOp = "MapEdge",
							Source = "Output",
						},
						Comments = Input {
							Value = "Creating a perpendicular motion using the blur.",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 175.15, },
					},
				},
				ScreenXY = Background {
					ExtentSet = false,
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Width = Input {
							Value = 500,
							Expression = "CutOut.Background.Width",
						},
						Height = Input {
							Value = 500,
							Expression = "CutOut.Background.Height",
						},
						PixelAspect = Input {
							Expression = "Point(CutOut.Background.XScale, CutOut.Background.YScale)",
						},
						Depth = Input {
							Value = 4,
						},
						Type = Input {
							Value = FuID { "Corner", },
						},
						TopLeftGreen = Input {
							Value = 1,
						},
						TopRightRed = Input {
							Value = 1,
						},
						TopRightGreen = Input {
							Value = 1,
						},
						BottomRightRed = Input {
							Value = 1,
						},
						Gradient = Input {
							Value = Gradient {
								Colors = {
									[0] = { 0, 0, 0, 1, },
									[1] = { 1, 1, 1, 1, },
								},
							},
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -330, 208.15, },
					},
				},
				AddEdge = Merge {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						PerformDepthMerge = Input {
							Value = 0,
						},
						Background = Input {
							SourceOp = "ScreenXY",
							Source = "Output",
						},
						Foreground = Input {
							SourceOp = "ExpandEdge",
							Source = "Output",
						},
						Comments = Input {
							Value = "Adding the result on a neutral canvas with coordinates.",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 208.15, },
					},
				},
				CalcEdge = ChannelBoolean {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Operation = Input {
							Value = 2,
						},
						Background = Input {
							SourceOp = "AddEdge",
							Source = "Output",
						},
						Foreground = Input {
							SourceOp = "ScreenXY",
							Source = "Output",
						},
						Comments = Input {
							Value = "Substracting which give the offsets for the individual pixels.",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 241.15, },
					},
				},
				OutToIn = ChannelBoolean {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Operation = Input {
							Value = 12,
						},
						ToAlpha = Input {
							Value = 4,
						},
						Background = Input {
							SourceOp = "CalcEdge",
							Source = "Output",
						},
						Comments = Input {
							Value = "Removing the outward motion vectors.",
						},
						EffectMask = Input {
							SourceOp = "Matte",
							Source = "Mask",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 274.15, },
					},
				},
				VectorDisplace = VectorMotionBlur {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Input = Input {
							SourceOp = "CutOut",
							Source = "Output",
						},
						Vectors = Input {
							SourceOp = "MultiplyOffset",
							Source = "Output",
						},
						XVectorChannel = Input {
							Value = 0,
						},
						YChannel = Input {
							Value = 1,
						},
						XScale = Input {
							Value = 300,
						},
						EffectMask = Input {
							SourceOp = "Matte",
							Source = "Mask",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { 165, 307.15, },
					},
				},
				MultiplyOffset = BrightnessContrast {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Gain = Input {
							Value = 600,
						},
						Input = Input {
							SourceOp = "OutToIn",
							Source = "Output",
						},
						Comments = Input {
							Value = "Scaling the offsets using gain only.",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { -165, 307.15, },
					},
					Colors = {
						TileColor = { R = 0, G = 1, B = 0.250980392156863, },
						TextColor = { R = 0, G = 0, B = 0, },
					},
				},
				Divide = ChannelBoolean {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						Operation = Input {
							Value = 7,
						},
						ToRed = Input {
							Value = 3,
						},
						ToGreen = Input {
							Value = 3,
						},
						ToBlue = Input {
							Value = 3,
						},
						ToAlpha = Input {
							Value = 4,
						},
						Background = Input {
							SourceOp = "VectorDisplace",
							Source = "Output",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { 165, 340.15, },
					},
				},
				SolidAlpha = ChannelBoolean {
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						ToAlpha = Input {
							Value = 16,
						},
						Background = Input {
							SourceOp = "Divide",
							Source = "Output",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { 165, 373.15, },
					},
				},
				Matte = BitmapMask {
					CtrlWZoom = false,
					CtrlWShown = false,
					NameSet = true,
					Inputs = {
						OutputSize = Input {
							Value = FuID { "Custom", },
						},
						MaskWidth = Input {
							Value = 500,
							Expression = "CutOut.Background.Width",
						},
						MaskHeight = Input {
							Value = 500,
							Expression = "CutOut.Background.Height",
						},
						PixelAspect = Input {
							Value = { 1, 1, },
							Expression = "Point(CutOut.Background.XScale, CutOut.Background.YScale)",
						},
						ClippingMode = Input {
							Value = FuID { "None", },
						},
						Image = Input {
							SourceOp = "Polygon1",
							Source = "Mask",
						},
					},
					ViewInfo = OperatorInfo {
						Pos = { 330, 208.15, },
					},
					Colors = {
						TileColor = { R = 0, G = 1, B = 0, },
					},
				},
			},
		},
		CutOutPoly = ChannelBoolean {
			NameSet = true,
			Inputs = {
				Operation = Input {
					Value = 12,
				},
				Background = Input {
					SourceOp = "SetAlpha",
					Source = "Output",
				},
				EffectMask = Input {
					SourceOp = "Polygon1",
					Source = "Mask",
				},
			},
			ViewInfo = OperatorInfo {
				Pos = { 440, 280.5, },
			},
		},
		SetAlpha = ChannelBoolean {
			NameSet = true,
			Inputs = {
				ToAlpha = Input {
					Value = 16,
				},
				Background = Input {
					SourceOp = "Plasma1",
					Source = "Output",
				},
			},
			ViewInfo = OperatorInfo {
				Pos = { 330, 280.5, },
			},
		},
		Plasma1 = Plasma {
			ExtentSet = false,
			Inputs = {
				Width = Input {
					Value = 500,
				},
				Height = Input {
					Value = 500,
				},
				Depth = Input {
					Value = 1,
				},
			},
			ViewInfo = OperatorInfo {
				Pos = { 220, 280.5, },
			},
		},
		Note1 = Note {
			Inputs = {
				Comments = Input {
					Value = "You can use an image file or a polygon mask, but it looks at the alpha only.",
				},
			},
			ViewInfo = StickyNoteInfo {
				Pos = { 605, 115.5, },
				Flags = {
					Expanded = true,
				},
				Size = { 196, 81.3, },
			},
		},
	},
}

Attached Files



#9 Tilt

Tilt

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 2,137 posts

Posted 03 September 2010 - 07:28 AM

 This is a nice macro! It should be added to vfxpedia or at least to Gringo's sticky tips thread...

#10 ChadCapeland

ChadCapeland

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 1,975 posts

Posted 03 September 2010 - 09:12 AM

There are easier ways to get a gradient though... Use the CFlt tool. The Vector motion blur is pretty clever though, have to explore that a bit more...

#11 Tilt

Tilt

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 2,137 posts

Posted 03 September 2010 - 12:54 PM

There are easier ways to get a gradient though...  Use the CFlt tool.  The Vector motion blur is pretty clever though, have to explore that a bit more...


How? :-)







#12 Kristof

Kristof

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 263 posts

Posted 03 September 2010 - 01:16 PM


There are easier ways to get a gradient though...  Use the CFlt tool.  The Vector motion blur is pretty clever though, have to explore that a bit more...


How? :-)


Using the custom tool? In the channels tab type x for the red expression, y for green and O for blue.
Funny thing, I remember seeing the "Determine the Displacement Vectors from a GridWarp" video but I was tired and I didn't really get it at the time. Forgot about it, fast forward a few months and after completing this macro I came across it again and I realized it somehow did get stuck in the back of my mind because they use a similar technique. Check it to see the use of the custom tool to make the gradient.

Good to know somebody else finds it to be useful. :) I use it a lot now, but it can be improved upon and I'm always curious to see what other people come up with.

I should use a divider on the scale control so the values don't look so extreme.

#13 Tilt

Tilt

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 2,137 posts

Posted 03 September 2010 - 03:14 PM

  Yeah, but Chad was talking about the Custom Filter, and - being a matrix-multiplication-challenged guy to begin with - I can't figure out how to use a filter to get the gradient. I guess he's thinking of some matrix to do the laplacian and the gradient in one go? 

#14 ChadCapeland

ChadCapeland

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 1,975 posts

Posted 03 September 2010 - 08:29 PM

Well, the gradient WAS a bit off, you have to go from 0 to image.sizeinpixels/1+image.sizeinpixels. That just caused a slight inaccuracy. The CT is a better approach (or a custom tool, we have a plugin that does a UVW gradient).

What I was actually referring to was finding the gradient of the mask edge. The Laplacian method in the macro returned better results than I would have expected, but it's more work than it needs to be. A pair of Sobel or Scharr filters, applied to a float version of the mask (using the CFlt), can be used to find the gradient more directly. This simplifies the macro a lot, and in my opinion improves the result.

The Scharr filters (3x3) would be:

3, 10, 3
0, 0, 0
-3, -10, -3

and

3, 0, -3
10, 0, -10
3, 0, -3

The first one finds the Y slope and the second finds the X.

- Chad

#15 Tilt

Tilt

    Flying Pig

  • Adv Members
  • PipPipPipPipPip
  • 2,137 posts

Posted 04 September 2010 - 02:31 AM

 Thanks Chad, I'll give it a shot :-)










0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users