Istnieje proste rozwiązanie do znalezienia transformacji afinicznej dla układu nadmiernie określonych równań.
- Należy zauważyć, że w ogóle afinicznych przekształcić znajduje rozwiązanie na określony układ równań liniowych Ax = B za pomocą pseudo odwrotności lub podobną techniką tak
x = (AA t) -1t B
Ponadto, jest obsługiwane w funkcji rdzenia OpenCV za pomocą prostego połączenia rozwiązania (a, B, X).
zapoznać się z kodeksem affine przekształcić w OpenCV/modułów/imgproc/src/imgwarp.cpp: to naprawdę tylko dwie rzeczy:
a. przegrupowuje dane wejściowe, aby utworzyć system Ax = B;
b. następnie wywołuje rozwiązanie (A, B, X);
UWAGA: zignoruj komentarze funkcji w kodzie openCV - są one mylące i nie odzwierciedlają rzeczywistej kolejności elementów w macierzach. Jeśli rozwiązywania [u, v]”= Afiniczna * [x, y, 1] Przegrupowanie:
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
Wszystko, co musisz zrobić, to dodać więcej punktów. Aby praca Solve (A, B, X) działała na nadmiernie zdeterminowanym systemie, dodaj parametr DECOMP_SVD. Aby zobaczyć powerpoint slajdy na temat, użyj tego link. Jeśli chcesz dowiedzieć się więcej o pseudoodwrocie w kontekście widzenia komputerowego, najlepszym źródłem jest: ComputerVision, patrz rozdział 15 i dodatek C.
Jeśli nadal nie jesteś pewien, jak dodać więcej punktów, zobacz mój Kod poniżej
// 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;
Może [estimateRigidTransform] (http://docs.opencv.org/modules/video/doc/motion_analysis_and_object_tracking.html # estimaterigidtransform) pasowałoby do twoich potrzeb. – cgat