Compositing - Beauty Fix Tutorial

"Go to a film studio", "Go do compositing", "You'll learn so much" was what one of the mentors while I was an apprentice at Disney told me one night. While I agreed since I have seen some of the amazing things that live action compositors do with all their tricks and hacks but oof, live action sounds like a lot of roto and rotopaint so I was initially averse to the idea.

I somehow did end up as a compositor for live action at Ingenuity Studios, and my previous experience was a semester of Intro to Nuke class in school. It was quite stressful since I was unsure if my work was good enough quality and working in primarily episodic TV meant that it was a far faster pace than feature film. I did learn a lot though such as how to stabilize my shot first before doing rotos and rotopaints and then matchmoving it back, 3d tracking, split screens, fluid morphs, setting up 3D scenes in Nuke, etc. One very scary amazing thing that I learned was how to do beauty fixes since this means not only can I use Photoshop to touch up photos but now I can also touch up videos, too! Never tell your friends and family!

Things that I have used this for are to get ride of various acne and blemishes, reduce eyebags, remove wrinkles, and to create soft beauty glows. This can probably even be used to add makeup such as eye shadow and blush; maybe lipstick but that would involve some heavy tracking and roto if the character is talking. Sadly beauty fix comps generally can't be shown on reels as the client doesn't want the original plate being seen.

There are two ways to do beauty fixes. One would be to just stabilize the plate, clone rotopaint, and matchmove it back. Seemingly simple and straightforward, but the downfall to this method is making sure the paint blends well with the surrounding and making sure the tracks are stable.
This other method that I'm going to show instead applies the paint fix with a linear light merge operation and the benefit of this is that it doesn't matter where you are cloning from, all that is being copied is the texture and with this setup, there is just one node to adjust if the client comes back wanting the beauty fix to be decreased or increased.

highpass.PNG

First we denoise the plate and do a high pass on it. Leave the invert and the grade alone as they are the adjustments needed for the Linear Light to work properly at the end of the tree. The Gaussian Blur node is the percentage adjustment of how much of the beauty fix paint you want with 0 being none and 100 being full. Generally you'd want to have it somewhere from 20 to 30.

paint.PNG

Next is tracking and stabilizing. At work, I had access to Mocha which I used for tracking. Without it, you may just need to manually animate a roto shape so it tracks with whatever you are tracking. I'd roto an eyebag or a cheek and let it track through and then copy out the shape data into nuke which give me a roto node.

