Hay una solución fácil para encontrar la transformación Affine para el sistema de ecuaciones sobre-determinadas.
- Tenga en cuenta que, en general, una transformación afín encuentra una solución al sistema sobredeterminado de ecuaciones lineales Ax = B mediante el uso de un pseudo-inversa o una técnica similar, por lo
x = (AA t) -1 a t B
por otra parte, esto se maneja en la funcionalidad central OpenCV por una llamada simple de resolver (a, B, X).
Familiarícese con el código de transformación afín en OpenCV/módulos/imgproc/src/imgwarp.cpp: lo que realmente hace sólo dos cosas:
a. reorganiza las entradas para crear un sistema Ax = B;
b. luego llama a resolver (A, B, X);
NOTA: ignorar los comentarios de función en el código OPENCV - que son confusas y no reflejan el orden real de los elementos de las matrices. Si está resolviendo [u, v]’= Afín * [x, y, 1] es el reordenamiento:
x1 y1 1 0 0 1
0 0 0 x1 y1 1
x2 y2 1 0 0 1
A = 0 0 0 x2 y2 1
x3 y3 1 0 0 1
0 0 0 x3 y3 1
X = [Affine11, Affine12, Affine13, Affine21, Affine22, Affine23]’
u1 v1
B = u2 v2
u3 v3
Todo lo que necesita hacer es añadir más puntos. Para hacer que Solve (A, B, X) funcione en un sistema excesivamente determinado, agregue el parámetro DECOMP_SVD. Para ver las diapositivas de PowerPoint sobre el tema, use este link. Si desea obtener más información sobre el pseudoinverso en el contexto de la visión artificial, la mejor fuente es: ComputerVision, consulte el capítulo 15 y el apéndice C.
Si todavía no está seguro de cómo agregar más puntos, consulte mi código de abajo:
// extension for n points;
cv::Mat getAffineTransformOverdetermined(const Point2f src[], const Point2f dst[], int n)
{
Mat M(2, 3, CV_64F), X(6, 1, CV_64F, M.data); // output
double* a = (double*)malloc(12*n*sizeof(double));
double* b = (double*)malloc(2*n*sizeof(double));
Mat A(2*n, 6, CV_64F, a), B(2*n, 1, CV_64F, b); // input
for(int i = 0; i < n; i++)
{
int j = i*12; // 2 equations (in x, y) with 6 members: skip 12 elements
int k = i*12+6; // second equation: skip extra 6 elements
a[j] = a[k+3] = src[i].x;
a[j+1] = a[k+4] = src[i].y;
a[j+2] = a[k+5] = 1;
a[j+3] = a[j+4] = a[j+5] = 0;
a[k] = a[k+1] = a[k+2] = 0;
b[i*2] = dst[i].x;
b[i*2+1] = dst[i].y;
}
solve(A, B, X, DECOMP_SVD);
delete a;
delete b;
return M;
}
// call original transform
vector<Point2f> src(3);
vector<Point2f> dst(3);
src[0] = Point2f(0.0, 0.0);src[1] = Point2f(1.0, 0.0);src[2] = Point2f(0.0, 1.0);
dst[0] = Point2f(0.0, 0.0);dst[1] = Point2f(1.0, 0.0);dst[2] = Point2f(0.0, 1.0);
Mat M = getAffineTransform(Mat(src), Mat(dst));
cout<<M<<endl;
// call new transform
src.resize(4); src[3] = Point2f(22, 2);
dst.resize(4); dst[3] = Point2f(22, 2);
Mat M2 = getAffineTransformOverdetermined(src.data(), dst.data(), src.size());
cout<<M2<<endl;
Tal [estimateRigidTransform] (http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html # estimaterigidtransform) se ajustaría a sus necesidades. – cgat