aruco_calibration.cpp
Go to the documentation of this file.
1 /*****************************
2 Copyright 2011 Rafael Muñoz Salinas. All rights reserved.
3 
4 Redistribution and use in source and binary forms, with or without modification, are
5 permitted provided that the following conditions are met:
6 
7  1. Redistributions of source code must retain the above copyright notice, this list of
8  conditions and the following disclaimer.
9 
10  2. Redistributions in binary form must reproduce the above copyright notice, this list
11  of conditions and the following disclaimer in the documentation and/or other materials
12  provided with the distribution.
13 
14 THIS SOFTWARE IS PROVIDED BY Rafael Muñoz Salinas ''AS IS'' AND ANY EXPRESS OR IMPLIED
15 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL Rafael Muñoz Salinas OR
17 CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
21 NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
22 ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 
24 The views and conclusions contained in the software and documentation are those of the
25 authors and should not be interpreted as representing official policies, either expressed
26 or implied, of Rafael Muñoz Salinas.
27 ********************************/
28 #include <iostream>
29 #include <fstream>
30 #include <sstream>
31 #include <opencv2/highgui/highgui.hpp>
32 #include <opencv2/imgproc/imgproc.hpp>
33 #include <opencv2/calib3d/calib3d.hpp>
34 #include "aruco.h"
36 using namespace cv;
37 using namespace aruco;
38 
39 float TheMarkerSize = -1;
40 VideoCapture TheVideoCapturer;
45 
47 
48 void cvTackBarEvents(int pos, void *);
50 int waitTime = 10;
51 
52 class CmdLineParser{int argc; char **argv; public: CmdLineParser(int _argc,char **_argv):argc(_argc),argv(_argv){} bool operator[] ( string param ) {int idx=-1; for ( int i=0; i<argc && idx==-1; i++ ) if ( string ( argv[i] ) ==param ) idx=i; return ( idx!=-1 ) ; } string operator()(string param,string defvalue="-1"){int idx=-1; for ( int i=0; i<argc && idx==-1; i++ ) if ( string ( argv[i] ) ==param ) idx=i; if ( idx==-1 ) return defvalue; else return ( argv[ idx+1] ); }};
53 
54 
55 //given the set of markers detected, the function determines the get the 2d-3d correspondes
56 void getMarker2d_3d(vector<cv::Point2f> &p2d, vector<cv::Point3f> &p3d, const vector< Marker >&markers_detected,const MarkerMap &bc){
57  p2d.clear();
58  p3d.clear();
59  //for each detected marker
60  for(size_t i=0;i<markers_detected.size();i++){
61  //find it in the bc
62  int fidx=-1;
63  for(size_t j=0;j<bc.size() &&fidx==-1;j++)
64  if (bc[j].id==markers_detected[i].id ) fidx=j;
65  if (fidx!=-1){
66  for(int j=0;j<4;j++){
67  p2d.push_back(markers_detected[i][j]);
68  p3d.push_back(bc[fidx][j]);
69  }
70  }
71  }
72  cout<<"points added"<<endl;
73 }
74 vector < vector<cv::Point2f> > calib_p2d;
75 vector < vector<cv::Point3f> > calib_p3d;
76 aruco::CameraParameters camp;//camera parameters estimated
77 
78 
79 /************************************
80  *
81  *
82  *
83  *
84  ************************************/
85 int main(int argc, char **argv) {
86  try {
87  CmdLineParser cml(argc,argv);
88  if (argc <3 || cml["-h"]){
89  cerr << "Usage: (in.avi|live) out_camera_calibration.yml [-m markermapConfig.yml (configuration of the board. If use default one (in utils), no need to set this)] [-size <float> :(value in meters of a marker. If you provide a board that contains that information, this is ommited) ] " << endl;
90  return -1;
91  }
92  // parse arguments
93  //load marker info from file if indicated
94  if (cml["-m"]) TheMarkerMapConfig.readFromFile( cml("-m"));
95  else {//use default
96  stringstream sstr;sstr.write((char*)default_a4_board,default_a4_board_size);
97  TheMarkerMapConfig.fromStream(sstr);
98  }
99  if (!TheMarkerMapConfig.isExpressedInMeters() && !cml["-size"]){
100  cerr<<"Need to specify the size of the makers (in meters) with -size"<<endl;
101  return -1;
102  }
103  if (!TheMarkerMapConfig.isExpressedInMeters())
104  TheMarkerMapConfig=TheMarkerMapConfig.convertToMeters(atof(cml("-size").c_str()));
105  // read from camera or from file
106  if (string(argv[1]) == "live") {
107  TheVideoCapturer.open(0);
108  }
109  else TheVideoCapturer.open(argv[1]);
110  // check video is open
111  if (!TheVideoCapturer.isOpened()) {
112  cerr << "Could not open video" << endl;
113  return -1;
114  }
115 
116  // read first image to get the dimensions
118 
119  //set specific parameters for this configuration
120  MarkerDetector::Params params;
121  //play with this paramteres if the detection does not work correctly
122  params._borderDistThres=.01;//acept markers near the borders
123  params._thresParam1=5;
124  params._thresParam1_range=5;//search in wide range of values for param1
125  params._cornerMethod=MarkerDetector::SUBPIX;//use subpixel corner refinement
126  params._subpix_wsize= (15./2000.)*float(TheInputImage.cols) ;//search corner subpix in a 5x5 widow area
127  TheMarkerDetector.setParams(params);//set the params above
128  TheMarkerDetector.setDictionary(TheMarkerMapConfig.getDictionary());
129  // Create gui and prepare the detector for an aruco chessboard
130  cout<<"Press 'a'' to add current view to the pool of images used for calibration"<<endl;
131  cout<<"Press 'c' to perform calibration"<<endl;
132  cout<<"Press 's' to start/stop capture"<<endl;
133  cv::namedWindow("in", 1);
134  iThresParam1=TheMarkerDetector.getParams()._thresParam1;
135  iThresParam2=TheMarkerDetector.getParams()._thresParam2;
136 
137  cv::createTrackbar("ThresParam1", "in", &iThresParam1, 13, cvTackBarEvents);
138  cv::createTrackbar("ThresParam2", "in", &iThresParam2, 13, cvTackBarEvents);
139  char key = 0,capturing=0;
140  // capture until press ESC or until the end of the video
141  do {
142  TheVideoCapturer.retrieve(TheInputImage);//get image
143  // detect and print
144  vector<aruco::Marker> detected_markers=TheMarkerDetector.detect(TheInputImage);
145  vector<int> markers_from_set=TheMarkerMapConfig.getIndices(detected_markers);
146  // print markers from the board
147  TheInputImage.copyTo(TheInputImageCopy);
148  for(auto idx:markers_from_set) detected_markers[idx].draw(TheInputImageCopy, Scalar(0, 0, 255), 1);
149 
150  // show input with augmented information and the thresholded image
151  cv::imshow("in", TheInputImageCopy);
152  // cv::imshow("thres", TheMarkerDetector.getThresholdedImage());
153 
154  // write to video if required
155 
156  while( (key = cv::waitKey(10))==-1 && !capturing) ; // wait for key to be pressed
157  if (key=='a'){
158  vector<cv::Point2f> p2d;
159  vector<cv::Point3f> p3d;
160 
161  getMarker2d_3d(p2d,p3d,detected_markers,TheMarkerMapConfig);
162  if(p3d.size()>0){
163  calib_p2d.push_back(p2d);
164  calib_p3d.push_back(p3d);
165  }
166  }
167  bool calibrate=false;
168  //calibrate if requested, or if going to leave
169  if (key=='c' || (key==27 && calib_p2d.size()>2) ) calibrate=true;
170  if (calibrate){
171  vector<cv::Mat> vr,vt;
172  camp.CamSize=TheInputImage.size();
173  cout<<calib_p2d.size()<<endl;
174  double err=cv::calibrateCamera(calib_p3d,calib_p2d,TheInputImage.size(),camp.CameraMatrix,camp.Distorsion,vr,vt);
175  cerr<<"repj error="<<err<<endl;
176  camp.saveToFile(argv[2]);
177  }
178  //set waitTime in start/stop mode
179  if (key=='s') { capturing=!capturing;}
180  } while (key != 27 && TheVideoCapturer.grab());
181 
182 
183  } catch (std::exception &ex)
184 
185  {
186  cout << "Exception :" << ex.what() << endl;
187  }
188 }
189 /************************************
190  *
191  *
192  *
193  *
194  ************************************/
195 
196 void cvTackBarEvents(int pos, void *) {
197  (void)(pos);
198  if (iThresParam1 < 3) iThresParam1 = 3;
199  if (iThresParam1 % 2 != 1) iThresParam1++;
200  if (iThresParam2 < 1) iThresParam2 = 1;
201 
202 
203  MarkerDetector::Params p= TheMarkerDetector.getParams();
206  TheMarkerDetector.setParams(p);
207  // detect and print
208  vector<aruco::Marker> detected_markers=TheMarkerDetector.detect(TheInputImage);
209  vector<int> markers_from_set=TheMarkerMapConfig.getIndices(detected_markers);
211  for(auto idx:markers_from_set) detected_markers[idx].draw(TheInputImageCopy, Scalar(0, 0, 255), 1);
212 
213  cv::imshow("in", TheInputImageCopy);
214  cv::waitKey(10);
215 }
int iThresParam1
bool param(const std::string &param_name, T &param_val, const T &default_val)
Params getParams() const
CameraParameters TheCameraParameters
MarkerDetector TheMarkerDetector
void saveToFile(string path, bool inXML=true)
bool isExpressedInMeters() const
Definition: markermap.h:87
unsigned int default_a4_board_size
string TheOutCameraParams
Mat TheInputImage
void setDictionary(std::string dict_type, float error_correction_rate=0)
std::vector< aruco::Marker > detect(const cv::Mat &input)
void readFromFile(string sfile)
Definition: markermap.cpp:89
void cvTackBarEvents(int pos, void *)
unsigned char default_a4_board[]
int waitTime
MarkerMap TheMarkerMapConfig
void setParams(Params p)
void getMarker2d_3d(vector< cv::Point2f > &p2d, vector< cv::Point3f > &p3d, const vector< Marker > &markers_detected, const MarkerMap &bc)
MarkerMap convertToMeters(float markerSize)
Definition: markermap.cpp:297
float TheMarkerSize
Main class for marker detection.
Parameters of the camera.
int iThresParam2
Mat TheInputImageCopy
std::string getDictionary() const
Definition: markermap.h:132
void fromStream(std::istream &str)
Definition: markermap.cpp:384
std::vector< int > getIndices(vector< aruco::Marker > &markers)
Definition: markermap.cpp:364
int main(int argc, char **argv)
VideoCapture TheVideoCapturer
CornerRefinementMethod _cornerMethod
vector< vector< cv::Point3f > > calib_p3d
This class defines a set of markers whose locations are attached to a common reference system...
Definition: markermap.h:71
aruco::CameraParameters camp
vector< vector< cv::Point2f > > calib_p2d


tuw_aruco
Author(s): Lukas Pfeifhofer
autogenerated on Mon Jun 10 2019 15:40:45