SampleMarkerCreator.cpp

This is an example that demonstrates the generation of MarkerData markers and saving the image using SaveMarkerImage.

#include "MultiMarker.h"
#include "highgui.h"
using namespace std;
using namespace alvar;

struct State {
    IplImage *img;
    stringstream filename;
    double minx, miny, maxx, maxy; // top-left and bottom-right in pixel units
    MultiMarker multi_marker;

    // General options
    bool   prompt;
    double units;           // how many pixels per one unit
    double marker_side_len; // marker side len in current units
    int    marker_type;     // 0:MarkerData, 1:ArToolkit
    double posx, posy;      // The position of marker center in the given units
    int    content_res;
    double margin_res;

    // MarkerData specific options
    MarkerData::MarkerContentType marker_data_content_type;
    bool                          marker_data_force_strong_hamming;

    State() 
        : img(0),
          prompt(false),
          units(96.0/2.54),      // cm assuming 96 dpi
          marker_side_len(9.0),  // 9 cm
          marker_type(0),
          posx(0), posy(0),
          content_res(0),        // 0 uses default
          margin_res(0.0),       // 0.0 uses default (can be n*0.5)
          marker_data_content_type(MarkerData::MARKER_CONTENT_TYPE_NUMBER),
          marker_data_force_strong_hamming(false)
    {}
    ~State() {
        if (img) cvReleaseImage(&img);
    }
    void AddMarker(const char *id) {
        if (marker_type == 0) {
            MarkerData md(marker_side_len, content_res, margin_res);
            int side_len = int(marker_side_len*units+0.5);
            if (img == 0) {
                img = cvCreateImage(cvSize(side_len, side_len), IPL_DEPTH_8U, 1);
                filename.str("");
                filename<<"MarkerData";
                minx = (posx*units) - (marker_side_len*units/2.0);
                miny = (posy*units) - (marker_side_len*units/2.0);
                maxx = (posx*units) + (marker_side_len*units/2.0);
                maxy = (posy*units) + (marker_side_len*units/2.0);
            } else {
                double new_minx = (posx*units) - (marker_side_len*units/2.0);
                double new_miny = (posy*units) - (marker_side_len*units/2.0);
                double new_maxx = (posx*units) + (marker_side_len*units/2.0);
                double new_maxy = (posy*units) + (marker_side_len*units/2.0);
                if (minx < new_minx) new_minx = minx;
                if (miny < new_miny) new_miny = miny;
                if (maxx > new_maxx) new_maxx = maxx;
                if (maxy > new_maxy) new_maxy = maxy;
                IplImage *new_img = cvCreateImage(cvSize(int(new_maxx-new_minx+0.5), int(new_maxy-new_miny+0.5)), IPL_DEPTH_8U, 1);
                cvSet(new_img, cvScalar(255));
                CvRect roi = cvRect(int(minx-new_minx+0.5), int(miny-new_miny+0.5), img->width, img->height);
                cvSetImageROI(new_img, roi);
                cvCopy(img, new_img);
                cvReleaseImage(&img);
                img = new_img;
                roi.x = int((posx*units) - (marker_side_len*units/2.0) - new_minx + 0.5); 
                roi.y = int((posy*units) - (marker_side_len*units/2.0) - new_miny + 0.5); 
                roi.width = int(marker_side_len*units+0.5); roi.height = int(marker_side_len*units+0.5);
                cvSetImageROI(img, roi);
                minx = new_minx; miny = new_miny;
                maxx = new_maxx; maxy = new_maxy;
            }
            if (marker_data_content_type == MarkerData::MARKER_CONTENT_TYPE_NUMBER) {
                int idi = atoi(id);
                md.SetContent(marker_data_content_type, idi, 0);
                if (filename.str().length()<64) filename<<"_"<<idi;

                Pose pose;
                pose.Reset();
                pose.SetTranslation(posx, -posy, 0);
                multi_marker.PointCloudAdd(idi, marker_side_len, pose);
            } else {
                md.SetContent(marker_data_content_type, 0, id);
                const char *p = id;
                int counter=0;
                filename<<"_";
                while(*p) {
                    if (!isalnum(*p)) filename<<"_";
                    else filename<<(char)tolower(*p);
                    p++; counter++;
                    if (counter > 8) break;
                }
            }
            md.ScaleMarkerToImage(img);
            cvResetImageROI(img);
        }
        else if (marker_type == 1) {
            // Create and save MarkerArtoolkit marker (Note, that this doesn't support multi markers)
            MarkerArtoolkit md(marker_side_len, content_res, margin_res);
            int side_len = int(marker_side_len*units+0.5);
            if (img != 0) cvReleaseImage(&img);
            img = cvCreateImage(cvSize(side_len, side_len), IPL_DEPTH_8U, 1);
            filename.str("");
            filename<<"MarkerArtoolkit";
            md.SetContent(atoi(id));
            filename<<"_"<<atoi(id);
            md.ScaleMarkerToImage(img);
        }
    }
    void Save() {
        if (img) {
            std::stringstream filenamexml;
            filenamexml<<filename.str()<<".xml";
            filename<<".png";
            std::cout<<"Saving: "<<filename.str()<<std::endl;
            cvSaveImage(filename.str().c_str(), img);
            if (multi_marker.Size() > 1) {
                std::cout<<"Saving: "<<filenamexml.str()<<std::endl;
                multi_marker.Save(filenamexml.str().c_str(), alvar::FILE_FORMAT_XML);
            }
        }
    }
} st;

