MV2DArray, MV2DPtr, and MV2DMask
MV2DArray
is based on MVArray
, but it stores 2-dimensional
[ horizontal, vertical ]
motion vectors instead of a single array.
MV2DArray
provides optimized functions which can greatly speed up
processing large chunks of 2-dimensional motion vectors.
MV2DArray
is fixed length
, which means that once it is created, it
cannot be made larger or smaller.
MV2DArray
is a dense array
(in contrast to a sparse array
), which
means there are no holes in the array.
All rows are available as MVPtr
s.
If any motion vector in a row is not available (i.e.: it wasn’t
available in the input file to start with) it will be represented as a
null
, but it will be an MV(null)
, so all the methods from MV
can
be used. All motion vectors from [0][0]
to [height-1][width-1]
can
be read/written.
MV2DPtr
is very similar to MV2DArray
, and shares all the same
methods. The main difference is that MV2DPtr
does not have any memory
allocated for its data. Instead, it points to data from MV2DArray
.
Be careful not to play around with MV2DPtr
s once the object they were
created from has run out of its scope. You will write into unallocated
memory and the program will segfault.
MV2DMask
is a 2-dimensional array of boolean
s that can be used with
certain methods from MV2DArray
/MV2DPtr
. This allows for very
efficient code which does not need to check for conditions inside loops
every time. The conditions are tested once to create the MV2DMask
,
and then the mask is applied on subsequent calls.
All of MV2DArray
, MV2DPtr
, and MV2DMask
contain a width
and
height
constant property, determined at creation time.
MV2DArray Constructor
The constructor is used to create a new MV2DArray
object of width
width
and height height
. All motion vectors are initialized to
[0,0]
.
Syntax
new MV2DArray(width, height)
Parameters
width
must be a non-zero positive number that specifies the width
of the 2-dimensional array to be created.
height
must be a non-zero positive number that specifies the height
of the 2-dimensional array to be created.
Return value
The new MV2DArray
object.
Examples
const mv2darr = new MV2DArray(3, 2);
print(mv2darr);
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[0,0],[0,0]]
// ]
print(mv2darr.width);
// 3
print(mv2darr.height);
// 2
MV2DPtr Constructor
The constructor is used to create a new MV2DPtr
object from either an
MV2DArray
object or another MV2DPtr
object. The new object will
have the same width/height as the source
object.
Syntax
new MV2DPtr(source)
Parameters
source
must be either an MV2DArray
or an MV2DPtr
object.
Return value
The new MV2DPtr
object.
Examples
const mv2darr = new MV2DArray(3, 2);
print(mv2darr);
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[0,0],[0,0]]
// ]
print(mv2darr instanceof MV2DArray); // true
print(mv2darr instanceof MV2DPtr); // false
const mv2dptr = new MV2DPtr(mv2darr);
print(mv2dptr instanceof MV2DArray); // false
print(mv2dptr instanceof MV2DPtr); // true
mv2dptr[1][1] = MV(1,1);
print(mv2darr);
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[1,1],[0,0]]
// ]
print(mv2dptr);
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[1,1],[0,0]]
// ]
print(mv2dptr.width);
// 3
print(mv2dptr.height);
// 2
MV2DMask Constructor
The constructor is used to create a new MV2DMask
object of width
width
and height height
. All elements are initialized to true
.
Syntax
new MV2DMask(width, height)
Parameters
width
must be a non-zero positive number that specifies the width
of the 2-dimensional mask array to be created.
height
must be a non-zero positive number that specifies the height
of the 2-dimensional mask array to be created.
Return value
The new MV2DMask
object.
Examples
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask);
// [
// [true,true,true],
// [true,true,true]
// ]
for ( let i = 0; i < mv2dmask.height; i++ )
for ( let j = 0; j < mv2dmask.width; j++ )
mv2dmask[i][j] = ((i+j) & 1);
print(mv2dmask);
// [
// [false,true,false],
// [true,false,true]
// ]
print(mv2dmask.width);
// 3
print(mv2dmask.height);
// 2
MV2DArray.prototype.toString()
The toString()
method returns a string representing the specified
2-dimensional array and its motion vectors.
Syntax
toString()
Return value
The string representation.
Examples
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask.toString());
// [
// [true,true,true],
// [true,true,true]
// ]
MV2DArray.prototype.subarray()
The subarray()
method returns an MV2DPtr
that points to a chunk of
data inside the current object, starting from index begin
and ending
in index end
.
Syntax
subarray()
subarray(begin)
subarray(begin, end)
Parameters
begin
(optional) is the starting [horizontal, vertical]
index where
the new object will point to.
If this value is omitted, begin
is [0,0]
.
end
(optional) is the end [horizontal, vertical]
index where the
new object will point to.
If this value is omitted, end
is [width,height]
.
Note: the begin
and end
parameters can contain negative values.
In that case, the values wrap around from the last index.
Return value
The new MV2DPtr
object.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
const mv2dptr = mv2darr.subarray();
print(mv2dptr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
print(mv2dptr instanceof MV2DArray); // false
print(mv2dptr instanceof MV2DPtr); // true
print(mv2darr.subarray([0,1]));
// [
// [[1,0],[1,1],[1,2]]
// ]
print(mv2darr.subarray([0,-1]));
// [
// [[1,0],[1,1],[1,2]]
// ]
print(mv2darr.subarray([1,1], [3,2]));
// [
// [[1,1],[1,2]]
// ]
MV2DArray.prototype.fill()
The fill()
method fills all the motion vectors of a 2-dimensional
array from an start
index to an end
index with a motion vector
mv
.
Syntax
fill(mv)
fill(mv, start)
fill(mv, start, end)
Parameters
mv
to fill the array with.
start
(optional) is the [horizontal, vertical]
index where the
filling starts.
If this value is omitted, begin
is [0,0]
.
end
(optional) is the end [horizontal, vertical]
index where the
filling starts.
If this value is omitted, end
is [width,height]
.
Note: the start
and end
parameters can contain negative values.
In that case, the values wrap around from the last index.
Return value
The modified 2-dimensional motion vector array.
Examples
const mv2darr = new MV2DArray(3, 2);
print(mv2darr);
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[0,0],[0,0]]
// ]
print(mv2darr.fill(MV(1,1)));
// [
// [[1,1],[1,1],[1,1]],
// [[1,1],[1,1],[1,1]]
// ]
print(mv2darr.fill(MV(2,2), [1,0]));
// [
// [[1,1],[2,2],[2,2]],
// [[1,1],[2,2],[2,2]]
// ]
print(mv2darr.fill(MV(3,3), [1,0], [2,2]));
// [
// [[1,1],[3,3],[2,2]],
// [[1,1],[3,3],[2,2]]
// ]
MVArray.prototype.reverse()
The reverse()
method reverses all motion vectors in the 2-dimensional
array in-place, both horizontally and vertically.
This operation applies to the entire 2-dimensional array (there are no
range arguments).
If you want to reverse just a small chunk of the array, use the
subarray()
method and call reverse()
on that.
Syntax
reverse()
Return value
The modified 2-dimensional motion vector array.
Examples
const mv2darr = new MV2DArray(3, 4);
mv2darr.forEach((mv, i, j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]],
// [[2,0],[2,1],[2,2]],
// [[3,0],[3,1],[3,2]]
// ]
print(mv2darr.reverse());
// [
// [[3,2],[3,1],[3,0]],
// [[2,2],[2,1],[2,0]],
// [[1,2],[1,1],[1,0]],
// [[0,2],[0,1],[0,0]]
// ]
const subarray = mv2darr.subarray([1,1], [3,3]);
print(subarray);
// [
// [[2,1],[2,0]],
// [[1,1],[1,0]]
// ]
print(subarray.reverse());
// [
// [[1,0],[1,1]],
// [[2,0],[2,1]]
// ]
print(mv2darr);
// [
// [[3,2],[3,1],[3,0]],
// [[2,2],[1,0],[1,1]],
// [[1,2],[2,0],[2,1]],
// [[0,2],[0,1],[0,0]]
// ]
MVArray.prototype.reverse_h()
The reverse_h()
method reverses all motion vectors in the
2-dimensional array in-place, but only horizontally.
This operation applies to the entire 2-dimensional array (there are no
range arguments).
If you want to horizontally reverse just a small chunk of the array,
use the subarray()
method and call reverse_h()
on that.
Syntax
reverse_h()
Return value
The modified 2-dimensional motion vector array.
Examples
const mv2darr = new MV2DArray(3, 4);
mv2darr.forEach((mv, i, j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]],
// [[2,0],[2,1],[2,2]],
// [[3,0],[3,1],[3,2]]
// ]
print(mv2darr.reverse_h());
// [
// [[0,2],[0,1],[0,0]],
// [[1,2],[1,1],[1,0]],
// [[2,2],[2,1],[2,0]],
// [[3,2],[3,1],[3,0]]
// ]
const subarray = mv2darr.subarray([1,1], [3,3]);
print(subarray);
// [
// [[1,1],[1,0]],
// [[2,1],[2,0]]
// ]
print(subarray.reverse_h());
// [
// [[1,0],[1,1]],
// [[2,0],[2,1]]
// ]
print(mv2darr);
// [
// [[0,2],[0,1],[0,0]],
// [[1,2],[1,0],[1,1]],
// [[2,2],[2,0],[2,1]],
// [[3,2],[3,1],[3,0]]
// ]
MVArray.prototype.reverse_v()
The reverse_v()
method reverses all motion vectors in the
2-dimensional array in-place, but only vertically.
This operation applies to the entire 2-dimensional array (there are no
range arguments).
If you want to vertically reverse just a small chunk of the array, use
the subarray()
method and call reverse_v()
on that.
Syntax
reverse_v()
Return value
The modified 2-dimensional motion vector array.
Examples
const mv2darr = new MV2DArray(3, 4);
mv2darr.forEach((mv, i, j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]],
// [[2,0],[2,1],[2,2]],
// [[3,0],[3,1],[3,2]]
// ]
print(mv2darr.reverse_v());
// [
// [[3,0],[3,1],[3,2]],
// [[2,0],[2,1],[2,2]],
// [[1,0],[1,1],[1,2]],
// [[0,0],[0,1],[0,2]]
// ]
const subarray = mv2darr.subarray([1,1], [3,3]);
print(subarray);
// [
// [[2,1],[2,2]],
// [[1,1],[1,2]]
// ]
print(subarray.reverse_v());
// [
// [[1,1],[1,2]],
// [[2,1],[2,2]]
// ]
print(mv2darr);
// [
// [[3,0],[3,1],[3,2]],
// [[2,0],[1,1],[1,2]],
// [[1,0],[2,1],[2,2]],
// [[0,0],[0,1],[0,2]]
// ]
MV2DArray.prototype.slice()
The slice()
method returns a new MV2DArray
object with a copy of
the data specified in the (optional) start
and end
range arguments.
If no range is specified, the entire 2-dimensional array is copied,
effectively performing a deep copy
of the current object.
Syntax
slice()
slice(start)
slice(start, end)
Parameters
start
(optional) is the [horizontal, vertical]
index where the
filling starts.
If this value is omitted, begin
is [0,0]
.
end
(optional) is the end [horizontal, vertical]
index where the
filling starts.
If this value is omitted, end
is [width,height]
.
Note: the start
and end
parameters can contain negative values.
In that case, the values wrap around from the last index.
Return value
The new MV2DArray
object.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
const mv2dslc = mv2darr.slice();
mv2dslc[1][1] = MV(3,3);
print(mv2dslc);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[3,3],[1,2]]
// ]
print(mv2darr.slice([1,0]));
// [
// [[0,1],[0,2]],
// [[1,1],[1,2]]
// ]
print(mv2darr.slice([1,0], [2,2]));
// [
// [[0,1]],
// [[1,1]]
// ]
MV2DArray.prototype.dup()
The dup()
method performs a deep copy
of the current object.
It has the same behaviour as calling slice()
with no range arguments.
Syntax
dup()
Return value
The new MV2DArray
object.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
const mv2ddup = mv2darr.dup();
mv2ddup[1][1] = MV(3,3);
print(mv2ddup);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[3,3],[1,2]]
// ]
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
MV2DArray.prototype.every()
The every()
method tests whether every motion vector in the
2-dimensional array passes the test implemented by the callbackFn
function.
If any motion vector does not pass the test, the method returns
early with false
.
Syntax
every(callbackFn(mv, i, j, array))
every(callbackFn(mv, i, j, array), thisArg)
Parameters
callbackFn
is a function (inline
, arrow
, or normal) that is
called for each motion vector of the 2-dimensional array.
The function’s parameters are mv
(an MVRef
to the current motion
vector being tested), i
(the vertical index it corresponds to in the
2-dimensional array), j
(the horizontal index it correspons to in the
2-dimensional array), and array
(the 2-dimensional array itself).
The function should return either true
or false
.
thisArg
(optional) is a value to use as this
when executing
callbackFn
.
Return value
true
or false
.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
print(mv2darr.every((mv,i,j) => mv[0] == i && j == mv[1])); // true
print(mv2darr.every((mv) => mv[0] >= 0)); // true
print(mv2darr.every((mv) => mv[0] > 0)); // false
MV2DArray.prototype.some()
The some()
method tests whether at least one motion vector in the
2-dimensional array passes the test implemented by the callbackFn
function.
If any motion vector does pass the test, the method returns early
with true
.
Syntax
some(callbackFn(mv, i, j, array))
some(callbackFn(mv, i, j, array), thisArg)
Parameters
callbackFn
is a function (inline
, arrow
, or normal) that is
called for each motion vector of the 2-dimensional array.
The function’s parameters are mv
(an MVRef
to the current motion
vector being tested), i
(the vertical index it corresponds to in the
2-dimensional array), j
(the horizontal index it correspons to in the
2-dimensional array), and array
(the 2-dimensional array itself).
The function should return either true
or false
.
thisArg
(optional) is a value to use as this
when executing
callbackFn
.
Return value
true
or false
.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
print(mv2darr.some((mv) => mv[0] <= 0)); // true
print(mv2darr.some((mv) => mv[0] < 0)); // false
MV2DArray.prototype.forEach()
The forEach()
method calls the callbackFn
function for each motion
vector of the 2-dimensional array. It has the same functionality as
calling the code below, but it’s slightly faster.
Note that you can modify mv
directly, since it is passed as an
MVRef
.
for ( let i = 0; i < mv2darr.height; i++ )
for ( let j = 0; j < mv2darr.width; j++ )
callbackFn(mv2darr[i][j], i, j, mv2darr);
Syntax
forEach(callbackFn(mv, i, j, array))
forEach(callbackFn(mv, i, j, array), thisArg)
Parameters
callbackFn
is a function (inline
, arrow
, or normal) that is
called for each motion vector of the 2-dimensional array.
The function’s parameters are mv
(an MVRef
to the current motion
vector being tested), i
(the vertical index it corresponds to in the
2-dimensional array), j
(the horizontal index it correspons to in the
2-dimensional array), and array
(the 2-dimensional array itself).
thisArg
(optional) is a value to use as this
when executing
callbackFn
.
Return value
undefined
.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
mv2darr.forEach((mv) => mv = MV(4,4));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
// Note that the previous call to `forEach()` did not modify the array
// since the scoped variable mv was replaced instead of modified.
mv2darr.forEach((mv) => mv[0] = 0);
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[0,0],[0,1],[0,2]]
// ]
function is_zero_zero(mv, i, j) {
const not_str = (mv.compare_neq(0,0)) ? "not " : "";
print(`mv [${i}][${j}] is ${mv}, which is ${not_str}[zero,zero]`);
}
mv2darr.forEach(is_zero_zero);
// mv [0][0] is [0,0], which is [zero,zero]
// mv [0][1] is [0,1], which is not [zero,zero]
// mv [0][2] is [0,2], which is not [zero,zero]
// mv [1][0] is [0,0], which is [zero,zero]
// mv [1][1] is [0,1], which is not [zero,zero]
// mv [1][2] is [0,2], which is not [zero,zero]
MV2DArray.prototype.maskedForEach()
The maskedForEach()
method calls the callbackFn
function for each
motion vector of the 2-dimensional array that is selected by the
mv2dmask
argument.
It has the same functionality as calling the code below, but it’s
slightly faster.
Note that you can modify mv
directly, since it is passed as an
MVRef
.
for ( let i = 0; i < mv2darr.height; i++ )
for ( let j = 0; j < mv2darr.width; j++ )
if ( mv2dmask[i][j] )
callbackFn(mv2darr[i][j], i, j, mv2darr);
Syntax
maskedForEach(mv2dmask, callbackFn(mv, i, j, array))
maskedForEach(mv2dmask, callbackFn(mv, i, j, array), thisArg)
Parameters
mv2dmask
is an MV2DMask
that specifies on which motion vectors the
callbackFn
function should be called on.
callbackFn
is a function (inline
, arrow
, or normal) that is
called for each motion vector of the 2-dimensional array.
The function’s parameters are mv
(an MVRef
to the current motion
vector being tested), i
(the vertical index it corresponds to in the
2-dimensional array), j
(the horizontal index it correspons to in the
2-dimensional array), and array
(the 2-dimensional array itself).
thisArg
(optional) is a value to use as this
when executing
callbackFn
.
Return value
undefined
.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
const mv2dmask = new MV2DMask(3, 2);
mv2dmask.forEach((_,i,j,arr) => arr[i][j] = (i == j));
print(mv2dmask);
// [
// [true,false,false],
// [false,true,false]
// ]
mv2darr.maskedForEach(mv2dmask, (mv) => mv.assign(MV(3,3)));
print(mv2darr);
// [
// [[3,3],[0,1],[0,2]],
// [[1,0],[3,3],[1,2]]
// ]
MV2DArray.prototype.map()
The map()
method creates a new MV2DArray
and calls the callbackFn
on each motion vector of the 2-dimensional source array, storing the
result in the corresponding motion vector in the new 2-dimensional
array.
Syntax
map(callbackFn(mv, i, j, array))
map(callbackFn(mv, i, j, array), thisArg)
Parameters
callbackFn
is a function (inline
, arrow
, or normal) that is
called for each motion vector of the 2-dimensional array.
The function’s parameters are mv
(an MVRef
to the current motion
vector being tested), i
(the vertical index it corresponds to in the
2-dimensional array), j
(the horizontal index it correspons to in the
2-dimensional array), and array
(the 2-dimensional array itself).
The function should return a motion vector value to be stored in the
new 2-dimensional array.
thisArg
(optional) is a value to use as this
when executing
callbackFn
.
Return value
The new MV2DArray
object.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
const mv2dmap = mv2darr.map((mv) => MV(mv[0]+2,mv[1]+2));
print(mv2dmap);
// [
// [[2,2],[2,3],[2,4]],
// [[3,2],[3,3],[3,4]]
// ]
MV2DArray.prototype.largest_sq()
The largest_sq()
method returns an [ index, mv.magnitude_sq() ]
array with the index and the value of the squared magnitude of the
motion vector with the largest squared magnitude in the 2-dimensional
array.
Syntax
largest_sq()
Return value
An [ i, j, mv.magnitude_sq() ]
array of the largest motion vector.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i+2,j+2)));
print(mv2darr);
// [
// [[2,2],[2,3],[2,4]],
// [[3,2],[3,3],[3,4]]
// ]
print(mv2darr.largest_sq()); // 1,2,25
// array element [1][2] ([3,4]) has a squared magnitude of 3*3+4*4 = 25.
MV2DArray.prototype.smallest_sq()
The smallest_sq()
method returns an [ index, mv.magnitude_sq() ]
array with the index and the value of the squared magnitude of the
motion vector with the smallest squared magnitude in the 2-dimensional
array.
Syntax
smallest_sq()
Return value
An [ i, j, mv.magnitude_sq() ]
array of the smallest motion vector.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i+2,j+2)));
print(mv2darr);
// [
// [[2,2],[2,3],[2,4]],
// [[3,2],[3,3],[3,4]]
// ]
print(mv2darr.smallest_sq()); // 0,0,8
// array element [0][0] ([2,2]) has a squared magnitude of 2*2+2*2 = 8.
MV2DArray.prototype.swap_hv()
The swap_hv()
method swaps the horizontal and vertical elements of
all the motion vectors in the 2-dimensional array in-place.
If you want to swap just a small chunk of the 2-dimensional array, use
the subarray()
method and call swap_hv()
on that.
Syntax
swap_hv()
Return value
The modified 2-dimensional motion vector array.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
print(mv2darr.swap_hv());
// [
// [[0,0],[1,0],[2,0]],
// [[0,1],[1,1],[2,1]]
// ]
print(mv2darr);
// [
// [[0,0],[1,0],[2,0]],
// [[0,1],[1,1],[2,1]]
// ]
MV2DArray.prototype.clear()
The clear()
method zeroes the horizontal and vertical elements of all
of the motion vectors in the 2-dimensional array in-place.
If you want to clear just a small chunk of the 2-dimensional array, use
the subarray()
method and call clear()
on that.
Syntax
clear()
Return value
The modified 2-dimensional motion vector array.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
print(mv2darr.clear());
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[0,0],[0,0]]
// ]
print(mv2darr);
// [
// [[0,0],[0,0],[0,0]],
// [[0,0],[0,0],[0,0]]
// ]
MV2DArray.prototype.mathOp()
There is no real mathOp()
method in the MV2DArray
prototype.
Instead, there are a bunch of math operation methods, listed below:
add()
sub()
mul()
div()
assign()
The arguments passed to the methods above should first start with a source of motion vectors, and then an optional mask.
The source of motion vectors should be either an MV2DArray
(of the
same width/height as the 2-dimensional array), an MVArray
(of the
same length as the 2-dimensional array’s width), null
(only for the
assign
operation), an MV
constant, an MV
object, or an MVRef
object, or a motion vector specified in terms of its horizontal and
vertical components.
The mask
argument is optional, and it should be either an MV2DMask
(of the same width/height as the 2-dimensional array), or an MVMask
(of the same length as the 2-dimensional array’s width). If a mask is
supplied, the operation is only applied to the motion vectors selected
by the mask.
The operations do exactly what the names mean. add()
will add the
argument to the 2-dimensional motion vector array, sub()
will
subtract, mul()
will multiply, div()
will divide (rounding to
nearest integer), and assign()
will assign (just copy).
If the motion vector source is a single motion vector, that motion
vector will be applied to the entire 2-dimensional array. If the motion
vector source is an MV2DArray
, each element in the MV2DArray
will
be applied to the corresponding element of the 2-dimensional array. If
the motion vector source is an MVArray
, each element in the MVArray
will be applied to the corresponding element of each row of the
2-dimensional array.
There are also similar methods that operate only on the horizontal or
vertical elements of the 2-dimensional motion vector array. These
methods have either _h
(horizontal) or _v
(vertical) appended to
the names.
These methods also take a mandatory source of motion vectors as
argument, and then an optional mask. They can also take only one
argument (the horizontal
or vertical
element) as motion vector
source.
They are listed below:
add_h()
sub_h()
mul_h()
div_h()
assign_h()
add_v()
sub_v()
mul_v()
div_v()
assign_v()
Syntax
mathOp(mv2darray)
mathOp(mvarray)
mathOp(null)
mathOp(mv)
mathOp(horizontal, vertical)
mathOp(mv2darray, mask)
mathOp(mvarray, mask)
mathOp(null, mask)
mathOp(mv, mask)
mathOp(horizontal, vertical, mask)
mathOp_h(mv2darray)
mathOp_h(mvarray)
mathOp_h(mv)
mathOp_h(horizontal, vertical)
mathOp_h(horizontal)
mathOp_h(mv2darray, mask)
mathOp_h(mvarray, mask)
mathOp_h(mv, mask)
mathOp_h(horizontal, vertical, mask)
mathOp_h(horizontal, mask)
mathOp_v(mv2darray)
mathOp_v(mvarray)
mathOp_v(mv)
mathOp_v(horizontal, vertical)
mathOp_v(vertical)
mathOp_v(mv2darray, mask)
mathOp_v(mvarray, mask)
mathOp_v(mv, mask)
mathOp_v(horizontal, vertical, mask)
mathOp_v(vertical, mask)
Parameters
mv2darray
(optional) is an MV2DArray
object.
mvarray
(optional) is an MVArray
object.
mv
(optional) must be either an MV
constant, an MV
object, or an MVRef
object.
horizontal
(optional) is the horizontal component of the motion vector.
vertical
(optional) is the vertical component of the motion vector.
mask
(optional) is either an MV2DMask
that specifies on which
motion vectors of the 2-dimensional array the operation should be
carried out on, or an MVMask
that specifies on which motion vectors
for each row of the 2-dimensional array the operation should be carried
out on.
Return value
The modified 2-dimensional motion vector array.
Examples
// create sources of motion vectors
const mv2dsrc = new MV2DArray(3, 2);
mv2dsrc.forEach((_,i,j,arr) => arr[i][j] = MV(i+j+1,i-j-1));
const mvarr = mv2dsrc[0].dup();
const mvsrc = new MV(mvarr[0]);
print(mv2dsrc instanceof MV2DArray); // true
print(mvarr instanceof MVArray); // true
print(mvsrc instanceof MV); // true
print(mv2dsrc);
// [
// [[1,-1],[2,-2],[3,-3]],
// [[2,0],[3,-1],[4,-2]]
// ]
print(mvarr);
// [1,-1],[2,-2],[3,-3]
print(mvsrc);
// [1,-1]
// create mask
const mv2dmask = new MV2DMask(3, 2);
mv2dmask.forEach((_,i,j,arr) => arr[i][j] = ((i+j) & 1));
const mvmask = mv2dmask[0];
print(mv2dmask instanceof MV2DMask); // true
print(mvmask instanceof MVMask); // true
print(mv2dmask);
// [
// [false,true,false],
// [true,false,true]
// ]
print(mvmask);
// false,true,false
// create work mv2darray
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i,j)));
// good luck keeping track of the value of the motion vectors!
print(mv2darr);
// [
// [[0,0],[0,1],[0,2]],
// [[1,0],[1,1],[1,2]]
// ]
print("add");
// add
print(mv2darr.add(mv2dsrc));
// [
// [[1,-1],[2,-1],[3,-1]],
// [[3,0],[4,0],[5,0]]
// ]
print(mv2darr.add(mvarr));
// [
// [[2,-2],[4,-3],[6,-4]],
// [[4,-1],[6,-2],[8,-3]]
// ]
print(mv2darr.add(mvsrc));
// [
// [[3,-3],[5,-4],[7,-5]],
// [[5,-2],[7,-3],[9,-4]]
// ]
print(mv2darr.add(mv2dsrc, mv2dmask));
// [
// [[3,-3],[7,-6],[7,-5]],
// [[7,-2],[7,-3],[13,-6]]
// ]
print(mv2darr.add(mvarr, mv2dmask));
// [
// [[3,-3],[9,-8],[7,-5]],
// [[8,-3],[7,-3],[16,-9]]
// ]
print(mv2darr.add(mvsrc, mv2dmask));
// [
// [[3,-3],[10,-9],[7,-5]],
// [[9,-4],[7,-3],[17,-10]]
// ]
print(mv2darr.add(mv2dsrc, mvmask));
// [
// [[3,-3],[12,-11],[7,-5]],
// [[9,-4],[10,-4],[17,-10]]
// ]
print(mv2darr.add(mvarr, mvmask));
// [
// [[3,-3],[14,-13],[7,-5]],
// [[9,-4],[12,-6],[17,-10]]
// ]
print(mv2darr.add(mvsrc, mvmask));
// [
// [[3,-3],[15,-14],[7,-5]],
// [[9,-4],[13,-7],[17,-10]]
// ]
print(mv2darr.add_h(mv2dsrc));
// [
// [[4,-3],[17,-14],[10,-5]],
// [[11,-4],[16,-7],[21,-10]]
// ]
print(mv2darr.add_h(mvarr));
// [
// [[5,-3],[19,-14],[13,-5]],
// [[12,-4],[18,-7],[24,-10]]
// ]
print(mv2darr.add_h(mvsrc));
// [
// [[6,-3],[20,-14],[14,-5]],
// [[13,-4],[19,-7],[25,-10]]
// ]
print(mv2darr.add_h(2));
// [
// [[8,-3],[22,-14],[16,-5]],
// [[15,-4],[21,-7],[27,-10]]
// ]
print(mv2darr.add_h(mv2dsrc, mv2dmask));
// [
// [[8,-3],[24,-14],[16,-5]],
// [[17,-4],[21,-7],[31,-10]]
// ]
print(mv2darr.add_h(mvarr, mv2dmask));
// [
// [[8,-3],[26,-14],[16,-5]],
// [[18,-4],[21,-7],[34,-10]]
// ]
print(mv2darr.add_h(mvsrc, mv2dmask));
// [
// [[8,-3],[27,-14],[16,-5]],
// [[19,-4],[21,-7],[35,-10]]
// ]
print(mv2darr.add_h(2, mv2dmask));
// [
// [[8,-3],[29,-14],[16,-5]],
// [[21,-4],[21,-7],[37,-10]]
// ]
print(mv2darr.add_h(mv2dsrc, mvmask));
// [
// [[8,-3],[31,-14],[16,-5]],
// [[21,-4],[24,-7],[37,-10]]
// ]
print(mv2darr.add_h(mvarr, mvmask));
// [
// [[8,-3],[33,-14],[16,-5]],
// [[21,-4],[26,-7],[37,-10]]
// ]
print(mv2darr.add_h(mvsrc, mvmask));
// [
// [[8,-3],[34,-14],[16,-5]],
// [[21,-4],[27,-7],[37,-10]]
// ]
print(mv2darr.add_h(2, mvmask));
// [
// [[8,-3],[36,-14],[16,-5]],
// [[21,-4],[29,-7],[37,-10]]
// ]
print(mv2darr.add_v(mv2dsrc));
// [
// [[8,-4],[36,-16],[16,-8]],
// [[21,-4],[29,-8],[37,-12]]
// ]
print(mv2darr.add_v(mvarr));
// [
// [[8,-5],[36,-18],[16,-11]],
// [[21,-5],[29,-10],[37,-15]]
// ]
print(mv2darr.add_v(mvsrc));
// [
// [[8,-6],[36,-19],[16,-12]],
// [[21,-6],[29,-11],[37,-16]]
// ]
print(mv2darr.add_v(2));
// [
// [[8,-4],[36,-17],[16,-10]],
// [[21,-4],[29,-9],[37,-14]]
// ]
print(mv2darr.add_v(mv2dsrc, mv2dmask));
// [
// [[8,-4],[36,-19],[16,-10]],
// [[21,-4],[29,-9],[37,-16]]
// ]
print(mv2darr.add_v(mvarr, mv2dmask));
// [
// [[8,-4],[36,-21],[16,-10]],
// [[21,-5],[29,-9],[37,-19]]
// ]
print(mv2darr.add_v(mvsrc, mv2dmask));
// [
// [[8,-4],[36,-22],[16,-10]],
// [[21,-6],[29,-9],[37,-20]]
// ]
print(mv2darr.add_v(2, mv2dmask));
// [
// [[8,-4],[36,-20],[16,-10]],
// [[21,-4],[29,-9],[37,-18]]
// ]
print(mv2darr.add_v(mv2dsrc, mvmask));
// [
// [[8,-4],[36,-22],[16,-10]],
// [[21,-4],[29,-10],[37,-18]]
// ]
print(mv2darr.add_v(mvarr, mvmask));
// [
// [[8,-4],[36,-24],[16,-10]],
// [[21,-4],[29,-12],[37,-18]]
// ]
print(mv2darr.add_v(mvsrc, mvmask));
// [
// [[8,-4],[36,-25],[16,-10]],
// [[21,-4],[29,-13],[37,-18]]
// ]
print(mv2darr.add_v(2, mvmask));
// [
// [[8,-4],[36,-23],[16,-10]],
// [[21,-4],[29,-11],[37,-18]]
// ]
// you get the idea, I won't repeat for "sub", "mul", and "div".
print("assign");
// assign
print(mv2darr.assign(mv2dsrc));
// [
// [[1,-1],[2,-2],[3,-3]],
// [[2,0],[3,-1],[4,-2]]
// ]
print(mv2darr.assign(mvarr));
// [
// [[1,-1],[2,-2],[3,-3]],
// [[1,-1],[2,-2],[3,-3]]
// ]
print(mv2darr.assign(mvsrc));
// [
// [[1,-1],[1,-1],[1,-1]],
// [[1,-1],[1,-1],[1,-1]]
// ]
// the null argument is only allowed when assigning
print(mv2darr.assign(null, mv2dmask));
// [
// [[8,-4],null,[16,-10]],
// [null,[29,-11],null]
// ]
print(mv2darr.assign(null, mvmask));
// [
// [[8,-4],null,[16,-10]],
// [null,null,null]
// ]
print(mv2darr.assign(null));
// [
// [null,null,null],
// [null,null,null]
// ]
Note: check MVArray.prototype.mathOp()
for more examples.
MV2DArray.prototype.compare()
The compare()
returns an MV2DMask
with the result from running the
provided compareFn()
function on all elements of the 2-dimensional
array.
Syntax
compare(compareFn(mv, i, j, array))
compare(compareFn(mv, i, j, array), thisArg)
Parameters
compareFn
is a function (inline
, arrow
, or normal) that is called
for each motion vector of the 2-dimensional array.
The function’s parameters are mv
(an MVRef
to the current motion
vector being tested), i
(the vertical index it corresponds to in the
2-dimensional array), j
(the horizontal index it correspons to in the
2-dimensional array), and array
(the 2-dimensional array itself).
The function should return either true
or false
.
thisArg
(optional) is a value to use as this
when executing
compareFn
.
Return value
An MV2DMask
filled with the results from each comparison.
Examples
const mv2darr = new MV2DArray(3, 2);
mv2darr.forEach((mv,i,j) => mv.assign(MV(i+2,j+2)));
print(mv2darr);
// [
// [[2,2],[2,3],[2,4]],
// [[3,2],[3,3],[3,4]]
// ]
const mv2dmask = mv2darr.compare((mv) => mv[0] == mv[1]);
print(mv2dmask);
// [
// [true,false,false],
// [false,true,false]
// ]
MV2DArray.prototype.compareOp()
There is no real compareOp()
method in the MV2DArray
prototype.
Instead, there are a bunch of comparison methods, listed below:
compare_eq()
compare_neq()
compare_gt()
compare_gte()
compare_lt()
compare_lte()
The difference between the compare()
method and the compareOp()
methods is that compare()
takes a function, and compareOp()
will
run some predefined comparisons, which should be much faster than
calling a function for each iteration.
The arguments passed to the methods above should be either an
MV2DArray
(of the same width/height as the 2-dimensional array), an
MVArray
(of the same length as the 2-dimensional array’s width),
null
(only for the assign
operation), an MV
constant, an MV
object, or an MVRef
object, a motion vector specified in terms of its
horizontal and vertical components, or a single integer, which will
be used as the squared magnitude of a motion vector.
The behaviour of each method is defined as follows:
compare_eq()
tests forequality
(==
).compare_neq()
tests forinequality
(!=
).compare_gt()
tests forgreater than
(>
)compare_gte()
tests forgreater than or equal
(>=
).compare_lt()
tests forless than
(<
).compare_lte()
tests forless than or equal
(<
).
There are also similar methods that operate only on the horizontal or
vertical elements of the motion vector. These methods take only one
argument (the horizontal
or vertical
element), and have either
_h
(horizontal) or _v
(vertical) appended to the method names.
They are listed below:
compare_eq_h()
compare_neq_h()
compare_gt_h()
compare_gte_h()
compare_lt_h()
compare_lte_h()
compare_eq_v()
compare_neq_v()
compare_gt_v()
compare_gte_v()
compare_lt_v()
compare_lte_v()
Syntax
compareOp(null)
compareOp(mv2darray)
compareOp(mvarray)
compareOp(mv)
compareOp(magnitude_sq)
compareOp(horizontal, vertical)
compareOp_h(horizontal)
compareOp_v(vertical)
Parameters
mv2darray
(optional) is an MV2DArray
object.
mvarray
(optional) is an MVArray
object.
mv
(optional) must be either an MV
constant, an MV
object, or an MVRef
object.
magnitude_sq
(optional) is the squared magnitude to compare against.
horizontal
(optional) is the horizontal component of the motion vector.
vertical
(optional) is the vertical component of the motion vector.
Return value
An MV2DMask
filled with the results from each comparison.
Examples
// create sources of motion vectors
const mv2dsrc = new MV2DArray(3, 2);
mv2dsrc.forEach((_,i,j,arr) => arr[i][j] = MV(i+j+1,i-j-1));
const mvarr = mv2dsrc[0].dup();
const mvsrc = new MV(mvarr[0]);
print(mv2dsrc instanceof MV2DArray); // true
print(mvarr instanceof MVArray); // true
print(mvsrc instanceof MV); // true
print(mv2dsrc);
// [
// [[1,-1],[2,-2],[3,-3]],
// [[2,0],[3,-1],[4,-2]]
// ]
print(mvarr);
// [1,-1],[2,-2],[3,-3]
print(mvsrc);
// [1,-1]
const mg_sq = 18;
// create work mv2darray
const mv2darr = mv2dsrc.dup();
mv2darr[0][2][1] = 3;
mv2darr[1][0] = MV(0,0);
mv2darr[1][1] = MV(2,-2);
mv2darr[1][2] = null;
// good luck keeping track of the value of the motion vectors!
print(mv2darr);
// [
// [[0,0],[2,-2],[3,3]],
// [[2,0],[4,2],null]
// ]
print("compare_eq"); // compare_eq
print(mv2darr.compare_eq(mv2dsrc));
// [
// [true,true,false],
// [false,false,false]
// ]
print(mv2darr.compare_eq(mvarr));
// [
// [true,true,false],
// [false,true,false]
// ]
print(mv2darr.compare_eq(mvsrc));
// [
// [true,false,false],
// [false,false,false]
// ]
print(mv2darr.compare_eq(null));
// [
// [false,false,false],
// [false,false,true]
// ]
print(mv2darr.compare_eq(mg_sq));
// [
// [false,false,true],
// [false,false,false]
// ]
// compare_neq() is just the opposite of compare_eq()
print("compare_gt"); // compare_gt
print(mv2darr.compare_gt(mv2dsrc));
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2darr.compare_gt(mvarr));
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2darr.compare_gt(mvsrc));
// [
// [false,true,true],
// [false,true,false]
// ]
print(mv2darr.compare_gt(null));
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2darr.compare_gt(mg_sq));
// [
// [false,false,false],
// [false,false,false]
// ]
print("compare_gte"); // compare_gt
print(mv2darr.compare_gte(mv2dsrc));
// [
// [true,true,true],
// [false,false,false]
// ]
print(mv2darr.compare_gte(mvarr));
// [
// [true,true,true],
// [false,true,false]
// ]
print(mv2darr.compare_gte(mvsrc));
// [
// [true,true,true],
// [false,true,false]
// ]
print(mv2darr.compare_gte(null));
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2darr.compare_gte(mg_sq));
// [
// [false,false,true],
// [false,false,false]
// ]
// compare_lt() is just the opposite of compare_gte()
// compare_lte() is just the opposite of compare_gt()
Note: check MVArray.prototype.compareOp()
for more examples.
MV2DMask.prototype.fill()
The fill()
method fills all the elements of a 2-dimensional mask
array from an start
index to an end
index with the boolean value
.
Syntax
fill(value)
fill(value, start)
fill(value, start, end)
Parameters
value
boolean to fill the 2-dimensional mask array with.
start
(optional) is the [horizontal, vertical]
index where the
filling starts.
If this value is omitted, begin
is [0,0]
.
end
(optional) is the end [horizontal, vertical]
index where the
filling starts.
If this value is omitted, end
is [width,height]
.
Note: the start
and end
parameters can contain negative values.
In that case, the values wrap around from the last index.
Return value
The modified 2-dimensional mask array.
Examples
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask);
// [
// [true,true,true],
// [true,true,true]
// ]
print(mv2dmask.fill(false));
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2dmask.fill(true, [2,0]));
// [
// [false,false,true],
// [false,false,true]
// ]
print(mv2dmask.fill(true, [0,1], [3,2]));
// [
// [false,false,true],
// [true,true,true]
// ]
MV2DMask.prototype.forEach()
The forEach()
method calls the callbackFn
function for each element
of the 2-dimensional mask array. It has the same functionality as
calling the code below, but it’s slightly faster.
for ( let i = 0; i < mvmask.height; i++ )
for ( let j = 0; j < mvmask.height; j++ )
callbackFn(mvmask[i][j], i, j, mvmask);
Syntax
forEach(callbackFn(element, i, j, array))
forEach(callbackFn(element, i, j, array), thisArg)
Parameters
callbackFn
is a function (inline
, arrow
, or normal) that is
called for each element of the 2-dimensional mask array.
The function’s parameters are element
(the current element being
tested), i
(the vertical index it corresponds to in the
2-dimensional mask array), j
(the horizontal index it correspons to
in the 2-dimensional mask array), and array
(the 2-dimensional mask
array itself).
thisArg
(optional) is a value to use as this
when executing
callbackFn
.
Return value
undefined
.
Examples
const mv2dmask = new MV2DMask(3, 2);
mv2dmask.forEach((_,i,j,arr) => arr[i][j] = ((i+j) & 1));
print(mv2dmask);
// [
// [false,true,false],
// [true,false,true]
// ]
MV2DMask.prototype.not()
The not()
method inverts all the elements of a 2-dimensional mask
array from an start
index to an end
index.
Syntax
not()
not(start)
not(start, end)
Parameters
start
(optional) is the [horizontal, vertical]
index where the
filling starts.
If this value is omitted, begin
is [0,0]
.
end
(optional) is the end [horizontal, vertical]
index where the
filling starts.
If this value is omitted, end
is [width,height]
.
Note: the start
and end
parameters can contain negative values.
In that case, the values wrap around from the last index.
Return value
The modified 2-dimensional mask array.
Examples
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask);
// [
// [true,true,true],
// [true,true,true]
// ]
print(mv2dmask.not());
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2dmask.not([2,0]));
// [
// [false,false,true],
// [false,false,true]
// ]
print(mv2dmask.not([0,1], [3,2]));
// [
// [false,false,true],
// [true,true,false]
// ]
MV2DMask.prototype.and()
The and
method performs an AND
binary operator with the mv2dmask
argument.
Syntax
and(mv2dmask)
Parameters
mv2dmask
is the source 2-dimensional mask array for the binary operation.
Return value
The modified 2-dimensional mask array.
Examples
const mv2dmaskx = new MV2DMask(3, 2);
mv2dmaskx.forEach((_,i,j,arr) => arr[i][j] = ((i+j) & 1));
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask);
// [
// [true,true,true],
// [true,true,true]
// ]
print(mv2dmaskx);
// [
// [false,true,false],
// [true,false,true]
// ]
print(mv2dmask.and(mv2dmaskx));
// [
// [false,true,false],
// [true,false,true]
// ]
MV2DMask.prototype.or()
The or
method performs an OR
binary operator with the mv2dmask
argument.
Syntax
or(mv2dmask)
Parameters
mv2dmask
is the 2-dimensional source mask array for the binary operation.
Return value
The modified 2-dimensional mask array.
Examples
const mv2dmaskx = new MV2DMask(3, 2);
mv2dmaskx.forEach((_,i,j,arr) => arr[i][j] = ((i+j) & 1));
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask.fill(false));
// [
// [false,false,false],
// [false,false,false]
// ]
print(mv2dmaskx);
// [
// [false,true,false],
// [true,false,true]
// ]
print(mv2dmask.or(mv2dmaskx));
// [
// [false,true,false],
// [true,false,true]
// ]
MV2DMask.prototype.xor()
The xor
method performs an XOR
binary operator with the mv2dmask
argument.
Syntax
xor(mv2dmask)
Parameters
mv2dmask
is the 2-dimensional source mask array for the binary operation.
Return value
The modified 2-dimensional mask array.
Examples
const mv2dmaskx = new MV2DMask(3, 2);
mv2dmaskx.forEach((_,i,j,arr) => arr[i][j] = ((i+j) & 1));
const mv2dmask = new MV2DMask(3, 2);
print(mv2dmask);
// [
// [true,true,true],
// [true,true,true]
// ]
print(mv2dmaskx);
// [
// [false,true,false],
// [true,false,true]
// ]
print(mv2dmask.xor(mv2dmaskx));
// [
// [true,false,true],
// [false,true,false]
// ]
print(mv2dmask.xor(mv2dmaskx));
// [
// [true,true,true],
// [true,true,true]
// ]
print(mv2dmask.xor(mv2dmask));
// [
// [false,false,false],
// [false,false,false]
// ]