16 #include <osl/osl_fit_circle.h>
17 #include <osl/osl_easy_canny.h>
18 #include <osl/osl_save_topology.h>
19 #include <vil1/vil1_load.h>
23 #include <vnl/vnl_least_squares_function.h>
24 #include <vnl/algo/vnl_levenberg_marquardt.h>
25 #include <mvl/HMatrix2D.h>
26 #include <mvl/HMatrix2DComputeLinear.h>
31 #include "SimpleOpt.h"
36 {
OPT_NX, _T(
"-nx"), SO_REQ_SEP },
37 {
OPT_NY, _T(
"-ny"), SO_REQ_SEP },
40 {
OPT_TOL, _T(
"-t"), SO_REQ_SEP },
41 {
OPT_TOL, _T(
"--tolerance"), SO_REQ_SEP },
56 std::vector<HomgPoint2D> & points_world) :
61 void f(
const vnl_vector<double>& x, vnl_vector<double>& fx);
70 h0(0,0) = x[0]; h0(0,1) = x[1]; h0(0,2) = x[2];
71 h0(1,0) = x[3]; h0(1,1) = x[4]; h0(1,2) = x[5];
72 h0(2,0) = x[6]; h0(2,1) = x[7]; h0(2,2) = x[8];
77 double k0 = 1.-k1-k2-k3;
86 double r = sqrt((u-u0)*(u-u0)+(
v-v0)*(
v-v0));
87 double L = k0+k1*r+k2*r*r+k3*r*r*r;
88 double un = u0+L*(u-u0);
89 double vn = v0+L*(
v-v0);
90 fx[i*2] = un-im.x()/im.w();
91 fx[i*2+1] = vn-im.y()/im.w();
101 #include "radial.help"
105 int main(
int argc,
char *argv[])
109 double poss_var = 0.25;
110 bool with_data =
false;
115 if (args.LastError() == SO_SUCCESS)
119 else if (args.OptionId() ==
OPT_DATA)
121 else if (args.OptionId() ==
OPT_NX)
123 std::ostringstream o;
124 o << args.OptionArg();
125 std::istringstream
in(o.str().c_str());
127 }
else if (args.OptionId() ==
OPT_NY)
129 std::ostringstream o;
130 o << args.OptionArg();
131 std::istringstream
in(o.str().c_str());
135 std::ostringstream o;
136 o << args.OptionArg();
137 std::istringstream
in(o.str().c_str());
139 }
else if (args.OptionId() ==
OPT_TOL)
141 std::ostringstream o;
142 o << args.OptionArg();
143 std::istringstream
in(o.str().c_str());
149 std::cerr <<
"Invalid argument: " << args.OptionText() << std::endl;
150 return error(args.LastError());
156 if (args.FileCount() != 1)
return error(-2);
158 const int npts = nrow*ncol;
159 const double cx_w = (ncol-1)/2.*ratio;
160 const double cy_w = (nrow-1)/2.;
161 const double s_w = sqrt(cx_w*cx_w+cy_w*cy_w);
162 std::vector<a_point> centers_w;
163 std::vector<HomgPoint2D> centers_w2;
164 for (
int i=0; i< nrow; i++)
166 for (
int j=0; j<ncol; j++)
168 double x = ratio*(j-cx_w)/s_w;
169 double y = (i-cy_w)/s_w;
170 centers_w.push_back(a_point(x,y,0.));
171 centers_w2.push_back(HomgPoint2D(x,y,1.));
175 vil1_image image = vil1_load(args.File(0));
176 if (!image)
return 2;
177 double width_i = image.width();
178 double height_i = image.height();
179 double cx_i = (width_i-1)/2.;
180 double cy_i = (height_i-1)/2.;
181 double s_i = sqrt(cx_i*cx_i+cy_i*cy_i);
183 std::list<osl_edge*> edgels;
184 osl_easy_canny(0, image, &edgels);
186 for (std::list<osl_edge*>::iterator it= edgels.begin(); it!= edgels.end(); it++)
188 osl_edge
const *e = *it;
189 osl_fit_circle fit(*e);
193 std::vector<a_point> centers_i;
195 std::cout << npts << std::endl;
196 for (std::list<osl_edge*>::iterator it= edgels.begin(); it!= edgels.end(); it++)
198 osl_edge
const *e = *it;
199 osl_fit_circle fit(*e);
200 double rf = fit.radius()/rm;
201 if ((rf>1.-poss_var)&&(rf<1.+poss_var))
203 double x = (fit.center().y()-cx_i)/s_i;
204 double y = (height_i-1-fit.center().x()-cy_i)/s_i;
207 centers_i.push_back(p);
210 if (centers_i.size() != npts)
212 std::cerr <<
"Problem" << std::endl;
213 std::cerr <<
"Number of circle identified is " << centers_i.size() <<
" and should be " << npts << std::endl;
214 std::cerr <<
"Did you try to blur the image? Is contrast high enough? Do you have borders?" << std::endl;
223 for (
int i =0; i< centers_i.size(); i++)
225 a_point p = centers_i[i];
226 double ptax = p.x()+p.y();
238 double x_h[4], y_h[4];
240 p_h[0] = centers_i[i_h[0]];
241 p_h[3] = centers_i[i_h[3]];
245 for (
int i =0; i< centers_i.size(); i++)
247 a_point p = centers_i[i];
248 a_point pn =
cross(p_h[3]-p_h[0],p-p_h[0]);
249 double ptax = pn.norm();
250 if (pn.z() < 0) ptax = -ptax;
262 p_h[1] = centers_i[i_h[1]];
263 p_h[2] = centers_i[i_h[2]];
264 std::cerr << p_h[0] <<
" " << p_h[1] <<
" " << p_h[2] <<
" " << p_h[3] << std::endl;
267 HMatrix2DComputeLinear computor(
false);
268 std::vector<HomgPoint2D> corners_w,corners_i;
269 a_point pp = centers_w[0];
270 corners_w.push_back(HomgPoint2D(pp.x(),pp.y(),1.));
271 pp = centers_w[ncol-1];
272 corners_w.push_back(HomgPoint2D(pp.x(),pp.y(),1.));
273 pp = centers_w[ncol*(nrow-1)];
274 corners_w.push_back(HomgPoint2D(pp.x(),pp.y(),1.));
275 pp = centers_w[ncol*nrow-1];
276 corners_w.push_back(HomgPoint2D(pp.x(),pp.y(),1.));
277 for (
int i=0;i<4;i++)
279 pp = centers_i[i_h[i]];
280 corners_i.push_back(HomgPoint2D(pp.x(),pp.y(),1.));
281 std::cerr << corners_w[i] <<
" " << corners_i[i] << std::endl;
283 HMatrix2D H = computor.compute(corners_w,corners_i);
284 std::cerr << H << std::endl;
286 std::vector<HomgPoint2D> centers_i2;
287 for (
int i =0; i< centers_i.size(); i++)
289 HomgPoint2D p_w(centers_w[i].x(),centers_w[i].y(),1.);
290 HomgPoint2D p_ie = H.transform_to_plane2(p_w);
293 for (
int j=0; j<centers_i.size(); j++)
295 HomgPoint2D p_i(centers_i[j].x(),centers_i[j].y(),1.);
296 double d = sqrt((p_i.x()/p_i.w()-p_ie.x()/p_ie.w())*(p_i.x()/p_i.w()-p_ie.x()/p_ie.w())+
297 (p_i.y()/p_i.w()-p_ie.y()/p_ie.w())*(p_i.y()/p_i.w()-p_ie.y()/p_ie.w()));
304 centers_i2.push_back(HomgPoint2D(centers_i[j0].x(),centers_i[j0].y(),1.));
306 HMatrix2D H2 = computor.compute(centers_w2,centers_i2);
307 std::cerr << H2 << std::endl;
308 for (
int i =0; i< centers_i.size(); i++)
310 HomgPoint2D
pi = centers_i2[i];
311 HomgPoint2D pw = centers_w2[i];
312 HomgPoint2D pi2 = H2.transform_to_plane2(pw);
313 double d = sqrt((
pi.x()/
pi.w()-pi2.x()/pi2.w())*(
pi.x()/
pi.w()-pi2.x()/pi2.w())+
314 (
pi.y()/
pi.w()-pi2.y()/pi2.w())*(
pi.y()/
pi.w()-pi2.y()/pi2.w()));
317 std::cout << centers_i2[i].x() <<
" " << centers_i2[i].y() <<
" " << d*10 << std::endl;
319 vnl_vector<double> x(12);
321 for (
int i = 0; i< 3; i++)
323 for (
int j = 0; j< 3; j++)
329 x[9] = 0.; x[10] = 0.; x[11] = 0.;
331 vnl_levenberg_marquardt levmarq(f);
335 std::cerr <<
"Levenberg Marquardt" << std::endl
336 <<
"min: " << levmarq.get_end_error() <<
" at " << x << std::endl
337 <<
"iterations: " << levmarq.get_num_iterations() <<
" "
338 <<
"evaluations: " << levmarq.get_num_evaluations() << std::endl;
339 levmarq.diagnose_outcome();
341 std::cout <<
" -k1=" << x[9] <<
" -k2=" << x[10] <<
" -k3=" << x[11] <<
" -s" << std::endl;
camera solver with radial distortions
std::vector< HomgPoint2D > & points_image_
a_radial_function(std::vector< HomgPoint2D > &points_image, std::vector< HomgPoint2D > &points_world)
std::vector< HomgPoint2D > & points_world_
void f(const vnl_vector< double > &x, vnl_vector< double > &fx)
e_point cross(e_point &a, e_point &b)
double v(const uint32_t step, const uint32_t n)
int main(int argc, char *argv[])
int error(int val)
camera solver with radial distortions
CSimpleOpt::SOption g_rgOptions[]