00001 #include "ar_track_alvar/MultiMarker.h"
00002 #include "highgui.h"
00003 using namespace std;
00004 using namespace alvar;
00005
00006 struct State {
00007 IplImage *img;
00008 stringstream filename;
00009 double minx, miny, maxx, maxy;
00010 MultiMarker multi_marker;
00011
00012
00013 bool prompt;
00014 double units;
00015 double marker_side_len;
00016 int marker_type;
00017 double posx, posy;
00018 int content_res;
00019 double margin_res;
00020 bool array;
00021
00022
00023 MarkerData::MarkerContentType marker_data_content_type;
00024 bool marker_data_force_strong_hamming;
00025
00026 State()
00027 : img(0),
00028 prompt(false),
00029 units(96.0/2.54),
00030 marker_side_len(9.0),
00031 marker_type(0),
00032 posx(0), posy(0),
00033 content_res(0),
00034 margin_res(0.0),
00035 marker_data_content_type(MarkerData::MARKER_CONTENT_TYPE_NUMBER),
00036 marker_data_force_strong_hamming(false)
00037 {}
00038 ~State() {
00039 if (img) cvReleaseImage(&img);
00040 }
00041 void AddMarker(const char *id) {
00042 std::cout<<"ADDING MARKER "<<id<<std::endl;
00043 if (marker_type == 0) {
00044 MarkerData md(marker_side_len, content_res, margin_res);
00045 int side_len = int(marker_side_len*units+0.5);
00046 if (img == 0) {
00047 img = cvCreateImage(cvSize(side_len, side_len), IPL_DEPTH_8U, 1);
00048 filename.str("");
00049 filename<<"MarkerData";
00050 minx = (posx*units) - (marker_side_len*units/2.0);
00051 miny = (posy*units) - (marker_side_len*units/2.0);
00052 maxx = (posx*units) + (marker_side_len*units/2.0);
00053 maxy = (posy*units) + (marker_side_len*units/2.0);
00054 } else {
00055 double new_minx = (posx*units) - (marker_side_len*units/2.0);
00056 double new_miny = (posy*units) - (marker_side_len*units/2.0);
00057 double new_maxx = (posx*units) + (marker_side_len*units/2.0);
00058 double new_maxy = (posy*units) + (marker_side_len*units/2.0);
00059 if (minx < new_minx) new_minx = minx;
00060 if (miny < new_miny) new_miny = miny;
00061 if (maxx > new_maxx) new_maxx = maxx;
00062 if (maxy > new_maxy) new_maxy = maxy;
00063 IplImage *new_img = cvCreateImage(cvSize(int(new_maxx-new_minx+0.5), int(new_maxy-new_miny+0.5)), IPL_DEPTH_8U, 1);
00064 cvSet(new_img, cvScalar(255));
00065 CvRect roi = cvRect(int(minx-new_minx+0.5), int(miny-new_miny+0.5), img->width, img->height);
00066 cvSetImageROI(new_img, roi);
00067 cvCopy(img, new_img);
00068 cvReleaseImage(&img);
00069 img = new_img;
00070 roi.x = int((posx*units) - (marker_side_len*units/2.0) - new_minx + 0.5);
00071 roi.y = int((posy*units) - (marker_side_len*units/2.0) - new_miny + 0.5);
00072 roi.width = int(marker_side_len*units+0.5); roi.height = int(marker_side_len*units+0.5);
00073 cvSetImageROI(img, roi);
00074 minx = new_minx; miny = new_miny;
00075 maxx = new_maxx; maxy = new_maxy;
00076 }
00077 if (marker_data_content_type == MarkerData::MARKER_CONTENT_TYPE_NUMBER) {
00078 int idi = atoi(id);
00079 md.SetContent(marker_data_content_type, idi, 0);
00080 if (filename.str().length()<64) filename<<"_"<<idi;
00081
00082 Pose pose;
00083 pose.Reset();
00084 pose.SetTranslation(posx, -posy, 0);
00085 multi_marker.PointCloudAdd(idi, marker_side_len, pose);
00086 } else {
00087 md.SetContent(marker_data_content_type, 0, id);
00088 const char *p = id;
00089 int counter=0;
00090 filename<<"_";
00091 while(*p) {
00092 if (!isalnum(*p)) filename<<"_";
00093 else filename<<(char)tolower(*p);
00094 p++; counter++;
00095 if (counter > 8) break;
00096 }
00097 }
00098 md.ScaleMarkerToImage(img);
00099 cvResetImageROI(img);
00100 }
00101 else if (marker_type == 1) {
00102
00103 MarkerArtoolkit md(marker_side_len, content_res, margin_res);
00104 int side_len = int(marker_side_len*units+0.5);
00105 if (img != 0) cvReleaseImage(&img);
00106 img = cvCreateImage(cvSize(side_len, side_len), IPL_DEPTH_8U, 1);
00107 filename.str("");
00108 filename<<"MarkerArtoolkit";
00109 md.SetContent(atoi(id));
00110 filename<<"_"<<atoi(id);
00111 md.ScaleMarkerToImage(img);
00112 }
00113 }
00114 void Save() {
00115 if (img) {
00116 std::stringstream filenamexml;
00117 filenamexml<<filename.str()<<".xml";
00118 filename<<".png";
00119 std::cout<<"Saving: "<<filename.str()<<std::endl;
00120 cvSaveImage(filename.str().c_str(), img);
00121 if (multi_marker.Size() > 1) {
00122 std::cout<<"Saving: "<<filenamexml.str()<<std::endl;
00123 multi_marker.Save(filenamexml.str().c_str(), alvar::FILE_FORMAT_XML);
00124 }
00125 }
00126 }
00127 } st;
00128
00129 int main(int argc, char *argv[])
00130 {
00131 try {
00132 if (argc < 2) st.prompt = true;
00133 for (int i=1; i<argc; i++) {
00134 if (strcmp(argv[i],"-f") == 0)
00135 st.marker_data_force_strong_hamming=true;
00136 else if (strcmp(argv[i],"-1") == 0)
00137 st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_STRING;
00138 else if (strcmp(argv[i],"-2") == 0)
00139 st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_FILE;
00140 else if (strcmp(argv[i],"-3") == 0)
00141 st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_HTTP;
00142 else if (strcmp(argv[i],"-u") == 0)
00143 st.units = atof(argv[++i]);
00144 else if (strcmp(argv[i],"-uin") == 0)
00145 st.units = (96.0);
00146 else if (strcmp(argv[i],"-ucm") == 0)
00147 st.units = (96.0/2.54);
00148 else if (strcmp(argv[i],"-s") == 0)
00149 st.marker_side_len = atof(argv[++i]);
00150 else if (strcmp(argv[i],"-r") == 0)
00151 st.content_res = atoi(argv[++i]);
00152 else if (strcmp(argv[i],"-m") == 0)
00153 st.margin_res = atof(argv[++i]);
00154 else if (strcmp(argv[i],"-a") == 0)
00155 st.marker_type = 1;
00156 else if (strcmp(argv[i],"-p") == 0)
00157 st.prompt = true;
00158 else if (strcmp(argv[i],"-xy") == 0) {
00159 st.posx = atof(argv[++i]);
00160 st.posy = atof(argv[++i]);
00161 }
00162 else if (strcmp(argv[i],"-ar") == 0) {
00163 st.array = true;
00164 }
00165 else st.AddMarker(argv[i]);
00166 }
00167
00168
00169 if (st.prompt) {
00170 std::string filename(argv[0]);
00171 filename = filename.substr(filename.find_last_of('\\') + 1);
00172 std::cout << "SampleMarkerCreator" << std::endl;
00173 std::cout << "===================" << std::endl;
00174 std::cout << std::endl;
00175 std::cout << "Description:" << std::endl;
00176 std::cout << " This is an example of how to use the 'MarkerData' and 'MarkerArtoolkit'" << std::endl;
00177 std::cout << " classes to generate marker images. This application can be used to" << std::endl;
00178 std::cout << " generate markers and multimarker setups that can be used with" << std::endl;
00179 std::cout << " SampleMarkerDetector and SampleMultiMarker." << std::endl;
00180 std::cout << std::endl;
00181 std::cout << "Usage:" << std::endl;
00182 std::cout << " " << filename << " [options] argument" << std::endl;
00183 std::cout << std::endl;
00184 std::cout << " 65535 marker with number 65535" << std::endl;
00185 std::cout << " -f 65535 force hamming(8,4) encoding" << std::endl;
00186 std::cout << " -1 \"hello world\" marker with string" << std::endl;
00187 std::cout << " -2 catalog.xml marker with file reference" << std::endl;
00188 std::cout << " -3 www.vtt.fi marker with URL" << std::endl;
00189 std::cout << " -u 96 use units corresponding to 1.0 unit per 96 pixels" << std::endl;
00190 std::cout << " -uin use inches as units (assuming 96 dpi)" << std::endl;
00191 std::cout << " -ucm use cm's as units (assuming 96 dpi) <default>" << std::endl;
00192 std::cout << " -s 5.0 use marker size 5.0x5.0 units (default 9.0x9.0)" << std::endl;
00193 std::cout << " -r 5 marker content resolution -- 0 uses default" << std::endl;
00194 std::cout << " -m 2.0 marker margin resolution -- 0 uses default" << std::endl;
00195 std::cout << " -a use ArToolkit style matrix markers" << std::endl;
00196 std::cout << " -p prompt marker placements interactively from the user" << std::endl;
00197 std::cout << std::endl;
00198
00199
00200 if (st.prompt) {
00201 st.marker_type = 0;
00202 st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_NUMBER;
00203 std::cout<<"\nPrompt marker placements interactively"<<std::endl;
00204 std::cout<<" units: "<<st.units/96.0*2.54<<" cm "<<st.units/96.0<<" inches"<<std::endl;
00205 std::cout<<" marker side: "<<st.marker_side_len<<" units"<<std::endl;
00206 bool loop=true;
00207 std::string s;
00208 int marker_id=0;
00209 double posx=0.0, posy=0.0;
00210 bool vert=false;
00211 while(loop) {
00212 std::cout<<" marker id (use -1 to end) ["<<marker_id<<"]: "; std::flush(std::cout);
00213 std::getline(std::cin, s); if (s.length() > 0) marker_id=atoi(s.c_str());
00214 if (marker_id < 0) break;
00215 std::cout<<" x position (in current units) ["<<posx<<"]: "; std::flush(std::cout);
00216 std::getline(std::cin, s); if (s.length() > 0) posx=atof(s.c_str());
00217 std::cout<<" y position (in current units) ["<<posy<<"]: "; std::flush(std::cout);
00218 std::getline(std::cin, s); if (s.length() > 0) posy=atof(s.c_str());
00219 st.posx=posx; st.posy=posy;
00220 std::stringstream ss;
00221 ss<<marker_id;
00222 st.AddMarker(ss.str().c_str());
00223
00224
00225 marker_id++;
00226 if (posx <= 0) {
00227 posx = int(sqrt(double(marker_id)))*st.marker_side_len*2;
00228 posy = 0;
00229 vert = true;
00230 } else if (vert) {
00231 posy += (st.marker_side_len*2);
00232 if (posy >= posx) vert = false;
00233 } else {
00234 posx -= (st.marker_side_len*2);
00235 }
00236 }
00237 }
00238 }
00239 else if(st.array) {
00240 st.marker_type = 0;
00241 st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_NUMBER;
00242 int rows = 0;
00243 int cols = 0;
00244 double rows_distance = 0;
00245 double cols_distance = 0;
00246 bool column_major = 1;
00247 int first_id = 0;
00248 int marker_id = 0;
00249 std::string s;
00250 std::cout<<"\nPrompt marker placements interactively"<<std::endl;
00251 std::cout<<" units: "<<st.units/96.0*2.54<<" cm "<<st.units/96.0<<" inches"<<std::endl;
00252 std::cout<<" marker side: "<<st.marker_side_len<<" units"<<std::endl;
00253 std::cout<<"Array rows : "; std::flush(std::cout);
00254 std::getline(std::cin, s); if (s.length() > 0) rows=atoi(s.c_str());
00255 std::cout<<"Array cols : "; std::flush(std::cout);
00256 std::getline(std::cin, s); if (s.length() > 0) cols=atoi(s.c_str());
00257 std::cout<<"Rows distance : "; std::flush(std::cout);
00258 std::getline(std::cin, s); if (s.length() > 0) rows_distance=atof(s.c_str());
00259 std::cout<<"Cols distance : "; std::flush(std::cout);
00260 std::getline(std::cin, s); if (s.length() > 0) cols_distance=atof(s.c_str());
00261 std::cout<<"Column major (1 or 0) : "; std::flush(std::cout);
00262 std::getline(std::cin, s); if (s.length() > 0) column_major=atoi(s.c_str());
00263 std::cout<<"First marker ID : "; std::flush(std::cout);
00264 std::getline(std::cin, s); if (s.length() > 0) first_id=atoi(s.c_str());
00265 if(!column_major) {
00266 for(int row = 0; row<rows; row++)
00267 for(int col = 0; col<cols; col++)
00268 {
00269 st.posy=row*rows_distance; st.posx=col*cols_distance;
00270 marker_id = first_id + row*cols + col;
00271 std::stringstream ss;
00272 ss<<marker_id;
00273 st.AddMarker(ss.str().c_str());
00274 }
00275 }
00276 else {
00277 for(int col = 0; col<cols; col++)
00278 for(int row = 0; row<rows; row++)
00279 {
00280 st.posy=row*rows_distance; st.posx=col*cols_distance;
00281 marker_id = first_id + col*rows + row;
00282 std::stringstream ss;
00283 ss<<marker_id;
00284 st.AddMarker(ss.str().c_str());
00285 }
00286 }
00287
00288 }
00289 st.Save();
00290 return 0;
00291 }
00292 catch (const std::exception &e) {
00293 std::cout << "Exception: " << e.what() << endl;
00294 }
00295 catch (...) {
00296 std::cout << "Exception: unknown" << std::endl;
00297 }
00298 }