Skip to content

I’d like to see the math behind your motion vectors

We assume that X is positive going from left to right. And the positive Y designates motion going UP.

We assume that X,Y vector information is encoded in the red and green channels of the image. In addition we assume the vector information has been normalized so that both X and Y range from -1 to 1, presumably using some constant value to divide the X and Y component values. We’ll call this normalization value the Max Displace value. The blue channel is often ignored.

More about alpha use in the motion vector format

8 bits per channel

In 8 bits per channel, we assume that -1 corresponds to pixel value of 0 and that +1 corresponds to 254. We have chosen to map (-1,+1) to (0,254) because with this scheme we can represent a 0 displacement with a pixel value of 127 (in a scheme that maps (-1,+1) to (0, 255), a 0 displacement value corresponds to pixel value of 127.5, which cannot be represented exactly).

So you can convert floating point motion vectors X,Y to 8 bit red,green values with the following pseudo-code:

// We wish to map (-MaxDisplace, +MaxDisplace) to (0,254)

//First, map (-MaxDisplace to +MaxDisplace) to (0, 1)
float fred = ((x/MaxDisplace)+1)*0.5;

/* clamp values if needed */
if (fred<0) fred = 0;
 if (fred>1) fred = 1;

* assign pixel value *
unsigned char red = fred*254.0 + 0.5; 
/* rounding is preferred to truncation, but this is your choice */

* float fgreen = ((y/MaxDisplace)+1)*0.5;
if (fgreen<0) fgreen = 0;
if (fgreen>1) fgreen = 1;
unsigned char green = fgreen*254.0 + 0.5; 
/* rounding is preferred to truncation, but that's your choice */ 
16 bits per channel

In 16 bpc, we map (-MaxDisplace,+MaxDispalce) to (0, 65534) (note: the maximum is 64434 and not 65535). When saving 16 bits per channel the formulae become:

* // First, map -MaxDisplace to MaxDisplace to 0 to 1
float fred = ((x/MaxDisplace)+1)*0.5;

/* clamp values if needed */
if (fred<0) fred = 0;
if (fred>1) fred = 1;

/* assign pixel value */
unsigned short red = fred*65534.0 + 0.5;
/* rounding is preferred to truncation, but that's your choice */

* float fgreen = ((y/MaxDisplace)+1)*0.5;
if (fgreen<0) fgreen = 0;
if (fgreen>1) fgreen = 1;
unsigned short green = fgreen*65534.0+0.5. 
Floating point

For floating point images, we map (-MaxDisplace,+MaxDisplace) to (0,1). When saving floating point images the formulae become:

* // First, map -MaxDisplace to MaxDisplace to 0 to 1
float fred = ((x/MaxDisplace)+1)*0.5;
/* clamp values if needed */
if (fred<0) fred = 0;
if (fred>1) fred = 1;

* float fgreen = ((y/MaxDisplace)+1)*0.5;
if (fgreen<0) fgreen = 0;
if (fgreen>1) fgreen = 1