-
Recent Comments
- pralhad on Colour Smear for Nuke (UPDATE v2.0):
i use this node education parpose - Francois Leduc on FrameBlendMerge:
You could also use a TimeEcho node. There’s no Min mode, but to fix that, apply a Invert Node to your source, plug TimeEcho (in Max method) and apply another Invert node after. Go at the end of your timeline, change the “Frames to look at” to the number of frames or your shot (or less) and you should get your clean plate. Of course all of this is done on a stabilized shot. - Richard Frazer on Colour Smear for Nuke (UPDATE v2.0):
Hi Josh. Thanks for the feedback. You have correctly discovered that this tool works best when you have a solid core for a matte with a feathered edge. Where it fails is if you have large areas that just have semi transparent alpha (such as your grimy window). I’d approach this by separating your actor with a rough roto and using the colour smear to deal with their edges. Then for the smudges maybe try extracting the green channel and using using it to drive a grade for your background, or... - Josh Northeast on Colour Smear for Nuke (UPDATE v2.0):
Hey Richard! Absolutely love the tool. Saved my ass alot. I’m working with some greenscreen plates where there is a smudgy window behind the actor and a greenscreen behind that. We need to preserve the smudges on the window but that means it’s hard to use your tool to treat the edges because the alpha isn’t clean. Any tips? Cheers, Josh - Matt on Keyframe Reduction script for Nuke:
Nice! Just used this on a projection/stabilization job and it worked great to simplify the original camera keyframes and smooth out the reprojected shot. Thanks!
- pralhad on Colour Smear for Nuke (UPDATE v2.0):

Keyframe Reduction script for Nuke
February 02, 2015
THE PROBLEM
I came across this issue when importing tracking data from PFTrack into Nuke, but it is equally relevant to tracking data create with a nuke Tracker node, or any animation data that gets “baked”.
The curves of a simple animation can be created using a small number of keyframes in the Curve Editor. However sometimes the animation gets baked in i.e. a keyframe is created on every frame. If we want to adjust the animation by dragging keyframes in the Curve Editor it is a lot easier to do so with keyframes only occurring at zenith points.
Here we see our original curves that require only 28 keyframes over a 100 frame range. Below it is the baked version, where we get 100 keyframes over 100 frames.
I wanted to find a way of un-baking the keyframes and returning to our animation curve being created using the minimal amount of keyframes possible.
The only existing method I found was a script by Julik Tarkhanov called reducer.py. His script works by iterating through each keyframe and comparing its derivative to the derivative of the previous keyframe. Where the difference in angle is small, the keyframe is removed. This works well for sections of the animation curve that are straight lines, but has limitations*. It did, however, give me a lot of help when it came to creating my own version.
I looked into a lot of research papers and settled on “Keyframe Reduction Techniques for Motion Capture Data” as the method to replicate. The proposed “curve simplification” algorithm seemed like something I could recreate using Python.
THE SOLUTION
Our script begins by launching a custom panel so that the user can input a range of frames in which the baked keyframes exist (tFrameRange) and a target error threshold (tErrorThreshold).
It then creates a new temporary knob (tTempKnob) with no keyframes in which to create our new animation curve (tTempCurve). It then places a keyframe on the first and last frame of the animation, creating a straight line in our tTempCurve.
Next we want to look at the frames in our original curve (tOriginalCurve) and find their distance from our new curve. This presented an interesting challenge as the distance had be to on a line perpendicular to our tTempCurve. Time to remember some basic maths from school. If we look at our Curve Editor and think of the frame number as our x axis and the value of the knob as the y axis, then we can take the triangle between our first and last frame and use trigonometry to calculate the angle of the slope in our new new curve (tMasterSlope). We can then create a triangle for each frame, taking the difference between the values on the y axis to give us a length of the ‘hypotenuse’ side, and use a ‘sin’ function to find the length of the ‘opposite’ side – which is the distance value needed.
We loop through each frame and find this distance, which is our “error value”. Here we loop through 100 frames and frame 76 produces the highest error value.
The frame that produces the highest error value (76) then gets turned into a keyframe.
This divides our new tTempCurve into 2 sections – frames 1-76 and frames 76-100. Our script then takes each of these sections and recursively runs the same function on them, iterating through each frame and finding the greatest error value.
These two new error frames are turned into keyframes and our script continues on the 4 new sections created, recursively calling itself each time.
Each time a section of the curve is scanned for placing a new keyframe it is also checked for how much it differs from our original curve, with this value being represented as a percentage of the overall height. If this error percentage is below our tErrorThreshold, then this section is considered to be close enough to our original and is no longer sub-divided. Here I have set the target error threshold to be 1%, which results in the final curve below
We have reduced down to only 51 keyframes – not quite as low as our original 28 keyframes, but still a reduction to half of the number in our baked version. Playing with the error threshold value (i.e. increasing it to of 3%) results in a reduction to fewer keyframes (only 27), but areas of lower accuracy.
ADDITIONAL CONSIDERATIONS
The script works well for most standard knobs that we find in most commonly used nodes. However it fails when we try to run it on animations that occur on Beziers or Layers in a RotoPaint node. Our script has a function called getKnobName which is designed to return the name of the knob on which we are running the script (i.e. “rotate”, translate.x” etc.). The RotoPaint node has a knob called “curves”, under which all transforms for Beziers and Layers fall, so the knob names returned tend to be called things like “curves.rotate” or “curves.Bezier1.translate.x”. There should be a way of easily accessing these animations, but I need to look more into the _curvelib.AnimCTransform object as it gets a bit inconsistent with syntax.
THE PYTHON SCRIPT
The full script for reduceKeyframes.py can be found here on GitHub
The script needs to be installed under the “Animation” sub menu, so it should be copied into your .nuke folder as “reduceKeyframes.py” and your menu.py file should be modified with the following lines:
import reduceKeyframes m=nuke.menu( 'Animation' ) m.addCommand( 'Reduce Keyframes', "reduceKeyframes.doReduceKeyframes()" )
This makes the “Reduce Keyframes” option appear if your right-click on the knob in the “Properties” panel
** UPDATE 16/02/14 **
Apparently the newer Tracker node introduced in Nuke 8 will not run this script as the copyAnimation() function fails (the “tracks” knob isn’t exposed as an Array_Knob, or a subclass thereof). I will write a workaround when I next have access to the latest copy of Nuke
*Julik describes his method as being based on the concept of Curve-fitting compaction, specifically citing the paper Data Reduction of Piecewise Linear Curves by Erlend Arge and Morten Dæhlen.
He points out that “curve fitting is never lossless, and for some values even small deviations from the baked values could produce wildly different images – depending to which parameter you apply it to. It can be disastrous for camera tracks for example, and normally when you have dense curves they are dense for a reason.”
3 Responses to "Keyframe Reduction script for Nuke"
Karpenko says: February 24, 2015 at 10:51 pm
Nuke 7 and 8 with the same error: “IndexError: tuple index out of range.”
Matt says: May 16, 2019 at 5:39 pm
Nice! Just used this on a projection/stabilization job and it worked great to simplify the original camera keyframes and smooth out the reprojected shot. Thanks!
Nuke 8v4 crashed at this line (186):
#copy our reduced keyframes from the temp knob back into our original knob
x[knob_name].copyAnimation(j, tTempKnob.animation(0))