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