опять же если взять дисторсию бочка и предположить, что значение пар точек до и после известны и попробовать по этим точкам восстановить параметры дисторсии.
запихиваем в математику (пробовал 4 разных метода Solve,NSolve и с Reals и без)
так же в математике можно переводить тоже на С, с помощью CForm, только как то не до конца адекватно, но возможно я не до конца разобрался.
Цитата:
CForm[c1 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
CForm[c2 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
CForm[k1 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
CForm[k2 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
решение в реалз
CForm[c1 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
CForm[c2 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
CForm[k1 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
CForm[k2 /.
Solve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
Еще и численный метод решения:
CForm[c1 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
CForm[c2 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
CForm[k1 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
CForm[k2 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2}]]
тоже самое только на реалз
CForm[c1 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
CForm[c2 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
CForm[k1 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
CForm[k2 /.
NSolve[v1 == c2 + y1 (1 + k2 (x1^2 + y1^2)) &&
v2 == c2 + y2 (1 + k2 (x2^2 + y2^2)) &&
u1 == c1 + x1 (1 + k1 (x1^2 + y1^2)) &&
u2 == c1 + x2 (1 + k2 (x2^2 + y2^2)), {c1, c2, k1, k2},Reals]]
далее собственно пробуем восстановить параметры по формуле экспортировав ответы на С.
Код:
void barrel_parameters(double x1,double y1,double x2,double y2,double u1,double v1,double u2,double v2)
{
//Solve
double c1= -((-(v1*pow(x2,3)) + v2*pow(x2,3) + u2*pow(x1,2)*y1 - pow(x1,2)*x2*y1 + pow(x2,3)*y1 + u2*pow(y1,3) - x2*pow(y1,3) - u2*pow(x2,2)*y2 - v1*x2*pow(y2,2) +
v2*x2*pow(y2,2) + x2*y1*pow(y2,2) - u2*pow(y2,3))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)));
double c2= -((-(y1*(pow(x1,2) + pow(y1,2))*(v2 - y2)) + (v1 - y1)*y2*(pow(x2,2) + pow(y2,2)))/(y1*(pow(x1,2) + pow(y1,2)) - y2*(pow(x2,2) + pow(y2,2))));
double k1= -((-u1 + u2 + x1 - x2)/(x1*(pow(x1,2) + pow(y1,2)))) + ((-v1 + y1)*(-pow(x2,3) - x2*pow(y2,2)))/(x1*y1*pow(pow(x1,2) + pow(y1,2),2)) +
((pow(x2,3) + x2*pow(y2,2))*(-(y1*(pow(x1,2) + pow(y1,2))*(v2 - y2)) + (v1 - y1)*y2*(pow(x2,2) + pow(y2,2))))/
(x1*y1*pow(pow(x1,2) + pow(y1,2),2)*(y1*(pow(x1,2) + pow(y1,2)) - y2*(pow(x2,2) + pow(y2,2))));
double k2= -((-v1 + v2 + y1 - y2)/(pow(x1,2)*y1 + pow(y1,3) - pow(x2,2)*y2 - pow(y2,3)));
//Solve reals
double с1_r= u1 - x1 - (pow(x1,3)*(-u1 + u2 + x1 - x2 - (pow(x2,3)*(-v1 + v2 + y1 - y2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(x2*(-v1 + v2 + y1 - y2)*pow(y2,2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3))))/(-pow(x1,3) - x1*pow(y1,2)) -
(x1*pow(y1,2)*(-u1 + u2 + x1 - x2 - (pow(x2,3)*(-v1 + v2 + y1 - y2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(x2*(-v1 + v2 + y1 - y2)*pow(y2,2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3))))/(-pow(x1,3) - x1*pow(y1,2));
double c2_r= v1 - y1 - (pow(x1,2)*y1*(-v1 + v2 + y1 - y2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(pow(y1,3)*(-v1 + v2 + y1 - y2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3));
double k1_r= (-u1 + u2 + x1 - x2 - (pow(x2,3)*(-v1 + v2 + y1 - y2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(x2*(-v1 + v2 + y1 - y2)*pow(y2,2))/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)))/(-pow(x1,3) - x1*pow(y1,2));
double k2_r= (-v1 + v2 + y1 - y2)/(-(pow(x1,2)*y1) - pow(y1,3) + pow(x2,2)*y2 + pow(y2,3));
//NSolve
double c1_n= 1.*u2 - 1.*x2 + (1.*(1.*(v1 - 1.*y1) - 1.*(v2 - 1.*y2))*(1.*pow(x2,3) + 1.*x2*pow(y2,2)))/(-1.*y1*(pow(x1,2) + pow(y1,2)) + 1.*y2*(pow(x2,2) + pow(y2,2)));
double c2_n= 1.*v1 - 1.*y1 + (1.*(1.*pow(x1,2)*y1 + 1.*pow(y1,3))*(1.*(v1 - 1.*y1) - 1.*(v2 - 1.*y2)))/(-1.*y1*(pow(x1,2) + pow(y1,2)) + 1.*y2*(pow(x2,2) + pow(y2,2)));
double k1_n= -((-1.*u1 + 1.*u2 + 1.*x1 - 1.*x2)/(x1*(pow(x1,2) + pow(y1,2)))) +
(1.*(1.*(v1 - 1.*y1) - 1.*(v2 - 1.*y2))*(-1.*pow(x2,3) - 1.*x2*pow(y2,2)))/
(x1*(pow(x1,2) + pow(y1,2))*(-1.*y1*(pow(x1,2) + pow(y1,2)) + 1.*y2*(pow(x2,2) + pow(y2,2))));
double k2_n= -((1.*(v1 - 1.*y1) - 1.*(v2 - 1.*y2))/(-1.*y1*(pow(x1,2) + pow(y1,2)) + 1.*y2*(pow(x2,2) + pow(y2,2))));
//NSolve reals
double c1_nr= u1 - 1.*x1 - (1.*pow(x1,3)*(-1.*u1 + u2 + x1 - 1.*x2 -
(1.*pow(x2,3)*(-1.*v1 + v2 + y1 - 1.*y2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(1.*x2*(-1.*v1 + v2 + y1 - 1.*y2)*pow(y2,2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3))))/(-1.*pow(x1,3) - 1.*x1*pow(y1,2)) -
(1.*x1*pow(y1,2)*(-1.*u1 + u2 + x1 - 1.*x2 - (1.*pow(x2,3)*(-1.*v1 + v2 + y1 - 1.*y2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(1.*x2*(-1.*v1 + v2 + y1 - 1.*y2)*pow(y2,2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3))))/(-1.*pow(x1,3) - 1.*x1*pow(y1,2));
double c2_nr= v1 - 1.*y1 - (1.*pow(x1,2)*y1*(-1.*v1 + v2 + y1 - 1.*y2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(1.*pow(y1,3)*(-1.*v1 + v2 + y1 - 1.*y2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3));
double k1_nr= (-1.*u1 + u2 + x1 - 1.*x2 - (1.*pow(x2,3)*(-1.*v1 + v2 + y1 - 1.*y2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)) -
(1.*x2*(-1.*v1 + v2 + y1 - 1.*y2)*pow(y2,2))/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3)))/(-1.*pow(x1,3) - 1.*x1*pow(y1,2));
double k2_nr= (-1.*v1 + v2 + y1 - 1.*y2)/(-1.*pow(x1,2)*y1 - 1.*pow(y1,3) + pow(x2,2)*y2 + pow(y2,3));
//тестируем
IplImage* src=cvLoadImage("сетка.PNG");//чистая сетка
cvSaveImage("test_barrel.png",barrel_pincusion_dist(src, c1,c2,k1,k2));
}
для теста использовал картинки
вызываю
Код:
barrel_parameters(3,2,284,283,26.4,25.2,259,259);
как моделирую само искажение
Код:
IplImage* barrel_pincusion_dist(IplImage* img, int Cx,int Cy,double kx,double ky)
{
IplImage* mapx = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );
IplImage* mapy = cvCreateImage( cvGetSize(img), IPL_DEPTH_32F, 1 );
int w= img->width;
int h= img->height;
float* pbuf = (float*)mapx->imageData;
for (int y = 0; y < h; y++)
{
int ty= y-Cy;
for (int x = 0; x < w; x++)
{
int tx= x-Cx;
int rt= tx*tx+ty*ty;
*pbuf = (float)(tx*(1+kx*rt)+Cx);
++pbuf;
}
}
pbuf = (float*)mapy->imageData;
for (int y = 0;y < h; y++)
{
int ty= y-Cy;
for (int x = 0; x < w; x++)
{
int tx= x-Cx;
int rt= tx*tx+ty*ty;
*pbuf = (float)(ty*(1+ky*rt)+Cy);
++pbuf;
}
}
IplImage* temp = cvCloneImage(img);
cvRemap( temp, img, mapx, mapy );
cvReleaseImage(&temp);
cvReleaseImage(&mapx);
cvReleaseImage(&mapy);
return img;
}
в итоге параметры определяются не правильно, возможно математика выдала какие то не те ответы?
или из-за того что точки я отмечал вручную,т.е. это приблизительные значения, а не реально известные теоретические ,всё расходится?