Preface
In a previous article, we explained the image pyramid, and this article is about affine transformations.
A copy of the gun?
Any affine transformation can be converted to, multiplied by a matrix (linear variation), plus a vector (translational change).
In fact, affine is the transformation relation of two pictures.
For example, we can use the affine transformation of the Image: Scaling, rotation, translation and so on.
A mathematical problem
Before we solve the affine problem, let's do a math problem.
As in the figure, for the point (x1, y1), rotate an angle relative to the origin a, then where is this point?
We turn the coordinate system into polar coordinates, then the point (x1, y1) becomes (r, Beta) and rotates to (R, α+ beta).
Back to the rectangular coordinate system, the rotated point becomes (cos (α+ β) * R, Sin (α+ Beta) * r).
then use the formula :
cos (α + β) =cosαcosβ-sinαsinβ
Sin (α + β) =sinαcosβ+cosαsinβ
As well as the original point (cosβ* R, sinβ * R), it is easy to draw a new point for (x1 * cosα-y1 * sinα, x1 * sinaα+ y1 * cosα).
we can derive the rotation transformation formula from the following:
So the translation is a lot simpler, and it's equivalent to adding a vector (c, D) on the line.
Obtain transformation matrix function realization
Usually we use matrices to represent affine transformations.
Where a is a rotational scaling transformation, and B is a translation transformation. The result T satisfies:
Or
That
Copy Code code as follows:
var getrotationarray2d = function (__angle, __x, __y) {
var sin = math.sin (__angle) | | 0,
cos = math.cos (__angle) | | 1,
x = __x | | 0,
y = __y | | 0;
return [Cos,-sin, X,
Sin, cos, y
];
};
So we get an affine transformation matrix.
Of course, the implementation itself has a problem, because the origin is fixed in the upper left corner.
Affine transformation Implementation
Copy Code code as follows:
var warpaffine = function (__src, __rotarray, __DST) {
(__src && __rotarray) | | Error (Arguments.callee, is_undefined_or_null/* {line} */);
if (__src.type && __src.type = = "Cv_rgba") {
var height = __src.row,
width = __src.col,
DST = __DST | | New Mat (height, width, cv_rgba),
SData = new Uint32array (__src.buffer),
Ddata = new Uint32array (dst.buffer);
var i, J, XS, Ys, X, Y, Nowpix;
for (j = 0, Nowpix = 0; j < height; J + +) {
xs = __rotarray[1] * j + __rotarray[2];
YS = __rotarray[4] * j + __rotarray[5];
for (i = 0; i < width; i++, nowpix++, XS + __rotarray[0], ys + = __rotarray[3]) {
if (xs > 0 && ys > 0 && xs < width && ys < height) {
y = Ys | 0;
x = xs | 0;
DDATA[NOWPIX] = sdata[y * width + x];
}else{
Ddata[nowpix] = 4278190080; Black
}
}
}
}else{
Error (Arguments.callee, unspport_data_type/* {line} */);
}
return DST;
};
This function first turns the matrix data into 32-bit form, and manipulating each element is equivalent to manipulating each pixel.
It then iterates through all the elements and assigns the corresponding points.
Effect