NORMALIZING / REMAPPING VALUES
Table of Contents:
2. Manual Normalization / Remapping:
1. The lerp() function
lerp(min, rmin, max, rmax, curve)
- min: the current minimum value.
- rmin: the new minimum value.
- max: the current maximum value.
- rmax: the new maximum value.
(Later, at 2.4. "Retrieving max and min values in Nuke using Expressions, we will see how to extract the minimum and maximum values from an animation curve in Nuke).
However, if we just provide the lerp() function with two numbers and what in this case is the weight, it turns itself into a linear interpolation function (also called a mix() function):
lerp or mix(value a, value b, weight)
- weight: the linear interpolation weight between value a and value b. The weight only accepts a value between 0 and 1. A weight of 0 returns value a fully while a weight of 1 returns value b, anything in between return a weighted interpolated mix.
Examples:
if value a is 0 and value b is 1, with a weight of 0.5, the resulting value would be: 0.5if value a is 5 and value b is 20, with a weight of 0.25, the resulting value would be: 12.5
This function is great for doing blends, if the weight is animated, to go from one value to another dynamically; and to generate ramps by using the image x or y position as the weight.
2. Manual Normalization / Remapping
2.1. Normalizing to a 0 to 1 range:
x normalized = (x - min) / (max - min)
x = current value
min & max = minimum and maximum value of the current range.
Let's apply the normalization formula to the following values:
Frame | Original Value | Normalization Formula | New Value |
1 | 3 | xn = (3 - 3) / (7-3) | 0 |
2 | 4 | xn = (4 - 3) / (7-3) | 0.25 |
3 | 5 | xn = (5 - 3) / (7-3) | 0.5 |
4 | 6 | xn = (6 - 3) / (7-3) | 0.75 |
5 | 7 | xn = (7 - 3) / (7-3) | 1 |
As we can see, the above values (from 3 to 7) have been normalized to their equivalents in a range from 0 to 1.
In the following example, we will remap to a range from 3 to 100:
2.2. Remapping to a custom range:
To remap to a range other than 0 to 1, we have to make some additions to the previous formula:
To remap to a range other than 0 to 1, we have to make some additions to the previous formula:
x remapped = (x - min) / (max - min) * (rmax - rmin) + rmin
rmax & rmin = new maximum and minimum value for the custom range.
In the following example, we will remap to a range from 3 to 100:
Frame | Original Value | Remap Formula | New Value |
1 | 3 | xn = (3 - 3) / (7-3) * (100-3) + 3 | 3 |
2 | 4 | xn = (4 - 3) / (7-3) * (100-3) + 3 | 27,25 |
3 | 5 | xn = (5 - 3) / (7-3) * (100-3) + 3 | 51,5 |
4 | 6 | xn = (6 - 3) / (7-3) * (100-3) + 3 | 75.75 |
5 | 7 | xn = (7 - 3) / (7-3) * (100-3) + 3 | 100 |
2.3. Explaining the formulas:
(x - min) offsets the values from the current range so that they start at 0 (the lowest value of the current range becomes 0, the rest is offset in the same amount). The result is divided by (max - min), which is the difference between the highest and the lowest value (i.e. the 'size' of the current range). This part has the function of keeping the 0 at 0 (0 divided by any number remains 0) while making the highest value in our current range become 1 (the result of max - min is equal to the highest value after the offset x - min, so the division of that number by the other -equal- returns 1). The intermediate values are proportionally adjusted.
x remapped = (x - min) / (max - min) * (rmax - rmin) + rmin
Similar to the above, * (rmax - rmin) multiplies the normalized values (from 0 to 1) into a new range by: multiplying those values by the 'size' of the new range (i.e. new range maximum - new range minimum), thus the values are proportionally adjusted to the new range while keeping the 0 at 0 (0 multiplied by any number remains 0). Then + rmin offsets all the values to start at the minimum value of the new range, which completes the operation.
These formulas are in fact equations of a straight line applying a linear interpolation.
2.4. Retrieving max and min values in Nuke using Expressions:
2.4.1 Max and min value between more than one knob:The following Expressions max (x, y, ... ), min (x, y, ... ) compare and retrieve the maximum or minimum value between more than one knob. The knobs to compare must be provided in the arguments section: (x, y, ... ) in the form of nodename.knobname.e.g. max(Multiply1.value, Multiply2.value).This method checks the value at the current frame unless specified otherwise, which is possible by adding brackets with the frame number.e.g. min(Multiply1.value(3), Multiply2.value(4)).2.4.2 Max and min value of an animated knob:To apply the normalization formula with an Expression on an animated knob, we can use brackets to indicate the frame number where the minimum and maximum values are. For this, we will use the parameter: curve(frame number)x normalized = (x - min) / (max - min) → curve = (curve - curve (frame number min value) / (curve (frame number max value) - curve (frame number min value))
- curve: retrieves the animation curve of the knob.
- (frame number): retrieves the value (from the animation curve) at the specified frame number.
Instead of manually pointing to the frame number, we can use Python to automatically iterate through the animation keys to find the minimum and maximum values (be sure to enable the 'Py' button in the Expression pop-up window). This method has the advantage of 'auto-updating' and works the same way for minimum and maximum but can be (more or less) computationally expensive depending on the number of frames to iterate.The Python command to retrieve an animation curve and its keys is:nuke.toNode('nodename')['knobname'].animation(index).keys()
- nuke.toNode: accesses the node.
- nodename: specifies the name of the node to access.
- knobname: specifies the name of the knob to access.
- animation: retrieves the animation curve object.
- index: specifies the index of the animation curve. (e.g. a Transform node: 'x' is index 0, 'y' is index 1; a Grade node: 'red' is index 0, 'green' is index 1, 'blue' is index 2; a Blur node: 'w' is index 0, 'h' is index 1, etc. i.e. the first index is 0 and so on).
- keys: retrieve the keys of the animation object.
At this point, we have accessed the keys in the animation curve for a given knob in a node. To iterate through the keys in the animation curve we add a for loop:for key in nuke.toNode('nodename')['knobname'].animation(index).keys()
- for key in: creates a 'for loop' that iterates through the keys in the animation curve.
Finally, the output from the keys itself contains an 'x' and 'y' index. The 'frame number' is stored in the 'x' index, while the 'value' is stored in the 'y', which we access with the following command:key.y for key in nuke.toNode('nodename')['knobname'].animation(index).keys()
- key.y: retrieves the value from the key index 'y'.
Finally, to retrieve the minimum or maximum value in the iterated keys, we add the min() and max() function:
max(key.y for key in nuke.toNode('nodename')['knobname'].animation(index).keys())min(key.y for key in nuke.toNode('nodename')['knobname'].animation(index).keys())e.g. min(key.y for key in nuke.toNode('Multiply1)['value'].animation(0).keys())