/******************************************************************** ** 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/camera-calibration. ** ** 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 "CameraCalibrationUtils.h" #include #include #include #include #include #include #include #include #include typedef CameraCalibrationUtils CCU; typedef CCU::PossibleMarker PossibleMarker; typedef CCU::MarkerType MarkerType; typedef CCU::FoundMarker FoundMarker; HSplit gui; GUI relTransGUI; GUI markerDetectionOptionGUI; GUI planeOptionGUI; Scene scene; GenericGrabber grabber; Point32f currentMousePos; bool haveAnyCalibration = false; CCU::CalibFileData calibFileData; AdjustGridMouseHandler gridAdjuster; void mouse(const MouseEvent &e){ currentMousePos = e.getPos(); if(gui["manual mode"]){ gridAdjuster.process(e); } } CCU::BestOfNSaver *bestOfNSaver = 0; void save(){ bestOfNSaver->lock(); Camera cam = scene.getCamera(0); bestOfNSaver->unlock(); CCU::save_cam_pa(cam,"-os","-o"); } int get_n_frames(){ return gui["save_num_frames"]; } void change_plane(const std::string &handle){ CCU::change_plane(handle, planeOptionGUI, scene, calibFileData); } void init(){ bestOfNSaver = new CCU::BestOfNSaver(get_n_frames); if( !pa("-c") || !pa("-c").n() ){ pa_show_usage("program argument -c must be given with at least one sub-argument"); ::exit(0); } for(int c = 0; c ()); gui << Draw3D().handle("draw").minSize(32,24); markerDetectionOptionGUI = Tab(cat(calibFileData.configurables,",")); for(unsigned int i=0;igetSize()); planeOptionGUI["planeOffset"].disable(); planeOptionGUI["planeRadius"].disable(); planeOptionGUI["planeTicDist"].disable(); planeOptionGUI["planeColor"].disable(); planeOptionGUI.registerCallback(change_plane,"planeOffset,planeRadius,planeTicDist,planeDim,planeColor"); gui["draw"].link(scene.getGLCallback(0)); gui["draw"].install(new MouseHandler(mouse)); } inline float len_vec(const Vec3 &v){ return ::sqrt(sqr(v[0]) + sqr(v[1]) + sqr(v[2])); } inline Vec3 normalize_vec(const Vec3 &v){ float len = len_vec(v); if(!len) return v; return v * 1./len; } void run(){ scene.lock(); scene.setDrawCoordinateFrameEnabled(gui["showCS"]); scene.unlock(); const Mat Trel = create_hom_4x4(relTransGUI["rx"].as()*M_PI/4, relTransGUI["ry"].as()*M_PI/4, relTransGUI["rz"].as()*M_PI/4, relTransGUI["tx"],relTransGUI["ty"],relTransGUI["tz"]); std::vector Ts(calibFileData.loadedFiles.size()); std::vector enabled(Ts.size()); for(unsigned int i=0;i("transform-obj-"+str(i)).getSelectedIndex(); Ts[i] = calibFileData.loadedFiles[i].transforms[tidx].transform; enabled[i] = gui.get("enable-obj-"+str(i)); SceneObject *calibObj = calibFileData.loadedFiles[i].obj; if(!calibObj) continue; calibObj->setTransformation(Trel * Ts[i]); const int a = gui["objAlpha"]; if(a){ const int r = enabled[i] ? 0 : 100, g = 100, b = enabled[i] ? 255 : 100; calibObj->setVisible(Primitive::quad,true); calibObj->setVisible(Primitive::triangle,true); calibObj->setVisible(Primitive::polygon,true); calibObj->setColor(Primitive::quad,GeomColor(r,g,b,a)); calibObj->setColor(Primitive::triangle,GeomColor(r,g,b,a)); calibObj->setColor(Primitive::polygon,GeomColor(r,g,b,a)); }else{ calibObj->setVisible(Primitive::quad,false); calibObj->setVisible(Primitive::triangle,false); calibObj->setVisible(Primitive::polygon,false); } if(!enabled[i]){ calibObj->setColor(Primitive::line,GeomColor(200,200,200,a)); }else{ calibObj->setColor(Primitive::line,GeomColor(255,0,0,a)); } } const ImgBase *image = CCU::preprocess(grabber.grab()); std::vector markers; bool manualMode = gui["manual mode"]; static bool lastManualMode = manualMode; /// one list of grids per loaded file static std::vector > detectedGrids(calibFileData.loadedFiles.size()); static const Rect bounds = image->getImageRect().enlarged(100); if(manualMode != lastManualMode){ if(!manualMode){ gridAdjuster.clear(); lastManualMode = manualMode; }else{ markers = CCU::detect_markers(image,calibFileData); lastManualMode = manualMode; detectedGrids.clear(); detectedGrids.resize(calibFileData.loadedFiles.size()); /// associate detected markers to registered grids for(size_t i=0;i &dgs = detectedGrids[p.cfgFileIndex]; if(!dgs.size()) { dgs.resize(cf.grids.size()); } CCU::DetectedGrid &dg = dgs[p.gridIdx]; if(!dg){ dg.setup(&g); } int mID = m.fid.getID(); int gridIDIdxPos = g.getCellIdx(mID); if(gridIDIdxPos == -1){ ERROR_LOG("found invalid grid idx position for markerID " << mID); continue; } dg.foundMarkers[gridIDIdxPos] = &m; } std::vector > manuallyAdjustableGrids; std::vector > textureLines; std::vector sizes; for(size_t i=0;i ps(5); ps[0] = centerGridSpace; for(int i=0;i<4;++i){ ps[i+1] = cornersGridSpace[i]; } */ std::vector ps; try{ ps = gridAdjuster.mapPoints(gridIdx, std::vector(1,centerGridSpace)); }catch(...){ y = realGrid.dim.height; break; } CCU::FoundMarker found; found.possible = 0; found.type = realGrid.type; found.id = realGrid.markerIDs.at(x + realGrid.dim.width * y); //markers::Fiducial fid; found.imagePos = ps[0]; found.worldPos = center.resize<1,4>(1); found.hasCorners = false; // true /* for(int i=0;i<4;++i){ found.imageCornerPositions[i] = ps[i+1]; found.worldCornerPositions[i] = corners[i].resize<1,4>(1); }*/ found.cfgFileIndex = ci; // todo setup found! markers.push_back(found); } } } } } }else{ markers = CCU::detect_markers(image,calibFileData); } ButtonHandle showRelTrans = relTransGUI["showRelTrans"]; if(showRelTrans.wasTriggered()){ std::cout << "current relative transformation is:" << std::endl << Trel << std::endl; for(unsigned int i=0;igetSize(), deactivatedCenters, gui["useCorners"], gui["errNormalized"], bestOfNSaver, haveAnyCalibration, scene); gui["status"] = res.status; gui["error"] = res.error; gui["save_remaining_frames"] = res.saveRemainingFrames; gui["save_best_error"] = res.saveBestError; static DrawHandle3D draw = gui["draw"]; draw = calibFileData.lastFD->getIntermediateImage(gui["iin"].as()); CCU::visualize_found_markers(draw,markers,enabled,deactivatedCenters,gui["useCorners"]); if(calibFileData.planeObj){ CCU::visualize_plane(draw, planeOptionGUI["planeDim"],planeOptionGUI["planeOffset"], currentMousePos, scene); } if(!gridAdjuster.isNull()){ draw->draw(gridAdjuster.vis()); } draw.render(); } int main(int n, char **ppc){ std::vector args(ppc+1,ppc+n); if(std::find(args.begin(),args.end(),"-cc") != args.end() || std::find(args.begin(),args.end(),"-create-emtpy-config-file") != args.end()){ std::cout << CCU::create_sample_calibration_file_content() << std::endl; return 0; } pa_explain("-crop-and-rescale","crops the outer pixels of the image (hcrop_pix on the left and on the " "right image border and vcrop_pix on the top and bottom image border). The resulting smaller image " "is then scaled up to the target image size given by target_width and target_height.") ("-normalize-input-image","automatically scales the input image range to [0,255] and converts the input image to depth8u"); return ICLApp(n,ppc,"[m]-input|-i(device,device-params) " "-config|-c(...) " "-camera|-cam(camera_file_to_load) " "-initial-transform-id|-it(idx=0) " "-create-empty-config-file|-cc " "-force-size|-s|-size(WxH) " "-convert-output-size|-os(WxH) " "-output|-o(output-xml-file-name) " "-normalize-input-image|-n " "-crop-and-rescale|-cr(crop_x_pix,crop_y_pix,new_width,new_height) " ,init,run).exec(); }