int main(int argc, char *argv[])
{
    try {
        if (argc < 2) st.prompt = true;
        for (int i=1; i<argc; i++) {
            if (strcmp(argv[i],"-f") == 0) 
                st.marker_data_force_strong_hamming=true;
            else if (strcmp(argv[i],"-1") == 0) 
                st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_STRING;
            else if (strcmp(argv[i],"-2") == 0) 
                st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_FILE;
            else if (strcmp(argv[i],"-3") == 0) 
                st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_HTTP;
            else if (strcmp(argv[i],"-u") == 0)
                st.units = atof(argv[++i]);
            else if (strcmp(argv[i],"-uin") == 0)
                st.units = (96.0);
            else if (strcmp(argv[i],"-ucm") == 0)
                st.units = (96.0/2.54);
            else if (strcmp(argv[i],"-s") == 0)
                st.marker_side_len = atof(argv[++i]);
            else if (strcmp(argv[i],"-r") == 0)
                st.content_res = atoi(argv[++i]);
            else if (strcmp(argv[i],"-m") == 0)
                st.margin_res = atof(argv[++i]);
            else if (strcmp(argv[i],"-a") == 0)
                st.marker_type = 1;
            else if (strcmp(argv[i],"-p") == 0)
                st.prompt = true;
            else if (strcmp(argv[i],"-xy") == 0) {
                st.posx = atof(argv[++i]);
                st.posy = atof(argv[++i]);
            }
            else st.AddMarker(argv[i]);
        }

        // Output usage message
        if (st.prompt) {
            std::string filename(argv[0]);
            filename = filename.substr(filename.find_last_of('\\') + 1);
            std::cout << "SampleMarkerCreator" << std::endl;
            std::cout << "===================" << std::endl;
            std::cout << std::endl;
            std::cout << "Description:" << std::endl;
            std::cout << "  This is an example of how to use the 'MarkerData' and 'MarkerArtoolkit'" << std::endl;
            std::cout << "  classes to generate marker images. This application can be used to" << std::endl;
            std::cout << "  generate markers and multimarker setups that can be used with" << std::endl;
            std::cout << "  SampleMarkerDetector and SampleMultiMarker." << std::endl;
            std::cout << std::endl;
            std::cout << "Usage:" << std::endl;
            std::cout << "  " << filename << " [options] argument" << std::endl;
            std::cout << std::endl;
            std::cout << "    65535             marker with number 65535" << std::endl;
            std::cout << "    -f 65535          force hamming(8,4) encoding" << std::endl;
            std::cout << "    -1 \"hello world\"  marker with string" << std::endl;
            std::cout << "    -2 catalog.xml    marker with file reference" << std::endl;
            std::cout << "    -3 www.vtt.fi     marker with URL" << std::endl;
            std::cout << "    -u 96             use units corresponding to 1.0 unit per 96 pixels" << std::endl;
            std::cout << "    -uin              use inches as units (assuming 96 dpi)" << std::endl;
            std::cout << "    -ucm              use cm's as units (assuming 96 dpi) <default>" << std::endl;
            std::cout << "    -s 5.0            use marker size 5.0x5.0 units (default 9.0x9.0)" << std::endl;
            std::cout << "    -r 5              marker content resolution -- 0 uses default" << std::endl;
            std::cout << "    -m 2.0            marker margin resolution -- 0 uses default" << std::endl;
            std::cout << "    -a                use ArToolkit style matrix markers" << std::endl;
            std::cout << "    -p                prompt marker placements interactively from the user" << std::endl;
            std::cout << std::endl;

            // Interactive stuff here
            if (st.prompt) {
                st.marker_type = 0;
                st.marker_data_content_type = MarkerData::MARKER_CONTENT_TYPE_NUMBER;
                std::cout<<"\nPrompt marker placements interactively"<<std::endl;
                std::cout<<"  units: "<<st.units/96.0*2.54<<" cm "<<st.units/96.0<<" inches"<<std::endl;
                std::cout<<"  marker side: "<<st.marker_side_len<<" units"<<std::endl;
                bool loop=true;
                std::string s;
                int marker_id=0;
                double posx=0.0, posy=0.0;
                bool vert=false;
                while(loop) {
                    std::cout<<"  marker id (use -1 to end) ["<<marker_id<<"]: "; std::flush(std::cout);
                    std::getline(std::cin, s); if (s.length() > 0) marker_id=atoi(s.c_str());
                    if (marker_id < 0) break;
                    std::cout<<"  x position (in current units) ["<<posx<<"]: "; std::flush(std::cout);
                    std::getline(std::cin, s); if (s.length() > 0) posx=atof(s.c_str());
                    std::cout<<"  y position (in current units) ["<<posy<<"]: "; std::flush(std::cout);
                    std::getline(std::cin, s); if (s.length() > 0) posy=atof(s.c_str());
                    st.posx=posx; st.posy=posy;
                    std::stringstream ss;
                    ss<<marker_id;
                    st.AddMarker(ss.str().c_str());

                    // Guess suitable marker_id and placement for the next marker
                    marker_id++;
                    if (posx <= 0) {
                        posx = int(sqrt(double(marker_id)))*st.marker_side_len*2;
                        posy = 0;
                        vert = true;
                    } else if (vert) {
                        posy += (st.marker_side_len*2);
                        if (posy >= posx) vert = false;
                    } else {
                        posx -= (st.marker_side_len*2);
                    }
                }
            }
        }
        st.Save();
        return 0;
    }
    catch (const std::exception &e) {
        std::cout << "Exception: " << e.what() << endl;
    }
    catch (...) {
        std::cout << "Exception: unknown" << std::endl;
    }
}


ar_track_alvar
Author(s): Scott Niekum
autogenerated on Sun Oct 5 2014 22:16:25