/******************************************************************** ** Image Component Library (ICL) ** ** ** ** Copyright (C) 2006-2013 CITEC, University of Bielefeld ** ** Neuroinformatics Group ** ** Website: www.iclcv.org and ** ** http://opensource.cit-ec.de/projects/icl ** ** ** ** File : ICLMarkers/apps/camera-calibration-planar/ ** ** camera-calibration-planar.cpp ** ** Module : ICLMarkers ** ** Authors: Christof Elbrechter ** ** ** ** ** ** GNU LESSER GENERAL PUBLIC LICENSE ** ** This file may be used under the terms of the GNU Lesser General ** ** Public License version 3.0 as published by the ** ** ** ** Free Software Foundation and appearing in the file LICENSE.LGPL ** ** included in the packaging of this file. Please review the ** ** following information to ensure the license requirements will ** ** be met: http://www.gnu.org/licenses/lgpl-3.0.txt ** ** ** ** The development of this software was supported by the ** ** Excellence Cluster EXC 277 Cognitive Interaction Technology. ** ** The Excellence Cluster EXC 277 is a grant of the Deutsche ** ** Forschungsgemeinschaft (DFG) in the context of the German ** ** Excellence Initiative. ** ** ** ********************************************************************/ #include #include #include #include #include #include #include #include struct Marker{ int id; Point32f center; Point32f corners[4]; }; struct Grid{ Grid(int idoffset, int nx, int ny, Size32f size, float dxmm, float dymm): idoffset(idoffset),nx(nx),ny(ny),size(size),dxmm(dxmm),dymm(dymm){ markers = Array2D(nx,ny); obj = new SceneObject; Point32f d(dxmm,dymm); Point32f s(size.width/2,size.height/2); for(int y=0,k=0;yaddVertex(Vec(m.corners[0].x, m.corners[0].y, 0, 1)); obj->addVertex(Vec(m.corners[1].x, m.corners[1].y, 0, 1)); obj->addVertex(Vec(m.corners[2].x, m.corners[2].y, 0, 1)); obj->addVertex(Vec(m.corners[3].x, m.corners[3].y, 0, 1)); obj->addLine(k*4,k*4+1, geom_blue()); obj->addLine(k*4+1,k*4+2, geom_blue()); obj->addLine(k*4+2,k*4+3, geom_blue()); obj->addLine(k*4+3,k*4, geom_blue()); } } plane = new SceneObject; Marker m = markers(0,0); plane->addVertex(Vec(m.corners[3].x, m.corners[3].y, 0,1)); m = markers(nx-1,0); plane->addVertex(Vec(m.corners[0].x, m.corners[0].y, 0,1)); m = markers(nx-1,ny-1); plane->addVertex(Vec(m.corners[1].x, m.corners[1].y, 0,1)); m = markers(0,ny-1); plane->addVertex(Vec(m.corners[2].x, m.corners[2].y, 0,1)); plane->addQuad(0,1,2,3,geom_blue(100)); plane->addLine(0,1,geom_blue(200)); plane->addLine(1,2,geom_blue(200)); plane->addLine(2,3,geom_blue(200)); plane->addLine(3,0,geom_blue(200)); } Mat T; int idoffset; int nx; int ny; Size32f size; float dxmm; float dymm; SmartPtr obj; SmartPtr plane; void clear(){ modelPoints.clear(); imagePoints.clear(); objPoints.clear(); } bool contains(int id){ return (id >= idoffset && id < idoffset+nx*ny); } Marker &getMarker(int id){ if(!contains(id)) throw ICLException("wrong marker ID"); id-=idoffset; return markers(id%nx,id/nx); } void add(const Fiducial &f){ Marker &m = getMarker(f.getID()); const std::vector &ks = f.getKeyPoints2D(); if(ks.size() != 4) throw ICLException("markers with 4 keypoints needed!"); for(int i=0;i<4;++i){ modelPoints.push_back(m.corners[i]); objPoints.push_back(Vec(m.corners[i].x, m.corners[i].y, 0, 1)); imagePoints.push_back(ks[i].imagePos); } } Array2D markers; std::vector modelPoints; std::vector imagePoints; std::vector objPoints; }; GenericGrabber grabber; HSplit gui; GUI rel; Scene scene; FiducialDetector fd("bch"); ComplexCoordinateFrameSceneObject *CS = 0; CoplanarPointPoseEstimator cpe(CoplanarPointPoseEstimator::worldFrame, CoplanarPointPoseEstimator::SamplingCoarse); std::vector grids; void init(){ if(pa("-p")){ fd.loadProperties(*pa("-p")); } std::ostringstream gridnames; ProgArg p = pa("-g"); for(int i=0;i ts = tok(p[i],","); if(ts.size() != 6) { pa_show_usage("invalid token for -grid"); ::exit(-1); } Grid g(parse(ts[0]), parse(ts[1]), parse(ts[2]), parse(ts[3]), parse(ts[4]), parse(ts[5]) ); grids.push_back(g); scene.addObject(g.obj.get()); scene.addObject(g.plane.get()); fd.loadMarkers(Range32s(g.idoffset,g.idoffset+g.nx*g.ny-1),"size="+str(g.size)); } CS = new ComplexCoordinateFrameSceneObject; scene.addObject(CS); scene.setBounds(1000); gui["draw"].link(scene.getGLCallback(0)); gui["draw"].install(scene.getMouseHandler(0)); } float r2(float x){ return float(round(x*100))*0.01; } float r1(float x){ return float(round(x*10))*0.1; } void run(){ static DrawHandle3D draw = gui["draw"]; const ImgBase *image = grabber.grab(); draw = image; std::vector fids = fd.detect(image); for(size_t i=0;ilinewidth(1); draw->color(255,0,0,255); draw->fill(255,0,0,20); for(size_t i=0;ipolygon(f.getCorners2D()); for(size_t j=0;jsetTransformation(g.T); g.plane->setTransformation(g.T); } Grid g = grids[gui["ref"].as()]; Mat T = g.T; if(gui["cen"]){ float dx = (g.nx-1) * g.dxmm * 0.5; float dy = (g.ny-1) * g.dymm * 0.5; T = T * create_hom_4x4(0,0,0, dx,dy,0); } const Mat R = create_hom_4x4(rel["rx"].as()*M_PI/4, rel["ry"].as()*M_PI/4, rel["rz"].as()*M_PI/4, rel["tx"],rel["ty"],rel["tz"]); T = T * R; CS->setTransformation(T); static DispHandle disp = gui.get("T"); static ButtonHandle save = gui["save"]; static ButtonHandle use = gui["use"]; for(int x=0;x<4;++x){ for(int y=0;y<4;++y){ disp(x,y) = x == 3 ? r1(T(x,y)) : r2(T(x,y)); } } if(use.wasTriggered()){ scene.getCamera(0).setWorldFrame(T); } if(save.wasTriggered()){ struct Evt : public ICLApp::AsynchronousEvent{ Mat T; Camera cam; Evt(const Mat &T, const Camera &cam):T(T), cam(cam){} virtual void execute() { try{ std::string fn = saveFileDialog("XML-Files (*.xml)"); cam.setWorldFrame(T); std::ofstream file(fn.c_str()); file << cam; }catch(...){} } }; ICLApp::instance()->executeInGUIThread(new Evt(T, scene.getCamera(0))); } draw.render(); } int main(int n, char **a){ pa_explain("-g","list of grid tokens 'ID-offset,nx,ny,marker-size,dx,dy' size units are in mm"); pa_explain("-t","gives initial transform paramters (rotation is given in integer units of PI/2)"); return ICLApp(n,a,"[m]-input|-i(2) " "[m]-initial-camera|-c(1) " "[m]-grids|-g(...) -fiducial-detector-props|-p(filename) " "-initial-relative-transform|-t(rx=0,ry=0,rz=0,tx=0,ty=0,tz=0)",init,run).exec(); }