Copy the roto shape and paste it into the first SplineWarp node and set the output to AB Morph (I've set it on default in the template to AB morph by default as a reminder but it will need to be switched to A first before pasting in the spline otherwise you get duplicate splines). Right click on your spline and choose "Duplicate in B and join". With the SplineWarp selected, hit tab and type freezeWarp (will need to install this python script), hit enter, and set the frame to your reference frame number.

Do your rotopaints. It may be hard to see what you're doing with everything gray and washed out from the high pass so feel free to disable the group of nodes in that background temporarily while you work. I have it set up with rotopaint (where you paint) > roto, with replace checked (define cut out area) > blur (soften shape) > premult (cutout). The idea of doing it straight down in a single line instead of branching out (which tends to be recommended when stereoscope is involved due to easy offsetting the roto) is that if the plate is switched to a different colorspace the paint will automatically match up properly.

Matchmove your paint fix back by duplicating your first SplineWarp, connect the B input, and reverse the the Mix and Root Warp attributes so that it is now 1 and 0 respectively. Repeat for as many paint fixes you need, ex: left eyebag, right eyebag, forehead, chin.

Now we just merge everything back together!

Full template view

Full template view

 

Possible video walkthrough coming later?

+ Nuke template script. Copy and paste into Nuke. (click to expand)

set cut_paste_input [stack 0]
version 10.0 v4
BackdropNode {
inputs 0
name BackdropNode3
tile_color 0xd38d8dff
label "Beauty Paint"
note_font_size 42
selected true
xpos 2706
ypos 699
bdwidth 300
bdheight 591
}
BackdropNode {
inputs 0
name High_Pass2
tile_color 0x4b4b4b01
label "High Pass"
note_font_size 30
selected true
xpos 3082
ypos 365
bdwidth 559
bdheight 361
}
Input {
inputs 0
name Plate
selected true
xpos 3755
ypos 51
}
Dot {
name Dot40
selected true
xpos 3783
ypos 245
}
set N6218b000 [stack 0]
Dot {
name Dot39
selected true
xpos 3783
ypos 325
}
set N6218ac00 [stack 0]
push $N6218b000
Denoise2 {
output Noise
analysisRegion {1671 1643.5 1909 1886.5}
analysisFrame 1013
needsAnalyzing false
profileCurve {profile {curve x0.1000000015 0 x0.1333521456 0 x0.1778279394 0 x0.2371373773 0 x0.3162277639 0 x0.4216965139 0 x0.5623413324 0 x0.7498942018 0 x1 0}}
serializeKnob "0.453965 0.640378 0.330174
0.00146132 0.00045174 0.00050087
0.00146132 0.00045174 0.00050087
0.000868511 0.000226545 0.000265541
0 0 0
0.00152308 0.00050158 0.000490358
0.00152308 0.00050158 0.000490358
0.000651655 0.000183915 0.000190092
0 0 0
0.00116549 0.000547355 0.000502862
0.00116549 0.000547355 0.000502862
0.00057804 0.000231491 0.000215478
0 0 0
0.000444892 0.000319364 0.000270761
0.000444892 0.000319364 0.000270761
0.000289052 0.000208838 0.00019106
0 0 0 0 0 0 0 0 0
4172215390408232403"
name Denoise3
selected true
xpos 3526
ypos 241
}
set N6218a800 [stack 0]
Merge2 {
inputs 2
operation minus
name Merge14
selected true
xpos 3526
ypos 327
}
Dot {
name Dot30
selected true
xpos 3554
ypos 421
}
set N6218a000 [stack 0]
Blur {
size 19
name Gausian_Blur2
selected true
xpos 3526
ypos 488
cached true
}
Dot {
name Dot31
selected true
xpos 3554
ypos 583
}
set N621bd800 [stack 0]
Invert {
name Invert3
selected true
xpos 3300
ypos 579
}
push $N6218a000
Dot {
name Dot32
selected true
xpos 3218
ypos 421
}
Merge2 {
inputs 2
operation plus
name Merge15
selected true
xpos 3190
ypos 585
}
Grade {
multiply 0.5
name Grade4
selected true
xpos 3190
ypos 657
}
set N621bc800 [stack 0]
Dot {
name Dot33
selected true
xpos 2844
ypos 655
}
SplineWarp3 {
crop_to_format false
boundary_bbox false
output_enum "AB morph"
curves {{{v x3f99999a}
{f 0}
{n
{layer Root
{f 0}
{t x44700000 x44070000}
{a pt1x 0 pt1y 0 pt2x 0 pt2y 0 pt3x 0 pt3y 0 pt4x 0 pt4y 0 ptex00 0 ptex01 0 ptex02 0 ptex03 0 ptex10 0 ptex11 0 ptex12 0 ptex13 0 ptex20 0 ptex21 0 ptex22 0 ptex23 0 ptex30 0 ptex31 0 ptex32 0 ptex33 0 ptof1x 0 ptof1y 0 ptof2x 0 ptof2y 0 ptof3x 0 ptof3y 0 ptof4x 0 ptof4y 0 pterr 0 ptrefset 0 ptmot x40800000 ptref 0}}}}}
toolbar_output_a_warped false
toolbar_output_ab true
toolbar_output_enum AB
toolbar_preview_mode "persistent preview"
name SplineWarp3_1
selected true
xpos 2816
ypos 795
}
RotoPaint {
curves {{{v x3f99999a}
{f 0}
{n
{layer Root
{f 2097152}
{t x44700000 x44070000}
{a pt1x 0 pt1y 0 pt2x 0 pt2y 0 pt3x 0 pt3y 0 pt4x 0 pt4y 0 ptex00 0 ptex01 0 ptex02 0 ptex03 0 ptex10 0 ptex11 0 ptex12 0 ptex13 0 ptex20 0 ptex21 0 ptex22 0 ptex23 0 ptex30 0 ptex31 0 ptex32 0 ptex33 0 ptof1x 0 ptof1y 0 ptof2x 0 ptof2y 0 ptof3x 0 ptof3y 0 ptof4x 0 ptof4y 0 pterr 0 ptrefset 0 ptmot x40800000 ptref 0}}}}}
toolbox {clone {
{ selectAll opc 0.1 bs 78.7 src 1 str 1 ssx 1 ssy 1 sf 1 }
{ createBezier str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createBezierCusped str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createBSpline str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createEllipse str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createRectangle str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createRectangleCusped str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ brush str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ eraser src 2 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ clone opc 0.1 bs 78.7 src 1 stx -62.5 sty 41.6997 str 1 ssx 1 ssy 1 sf 1 sb 1 ltn 1013 ltm 1013 ltt 0 tt 19 }
{ reveal src 3 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ dodge src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ burn src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ blur src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ sharpen src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ smear src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
} }
toolbar_opacity 0.1000000015
toolbar_brush_size 78.69999695
toolbar_brush_hardness 0.200000003
toolbar_lifetime_start 1013
toolbar_lifetime_end 1013
toolbar_paint_source fg
toolbar_source_transform_translate {-62.5 41.6996994}
toolbar_source_transform_scale {1 1}
toolbar_source_transform_center {960 540}
colorOverlay {0 0 0 0}
paint_source foreground
lifetime_type "start to frame"
lifetime_start 1013
lifetime_end 1013
view {}
motionblur_on true
brush_size 78.69999695
brush_spacing 0.05000000075
brush_hardness 0.200000003
source_black_outside true
name RotoPaint6
selected true
xpos 2816
ypos 908
}
Roto {
output alpha
replace true
curves {{{v x3f99999a}
{f 0}
{n
{layer Root
{f 2097152}
{t x44fc0000 x44bd0000}
{a pt1x 0 pt1y 0 pt2x 0 pt2y 0 pt3x 0 pt3y 0 pt4x 0 pt4y 0 ptex00 0 ptex01 0 ptex02 0 ptex03 0 ptex10 0 ptex11 0 ptex12 0 ptex13 0 ptex20 0 ptex21 0 ptex22 0 ptex23 0 ptex30 0 ptex31 0 ptex32 0 ptex33 0 ptof1x 0 ptof1y 0 ptof2x 0 ptof2y 0 ptof3x 0 ptof3y 0 ptof4x 0 ptof4y 0 pterr 0 ptrefset 0 ptmot x40800000 ptref 0}}}}}
toolbox {selectAll {
{ selectAll str 1 ssx 1 ssy 1 sf 1 }
{ createBezier str 1 ssx 1 ssy 1 sf 1 sb 1 tt 4 }
{ createBezierCusped str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createBSpline str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createEllipse str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createRectangle str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ createRectangleCusped str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ brush str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ eraser src 2 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ clone src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ reveal src 3 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ dodge src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ burn src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ blur src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ sharpen src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
{ smear src 1 str 1 ssx 1 ssy 1 sf 1 sb 1 }
} }
toolbar_brush_hardness 0.200000003
toolbar_source_transform_scale {1 1}
toolbar_source_transform_center {2016 1512}
colorOverlay {0 0 0 0}
lifetime_type "all frames"
lifetime_start 1013
lifetime_end 1013
view {}
motionblur_on true
motionblur_shutter_offset_type centred
source_black_outside true
name Roto8
selected true
xpos 2816
ypos 934
}
Blur {
channels alpha
size 10
name Blur6
label "\[value size]"
selected true
xpos 2816
ypos 972
}
Premult {
name Premult4
selected true
xpos 2816
ypos 1024
}
push 0
SplineWarp3 {
inputs 2
crop_to_format false
boundary_bbox false
output_enum "AB morph"
mix 1
curves {{{v x3f99999a}
{f 0}
{n
{layer Root
{f 512}
{t x44700000 x44070000}
{a pt1x 0 pt1y 0 pt2x 0 pt2y 0 pt3x 0 pt3y 0 pt4x 0 pt4y 0 ptex00 0 ptex01 0 ptex02 0 ptex03 0 ptex10 0 ptex11 0 ptex12 0 ptex13 0 ptex20 0 ptex21 0 ptex22 0 ptex23 0 ptex30 0 ptex31 0 ptex32 0 ptex33 0 ptof1x 0 ptof1y 0 ptof2x 0 ptof2y 0 ptof3x 0 ptof3y 0 ptof4x 0 ptof4y 0 pterr 0 ptrefset 0 ptmot x40800000 ptref 0 warp 0}}}}}
toolbar_output_a_warped false
toolbar_output_ab true
toolbar_output_enum AB
toolbar_preview_mode "persistent preview"
name SplineWarp3_2
selected true
xpos 2816
ypos 1162
}
Dot {
name Dot34
selected true
xpos 2844
ypos 1290
}
set N62200800 [stack 0]
Dot {
name Dot35
selected true
xpos 2844
ypos 1496
}
set N62200400 [stack 0]
Blur {
size 30
name Blur7
label "\[value size]"
selected true
xpos 2816
ypos 1625
}
push $N62200400
push $N6218a800
Dot {
name Dot36
selected true
xpos 2350
ypos 245
}
Shuffle {
alpha black
name Shuffle3
label "\[value in]"
selected true
xpos 2322
ypos 275
}
Dot {
name Dot37
selected true
xpos 2350
ypos 1406
}
push $N62200800
push $N621bc800
Merge2 {
inputs 2
name Merge16
selected true
xpos 3191
ypos 1292
}
Dot {
name Dot38
selected true
xpos 3219
ypos 1339
}
push $N621bd800
PSDMerge {
inputs 2
name PSDMerge1
note_font "Bitstream Vera Sans"
selected true
xpos 3527
ypos 1342
operation "linear light"
sRGB false
maskChannelInput none
}
Merge2 {
inputs 2
operation plus
name Merge17
selected true
xpos 3527
ypos 1408
}
Copy {
inputs 2
from0 rgba.alpha
to0 rgba.alpha
name Copy4
selected true
xpos 3527
ypos 1492
}
Premult {
name Premult5
selected true
xpos 3527
ypos 1530
}
GrainPro {
name GrainPro1
selected true
xpos 3527
ypos 1556
Sizes 1
inttt 1
softenChannels 1
Curve 0
lut {master {curve C 0.136069715 x0.4177164733 1}
red {}
green {}
blue {}
alpha {}}
}
push $N6218ac00
Merge2 {
inputs 2
name Merge18
selected true
xpos 3755
ypos 1556
}
Grade {
inputs 1+1
white 1.15
name Grade5
selected true
xpos 3755
ypos 1638
}
Output {
name Output1
selected true
xpos 3755
ypos 1726
}