Normalizing values - Guillermo Algora

Guillermo Algora
Go to content
First, we will see the formulas for normalizing a value to a range from 0 to 1 and a custom one. Then, we will get to the explanations of these formulas. To conclude, we will see how to retrieve maximum and minimum values in Nuke using Expressions.

1. Normalizing to a 0 to 1 range:

The formula for normalizing a value to a range from 0 to 1 is:

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 FormulaNew Value
13xn = (3 - 3) / (7-3) 0
24
xn = (4 - 3) / (7-3)
0.25
35
xn = (5 - 3) / (7-3)
0.5
46
xn = (6 - 3) / (7-3)
0.75
57
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.

2. Normalizing to a custom range:

To normalize to a range other than 0 to 1, we have to make some additions to the previous formula:

x normalized = (x - min) / (max - min) * (rmax - rmin) + rmin

rmax & rmin  =  new maximum and minimum value for the custom range.

In the following example, we will normalize to a range from
3 to 100:
Frame
Original Value
Normalization FormulaNew Value
13xn = (3 - 3) / (7-3) * (100-3) + 33
24
xn = (4 - 3) / (7-3) * (100-3) + 3
27,25
35
xn = (5 - 3) / (7-3) * (100-3) + 3
51,5
46
xn = (6 - 3) / (7-3) * (100-3) + 3
75.75
57
xn = (7 - 3) / (7-3) * (100-3) + 3
100
3. Explaining the formulas:

x normalized = (x - min) / (max - min)

(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 normalized = (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.

4. Retrieving max and min values in Nuke using Expressions:

A bit of insight on how to retrieve maximum and minimum values.

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)).

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())
Back to content