39 void Marker::VisualizeMarkerPose(IplImage *
image, 
Camera *
cam, 
double visualize2d_points[12][2], CvScalar color)
 const {
    41         for (
int i=0; i<4; i++) {
    42                 cvLine(image, cvPoint((
int)visualize2d_points[i][0], (
int)visualize2d_points[i][1]), cvPoint((
int)visualize2d_points[(i+1)%4][0], (
int)visualize2d_points[(i+1)%4][1]), color);
    43                 cvLine(image, cvPoint((
int)visualize2d_points[i][0], (
int)visualize2d_points[i][1]), cvPoint((
int)visualize2d_points[4+i][0], (
int)visualize2d_points[4+i][1]), color);
    44                 cvLine(image, cvPoint((
int)visualize2d_points[4+i][0], (
int)visualize2d_points[4+i][1]), cvPoint((
int)visualize2d_points[4+((i+1)%4)][0], (
int)visualize2d_points[4+((i+1)%4)][1]), color);
    47         cvLine(image, cvPoint((
int)visualize2d_points[8][0], (
int)visualize2d_points[8][1]), cvPoint((
int)visualize2d_points[9][0], (
int)visualize2d_points[9][1]), CV_RGB(255,0,0));
    48         cvLine(image, cvPoint((
int)visualize2d_points[8][0], (
int)visualize2d_points[8][1]), cvPoint((
int)visualize2d_points[10][0], (
int)visualize2d_points[10][1]), CV_RGB(0,255,0));
    49         cvLine(image, cvPoint((
int)visualize2d_points[8][0], (
int)visualize2d_points[8][1]), cvPoint((
int)visualize2d_points[11][0], (
int)visualize2d_points[11][1]), CV_RGB(0,0,255));
    52 void Marker::VisualizeMarkerContent(IplImage *
image, 
Camera *
cam, 
double datatext_point[2], 
double content_point[2])
 const {
    53 #ifdef VISUALIZE_MARKER_POINTS    54         for (
size_t i=0; i<marker_allpoints_img.size(); i++) {
    55                 if (marker_allpoints_img[i].val == 0) 
    56                         cvCircle(image, cvPoint(
int(marker_allpoints_img[i].
x), 
int(marker_allpoints_img[i].
y)), 1, CV_RGB(0, 255,0));
    57                 else if (marker_allpoints_img[i].val == 255) 
    58                         cvCircle(image, cvPoint(
int(marker_allpoints_img[i].x), 
int(marker_allpoints_img[i].y)), 1, CV_RGB(255, 0,0));
    60                         cvCircle(image, cvPoint(
int(marker_allpoints_img[i].x), 
int(marker_allpoints_img[i].y)), 2, CV_RGB(255,255,0));
    66         cvInitFont(&font, 0, 0.5, 0.5, 0);
    67         std::stringstream val;
    69         cvPutText(image, val.str().c_str(), cvPoint((
int)datatext_point[0], (
int)datatext_point[1]), &
font, CV_RGB(255,255,0));
    72         int xc = int(content_point[0]);
    73         int yc = int(content_point[1]);
    74         for (
int j=0; j<
res*3; j++) {
    75                 for (
int i=0; i<res*3; i++) {
    78                         if ((x >= 0) && (x < image->
width) &&
    79                                 (y >= 0) && (y < image->
height))
    81                                 if (cvGet2D(marker_content, j/3, i/3).val[0]) {
    82                                         cvSet2D(image, y, x, CV_RGB(255,255,255));
    84                                         cvSet2D(image, y, x, CV_RGB(0,0,0));
    91 void Marker::VisualizeMarkerError(IplImage *
image, 
Camera *
cam, 
double errortext_point[2])
 const {
    93         cvInitFont(&font, 0, 0.5, 0.5, 0);
    94         std::stringstream val;
    95         if (GetError(MARGIN_ERROR|DECODE_ERROR) > 0) {
    97                 val<<int(GetError(MARGIN_ERROR)*100)<<
"% ";
    98                 val<<int(GetError(DECODE_ERROR)*100)<<
"% ";
    99                 cvPutText(image, val.str().c_str(), cvPoint((
int)errortext_point[0], (
int)errortext_point[1]), &
font, CV_RGB(255,0,0));
   100         } 
else if (GetError(TRACK_ERROR) > 0.01) {
   102                 val<<int(GetError(TRACK_ERROR)*100)<<
"%";
   103                 cvPutText(image, val.str().c_str(), cvPoint((
int)errortext_point[0], (
int)errortext_point[1]), &
font, CV_RGB(128,0,0));
   107 void MarkerData::VisualizeMarkerContent(IplImage *
image, 
Camera *
cam, 
double datatext_point[2], 
double content_point[2])
 const {
   108 #ifdef VISUALIZE_MARKER_POINTS   109         for (
size_t i=0; i<marker_allpoints_img.size(); i++) {
   110                 if (marker_allpoints_img[i].val == 0) 
   111                         cvCircle(image, cvPoint(
int(marker_allpoints_img[i].
x), 
int(marker_allpoints_img[i].
y)), 1, CV_RGB(0, 255,0));
   112                 else if (marker_allpoints_img[i].val == 255) 
   113                         cvCircle(image, cvPoint(
int(marker_allpoints_img[i].x), 
int(marker_allpoints_img[i].y)), 1, CV_RGB(255, 0,0));
   115                         cvCircle(image, cvPoint(
int(marker_allpoints_img[i].x), 
int(marker_allpoints_img[i].y)), 2, CV_RGB(255,255,0));
   121         cvInitFont(&font, 0, 0.5, 0.5, 0);
   122         std::stringstream val;
   123         CvScalar rgb=CV_RGB(255,255,0);
   124         if (content_type == MARKER_CONTENT_TYPE_NUMBER) {
   127                 if (content_type == MARKER_CONTENT_TYPE_FILE) rgb=CV_RGB(0,255,255);
   128                 if (content_type == MARKER_CONTENT_TYPE_HTTP) rgb=CV_RGB(255,0,255);
   131         cvPutText(image, val.str().c_str(), cvPoint((
int)datatext_point[0], (
int)datatext_point[1]), &
font, rgb);
   135         double visualize3d_points[12][3] = {
   137                 { -(edge_length/2), -(edge_length/2), 0 },
   138                 { -(edge_length/2),  (edge_length/2), 0 },
   139                 {  (edge_length/2),  (edge_length/2), 0 },
   140                 {  (edge_length/2), -(edge_length/2), 0 },
   141                 { -(edge_length/2), -(edge_length/2), edge_length },
   142                 { -(edge_length/2),  (edge_length/2), edge_length },
   143                 {  (edge_length/2),  (edge_length/2), edge_length },
   144                 {  (edge_length/2), -(edge_length/2), edge_length },
   147                 {  edge_length, 0, 0 },
   148                 {  0, edge_length, 0 },
   149                 {  0, 0, edge_length },
   151         double visualize2d_points[12][2];
   152         CvMat visualize3d_points_mat;
   153         CvMat visualize2d_points_mat;
   154         cvInitMatHeader(&visualize3d_points_mat, 12, 3, CV_64F, visualize3d_points);
   155         cvInitMatHeader(&visualize2d_points_mat, 12, 2, CV_64F, visualize2d_points);
   156         cam->
ProjectPoints(&visualize3d_points_mat, &pose, &visualize2d_points_mat);
   158         VisualizeMarkerPose(image, cam, visualize2d_points, color);
   159         VisualizeMarkerContent(image, cam, visualize2d_points[0], visualize2d_points[8]);
   160         VisualizeMarkerError(image, cam, visualize2d_points[2]);
   163 void Marker::CompareCorners(vector<PointDouble > &_marker_corners_img, 
int *orientation, 
double *error) {
   164         vector<PointDouble >::iterator corners_new = _marker_corners_img.begin();
   165         vector<PointDouble >::const_iterator corners_old = marker_corners_img.begin();
   166         vector<double> errors(4);
   167         for (
int i=0; i<4; i++) {
   173         *orientation = min_element(errors.begin(), errors.end()) - errors.begin();
   174         *error = sqrt(errors[*orientation]/4);
   178 void Marker::CompareContent(vector<PointDouble > &_marker_corners_img, IplImage *
gray, 
Camera *
cam, 
int *orientation)
 const {
   184 bool Marker::UpdateContent(vector<PointDouble > &_marker_corners_img, IplImage *
gray, 
Camera *
cam, 
int frame_no ) {
   185         return UpdateContentBasic(_marker_corners_img, gray, cam, frame_no);
   188 bool Marker::UpdateContentBasic(vector<PointDouble > &_marker_corners_img, IplImage *
gray, 
Camera *
cam, 
int frame_no ) {
   189         vector<PointDouble > marker_corners_img_undist;
   190         marker_corners_img_undist.resize(_marker_corners_img.size());
   191         copy(_marker_corners_img.begin(), _marker_corners_img.end(), marker_corners_img_undist.begin());
   195         vector<PointDouble> marker_points_img(marker_points.size());
   196         marker_points_img.resize(marker_points.size());
   197         cam->
Undistort(marker_corners_img_undist);
   198         H.Find(marker_corners, marker_corners_img_undist);
   199         H.ProjectPoints(marker_points, marker_points_img);
   200         cam->
Distort(marker_points_img);
   202         ros_marker_points_img.clear();
   206         double min = 255.0, max = 0.0;
   207         for (
int j=0; j<marker_content->height; j++) {
   208                 for (
int i=0; i<marker_content->width; i++) {
   209                         x = (int)(0.5+
Limit(marker_points_img[(j*marker_content->width)+i].x, 1, gray->width-2));
   210                         y = (int)(0.5+
Limit(marker_points_img[(j*marker_content->width)+i].y, 1, gray->height-2));
   212                         marker_points_img[(j*marker_content->width)+i].val = (
int)cvGetReal2D(gray, y, x);
   229                         cvSet2D(marker_content, j, i, cvScalar(marker_points_img[(j*marker_content->width)+i].val));
   230                         if(marker_points_img[(j*marker_content->width)+i].val > max) max = marker_points_img[(j*marker_content->width)+i].val;
   231                         if(marker_points_img[(j*marker_content->width)+i].val < min) min = marker_points_img[(j*marker_content->width)+i].val;
   237         vector<PointDouble> marker_margin_w_img(marker_margin_w.size());
   238         vector<PointDouble> marker_margin_b_img(marker_margin_b.size());
   239         H.ProjectPoints(marker_margin_w, marker_margin_w_img);
   240         H.ProjectPoints(marker_margin_b, marker_margin_b_img);
   241         cam->
Distort(marker_margin_w_img);
   242         cam->
Distort(marker_margin_b_img);
   245         for (
size_t i=0; i<marker_margin_w_img.size(); i++) {
   246                 x = (int)(0.5+
Limit(marker_margin_w_img[i].x, 0, gray->width-1));
   247                 y = (int)(0.5+
Limit(marker_margin_w_img[i].y, 0, gray->height-1));
   248                 marker_margin_w_img[i].val = (int)cvGetReal2D(gray, y, x);
   249                 max += marker_margin_w_img[i].val;
   253         for (
size_t i=0; i<marker_margin_b_img.size(); i++) {
   254                 x = (int)(0.5+
Limit(marker_margin_b_img[i].x, 0, gray->width-1));
   255                 y = (int)(0.5+
Limit(marker_margin_b_img[i].y, 0, gray->height-1));
   256                 marker_margin_b_img[i].val = (int)cvGetReal2D(gray, y, x);
   257                 min += marker_margin_b_img[i].val;
   262         max /= marker_margin_w_img.size();
   263         min /= marker_margin_b_img.size();
   266         cvThreshold(marker_content, marker_content, (max+min)/2.0, 255, CV_THRESH_BINARY);
   271         for (
size_t i=0; i<marker_margin_w_img.size(); i++) {
   272                 if (marker_margin_w_img[i].val < (max+min)/2.0) erroneous++;
   275         for (
size_t i=0; i<marker_margin_b_img.size(); i++) {
   276                 if (marker_margin_b_img[i].val > (max+min)/2.0) erroneous++;
   279         margin_error = (double)erroneous/total;
   282 #ifdef VISUALIZE_MARKER_POINTS   285         marker_allpoints_img.clear();
   286         for (
size_t i=0; i<marker_margin_w_img.size(); i++) {
   288                 if (p.val < (max+min)/2.0) p.val=255; 
   290                 marker_allpoints_img.push_back(p);
   292         for (
size_t i=0; i<marker_margin_b_img.size(); i++) {
   294                 if (p.val > (max+min)/2.0) p.val=255; 
   296                 marker_allpoints_img.push_back(p);
   298         for (
size_t i=0; i<marker_points_img.size(); i++) {
   301                 marker_allpoints_img.push_back(p);
   306 void Marker::UpdatePose(vector<PointDouble > &_marker_corners_img, 
Camera *
cam, 
int orientation, 
int frame_no , 
bool update_pose ) {
   307         marker_corners_img.resize(_marker_corners_img.size());
   308         copy(_marker_corners_img.begin(), _marker_corners_img.end(), marker_corners_img.begin());
   312                 std::rotate(marker_corners_img.begin(), marker_corners_img.begin() + orientation, marker_corners_img.end());
   316 bool Marker::DecodeContent(
int *orientation) {
   322 void Marker::SaveMarkerImage(
const char *filename, 
int save_res)
 const {
   330         IplImage *img = cvCreateImage(cvSize(save_res, save_res), IPL_DEPTH_8U, 1);
   331         IplImage *img_content = cvCreateImage(cvSize(
int(
res*scale+0.5), 
int(
res*scale+0.5)), IPL_DEPTH_8U, 1);
   334         cvGetSubRect(img, &submat, cvRect(
int(
margin*scale), 
int(
margin*scale), 
int(
res*scale), 
int(
res*scale)));
   335         cvResize(marker_content, img_content, CV_INTER_NN);
   336         cvCopy(img_content, &submat);
   337         cvSaveImage(filename, img);
   338         cvReleaseImage(&img_content);
   339         cvReleaseImage(&img);
   342 void Marker::ScaleMarkerToImage(IplImage *
image)
 const {
   343         const int multiplier=96;
   345         IplImage *img_content = cvCreateImage(cvSize(
int(multiplier*
res+0.5), 
int(multiplier*
res+0.5)), IPL_DEPTH_8U, 1);
   348         cvGetSubRect(img, &submat, cvRect(
int(multiplier*
margin+0.5), 
int(multiplier*
margin+0.5), 
int(multiplier*
res+0.5), 
int(multiplier*
res+0.5)));
   349         cvResize(marker_content, img_content, CV_INTER_NN);
   350         cvCopy(img_content, &submat);
   351         cvResize(img, image, CV_INTER_NN);
   352         cvReleaseImage(&img_content);
   353         cvReleaseImage(&img);
   356 void Marker::SetMarkerSize(
double _edge_length, 
int _res, 
double _margin) {
   358         edge_length = (_edge_length?_edge_length:1);
   360         margin = (_margin?_margin:1);
   361         double x_min = -0.5*edge_length;
   362         double y_min = -0.5*edge_length;
   363         double x_max = 0.5*edge_length;
   364         double y_max = 0.5*edge_length;
   372         marker_corners_img.resize(4);
   375         marker_corners.clear();
   376         marker_corners.push_back(
PointDouble(x_min, y_min));
   377         marker_corners.push_back(
PointDouble(x_max, y_min));
   378         marker_corners.push_back(
PointDouble(x_max, y_max));
   379         marker_corners.push_back(
PointDouble(x_min, y_max));
   382         if (
res <= 0) 
return;
   385         marker_points.clear();
   386         for(
int j = 0; j < 
res; ++j) {
   387                 for(
int i = 0; i < 
res; ++i) {
   389                         pt.y = cy_max - (step*j) - (step/2);
   390                         pt.x = cx_min + (step*i) + (step/2);
   391                         marker_points.push_back(pt);
   398         marker_margin_w.clear();
   399         marker_margin_b.clear();
   400         for(
int j = -1; j<=
margin-1; j++) {
   403                 for (
int i=0; i<
res; i++) {
   404                         pt.x = cx_min + step*i + step/2;
   405                         pt.y = y_min + step*j + step/2;
   406                         if (j < 0) marker_margin_w.push_back(pt);
   407                         else marker_margin_b.push_back(pt);
   408                         pt.y = y_max - step*j - step/2;
   409                         if (j < 0) marker_margin_w.push_back(pt);
   410                         else marker_margin_b.push_back(pt);
   411                         pt.y = cy_min + step*i + step/2;
   412                         pt.x = x_min + step*j + step/2;
   413                         if (j < 0) marker_margin_w.push_back(pt);
   414                         else marker_margin_b.push_back(pt);
   415                         pt.x = x_max - step*j - step/2;
   416                         if (j < 0) marker_margin_w.push_back(pt);
   417                         else marker_margin_b.push_back(pt);
   420                 for(
int i = -1; i<=
margin-1; i++) {
   421                         pt.x = x_min + step*i + step/2;
   422                         pt.y = y_min + step*j + step/2;
   423                         if ((j < 0) || (i < 0)) marker_margin_w.push_back(pt);
   424                         else marker_margin_b.push_back(pt);
   425                         pt.x = x_min + step*i + step/2;
   426                         pt.y = y_max - step*j - step/2;
   427                         if ((j < 0) || (i < 0)) marker_margin_w.push_back(pt);
   428                         else marker_margin_b.push_back(pt);
   429                         pt.x = x_max - step*i - step/2;
   430                         pt.y = y_max - step*j - step/2;
   431                         if ((j < 0) || (i < 0)) marker_margin_w.push_back(pt);
   432                         else marker_margin_b.push_back(pt);
   433                         pt.x = x_max - step*i - step/2;
   434                         pt.y = y_min + step*j + step/2;
   435                         if ((j < 0) || (i < 0)) marker_margin_w.push_back(pt);
   436                         else marker_margin_b.push_back(pt);
   511         if (marker_content) cvReleaseMat(&marker_content);
   512         marker_content = cvCreateMat(res, res, CV_8U);
   513         cvSet(marker_content, cvScalar(255));
   516         if (marker_content) cvReleaseMat(&marker_content);
   518 Marker::Marker(
double _edge_length, 
int _res, 
double _margin)
   520         marker_content = NULL;
   524         SetMarkerSize(_edge_length, _res, _margin);
   525         ros_orientation = -1;
   526         ros_corners_3D.resize(4);
   530         marker_content = NULL;
   552 #ifdef VISUALIZE_MARKER_POINTS   553         marker_allpoints_img.resize(m.marker_allpoints_img.size());
   554         copy(m.marker_allpoints_img.begin(), m.marker_allpoints_img.end(), marker_allpoints_img.begin());
   558 bool MarkerArtoolkit::DecodeContent(
int *orientation) {
   559         int a = (int)cvGetReal2D(marker_content, 0, 0);
   560         int b = (int)cvGetReal2D(marker_content, 
res-1, 0);
   561         int c = (int)cvGetReal2D(marker_content, 
res-1, 
res-1);
   562         int d = (int)cvGetReal2D(marker_content, 0, 
res-1);
   563         if (!a && !b && c) *orientation = 0;
   564         else if (!b && !c && d) *orientation = 1;
   565         else if (!c && !d && a) *orientation = 2;
   566         else if (!d && !a && b) *orientation = 3;
   571         for (
int j = 0; j < 
res; j++) {
   572                 for (
int i = 0; i < 
res ; i++) {
   573                         if (*orientation == 0) {
   574                                 if ((j == 0)     && (i == 0)) 
continue;
   575                                 if ((j == res-1) && (i == 0)) 
continue;
   576                                 if ((j == res-1) && (i == res-1)) 
continue;
   577                                 if (cvGetReal2D(marker_content, j, i)) bs.
push_back(
false);
   580                         else if (*orientation == 1) {
   581                                 if (((res-i-1) == res-1) && (j == 0)) 
continue;
   582                                 if (((res-i-1) == res-1) && (j == res-1)) 
continue;
   583                                 if (((res-i-1) == 0)     && (j == res-1)) 
continue;
   584                                 if (cvGetReal2D(marker_content, res-i-1, j)) bs.
push_back(
false);
   587                         else if (*orientation == 2) {
   588                                 if (((res-j-1) == res-1) && ((res-i-1) == res-1)) 
continue;
   589                                 if (((res-j-1) == 0)     && ((res-i-1) == res-1)) 
continue;
   590                                 if (((res-j-1) == 0)     && ((res-i-1) == 0)) 
continue;
   591                                 if (cvGetReal2D(marker_content, res-j-1, res-i-1)) bs.
push_back(
false);
   594                         else if (*orientation == 3) {
   595                                 if ((i == 0)     && ((res-j-1) == res-1)) 
continue;
   596                                 if ((i == 0)     && ((res-j-1) == 0)) 
continue;
   597                                 if ((i == res-1) && ((res-j-1) == 0)) 
continue;
   598                                 if (cvGetReal2D(marker_content, i, res-j-1)) bs.
push_back(
false);
   607 void MarkerArtoolkit::SetContent(
unsigned long _id) {
   614         for (
int j = 
res-1; j >= 0; j--) {
   615                 for (
int i = 
res-1; i >= 0 ; i--) {
   616                         if ((j == 0)     && (i == 0))
   617                                 cvSetReal2D(marker_content, j, i, 0);
   618                         else if ((j == 
res-1) && (i == 0))
   619                                 cvSetReal2D(marker_content, j, i, 0);
   620                         else if ((j == 
res-1) && (i == 
res-1)) 
   621                                 cvSetReal2D(marker_content, j, i, 255);
   624                                         cvSetReal2D(marker_content, j, i, 0);
   626                                         cvSetReal2D(marker_content, j, i, 255);
   632 void MarkerData::DecodeOrientation(
int *error, 
int *total, 
int *orientation) {
   634         vector<double> errors(4);
   639         for (i=0; i<
res; i++) {
   641                 if ((
int)cvGetReal2D(marker_content, j, i) != color) errors[0]++;
   642                 if ((
int)cvGetReal2D(marker_content, i, j) != color) errors[1]++;
   643                 color = (color?0:255);
   645         errors[2] = errors[0];
   646         errors[3] = errors[1];
   650         for (j = (res/2)-2; j <= (res/2)+2; j++) {
   653                         if ((
int)cvGetReal2D(marker_content, j, i)       !=   0) errors[0]++;
   654                         if ((
int)cvGetReal2D(marker_content, i, j)       !=   0) errors[1]++;
   655                         if ((
int)cvGetReal2D(marker_content, j, i)       != 255) errors[2]++;
   656                         if ((
int)cvGetReal2D(marker_content, i, j)       != 255) errors[3]++;
   657                 } 
else if (j > (res/2)) {
   659                         if ((
int)cvGetReal2D(marker_content, j, i)       != 255) errors[0]++;
   660                         if ((
int)cvGetReal2D(marker_content, i, j)       != 255) errors[1]++;
   661                         if ((
int)cvGetReal2D(marker_content, j, i)       !=   0) errors[2]++;
   662                         if ((
int)cvGetReal2D(marker_content, i, j)       !=   0) errors[3]++;
   665         *orientation = min_element(errors.begin(), errors.end()) - errors.begin();
   666         *error = int(errors[*orientation]);
   670 bool MarkerData::DetectResolution(vector<PointDouble > &_marker_corners_img, IplImage *
gray, 
Camera *
cam) {
   671         vector<PointDouble> marker_corners_img_undist;
   672         marker_corners_img_undist.resize(_marker_corners_img.size());
   673         copy(_marker_corners_img.begin(), _marker_corners_img.end(), marker_corners_img_undist.begin());
   676         std::vector<PointDouble> line_points;
   679         pt.x=0; pt.y=0; line_points.push_back(pt);
   680         pt.x=-0.5*edge_length; pt.y=0; line_points.push_back(pt);
   681         pt.x=+0.5*edge_length; pt.y=0; line_points.push_back(pt);
   682         pt.x=0; pt.y=-0.5*edge_length; line_points.push_back(pt);
   683         pt.x=0; pt.y=+0.5*edge_length; line_points.push_back(pt);
   690         vector<PointDouble> line_points_img(line_points.size());
   691         line_points_img.resize(line_points.size());
   692         cam->
Undistort(marker_corners_img_undist);
   693         H.
Find(marker_corners, marker_corners_img_undist);
   699         int white_count[4] = {0}; 
   701         pt2.x = int(line_points_img[0].
x);
   702         pt2.y = int(line_points_img[0].
y);
   703         if ((pt2.x < 0) || (pt2.y < 0) ||
   704                 (pt2.x >= gray->width) || (pt2.y >= gray->height))
   709         for (
int i=0; i<4; i++) {
   710                 CvLineIterator iterator;
   711                 pt1.x = int(line_points_img[i+1].x);
   712                 pt1.y = int(line_points_img[i+1].y);
   713                 if ((pt1.x < 0) || (pt1.y < 0) ||
   714                         (pt1.x >= gray->width) || (pt1.y >= gray->height))
   718                 int count = cvInitLineIterator(gray, pt1, pt2, &iterator, 8, 0);
   719                 std::vector<uchar> vals;
   720                 for(
int ii = 0; ii < count; ii++ ){
   721                         CV_NEXT_LINE_POINT(iterator);
   722                         vals.push_back(*(iterator.ptr));
   724                 uchar vmin = *(std::min_element(vals.begin(), vals.end()));
   725                 uchar vmax = *(std::max_element(vals.begin(), vals.end()));
   726                 uchar thresh = (vmin+vmax)/2;
   729                 for (
size_t ii=0; ii<vals.size(); ii++) {
   732                         if (vals[ii] < thresh) { bc++; wc=0; }
   735                         if (white && (bc >= N)) {
   738                         else if (!white && (wc >= N)) {
   745         if ((white_count[0]+white_count[1]) == (white_count[2]+white_count[3])) 
return false;
   746         else if ((white_count[0]+white_count[1]) > (white_count[2]+white_count[3])) {
   747                 if (white_count[0] != white_count[1]) 
return false;
   748                 if (white_count[0] < 2) 
return false;
   749                 int nof_whites = white_count[0]*2-(white?1:0); 
   750                 int new_res = 2*nof_whites-1;
   751                 SetMarkerSize(edge_length, new_res, 
margin);
   754                 if (white_count[2] != white_count[3]) 
return false;
   755                 if (white_count[2] < 2) 
return false;
   756                 if (((white_count[2]%2) == 0) != white) 
return false;
   757                 int nof_whites = white_count[2]*2-(white?1:0);
   758                 int new_res = 2*nof_whites-1;
   759                 SetMarkerSize(edge_length, new_res, 
margin);
   764 bool MarkerData::UpdateContent(vector<PointDouble > &_marker_corners_img, IplImage *
gray, 
Camera *
cam, 
int frame_no ) {
   766                 if (!DetectResolution(_marker_corners_img, gray, cam)) 
return false;
   768         return UpdateContentBasic(_marker_corners_img, gray, cam, frame_no);
   771 int MarkerData::DecodeCode(
int orientation, 
BitsetExt *bs, 
int *erroneous, 
int *total, 
   772         unsigned char* content_type) 
   776         for (
int j = 0; j < 
res; j++) {
   777                 for (
int i = 0; i < 
res ; i++) {
   779                         if ((orientation == 0) || (orientation == 2)) {
   780                                 if (j == res/2) 
continue;
   781                                 if ((i == res/2) && (j >= (res/2)-2) && (j <= (res/2)+2)) 
continue;
   783                                 if (i == res/2) 
continue;
   784                                 if ((j == res/2) && (i >= (res/2)-2) && (i <= (res/2)+2)) 
continue;
   787                         if (orientation == 0) color = (int)cvGetReal2D(marker_content, j, i);
   788                         else if (orientation == 1) color = (int)cvGetReal2D(marker_content, res-i-1, j);
   789                         else if (orientation == 2) color = (int)cvGetReal2D(marker_content, res-j-1, res-i-1);
   790                         else if (orientation == 3) color = (int)cvGetReal2D(marker_content, i, res-j-1);
   797         unsigned char flags = 0;
   815                 flags = header.
uchar();
   818                 flags &= MARKER_CONTENT_TYPE_NUMBER;
   824         *content_type = flags & 0x7;
   826         if (errors > 0) (*erroneous) += errors;
   829 void MarkerData::Read6bitStr(
BitsetExt *bs, 
char *s, 
size_t s_max_len) {
   830         deque<bool> bits = bs->
GetBits();
   831         deque<bool>::const_iterator iter;
   835         for (iter = bits.begin(); iter != bits.end(); iter++) {
   836                 if (*iter) c |= (0x01 << bitpos);
   839                         if (c == 000)                      s[len] = 
':';
   840                         else if ((c >= 001) && (c <= 032)) s[len] = 
'a' + (char)c - 1;
   841                         else if ((c >= 033) && (c <= 044)) s[len] = 
'0' + (char)c - 1;
   842                         else if (c == 045)                 s[len] = 
'+';
   843                         else if (c == 046)                 s[len] = 
'-';
   844                         else if (c == 047)                 s[len] = 
'*';
   845                         else if (c == 050)                 s[len] = 
'/';
   846                         else if (c == 051)                 s[len] = 
'(';
   847                         else if (c == 052)                 s[len] = 
')';
   848                         else if (c == 053)                 s[len] = 
'$';
   849                         else if (c == 054)                 s[len] = 
'=';
   850                         else if (c == 055)                 s[len] = 
' ';
   851                         else if (c == 056)                 s[len] = 
',';
   852                         else if (c == 057)                 s[len] = 
'.';
   853                         else if (c == 060)                 s[len] = 
'#';
   854                         else if (c == 061)                 s[len] = 
'[';
   855                         else if (c == 062)                 s[len] = 
']';
   856                         else if (c == 063)                 s[len] = 
'%';
   857                         else if (c == 064)                 s[len] = 
'\"';
   858                         else if (c == 065)                 s[len] = 
'_';
   859                         else if (c == 066)                 s[len] = 
'!';
   860                         else if (c == 067)                 s[len] = 
'&';
   861                         else if (c == 070)                 s[len] = 
'\'';
   862                         else if (c == 071)                 s[len] = 
'?';
   863                         else if (c == 072)                 s[len] = 
'<';
   864                         else if (c == 073)                 s[len] = 
'>';
   865                         else if (c == 074)                 s[len] = 
'@';
   866                         else if (c == 075)                 s[len] = 
'\\';
   867                         else if (c == 076)                 s[len] = 
'^';
   868                         else if (c == 077)                 s[len] = 
';';
   871                         if (len >= (s_max_len-1)) 
break;
   878 bool MarkerData::DecodeContent(
int *orientation) {
   886         DecodeOrientation(&erroneous, &total, orientation);
   887         int err = DecodeCode(*orientation, &bs, &erroneous, &total, &content_type);
   890                 decode_error = DBL_MAX;
   894         if(content_type == MARKER_CONTENT_TYPE_NUMBER){
   895                 data.id = bs.
ulong();
   898                 Read6bitStr(&bs, data.str, MAX_MARKER_STRING_LEN);
   901         decode_error = (double)(erroneous)/total;
   908                 unsigned char c = (
unsigned char)*s;
   909                 if (c == 
':')                      bs->
push_back((
unsigned char)0,6);
   910                 else if ((c >= 
'A') && (c <= 
'Z')) bs->
push_back((
unsigned char)(001 + c - 
'A'),6);
   911                 else if ((c >= 
'a') && (c <= 
'z')) bs->
push_back((
unsigned char)(001 + c - 
'a'),6);
   912                 else if ((c >= 
'0') && (c <= 
'9')) bs->
push_back((
unsigned char)(033 + c - 
'0'),6);
   913                 else if (c == 
'+')                 bs->
push_back((
unsigned char)045,6);
   914                 else if (c == 
'-')                 bs->
push_back((
unsigned char)046,6);
   915                 else if (c == 
'*')                 bs->
push_back((
unsigned char)047,6);
   916                 else if (c == 
'/')                 bs->
push_back((
unsigned char)050,6);
   917                 else if (c == 
'(')                 bs->
push_back((
unsigned char)051,6);
   918                 else if (c == 
')')                 bs->
push_back((
unsigned char)052,6);
   919                 else if (c == 
'$')                 bs->
push_back((
unsigned char)053,6);
   920                 else if (c == 
'=')                 bs->
push_back((
unsigned char)054,6);
   921                 else if (c == 
' ')                 bs->
push_back((
unsigned char)055,6);
   922                 else if (c == 
',')                 bs->
push_back((
unsigned char)056,6);
   923                 else if (c == 
'.')                 bs->
push_back((
unsigned char)057,6);
   924                 else if (c == 
'#')                 bs->
push_back((
unsigned char)060,6);
   925                 else if (c == 
'[')                 bs->
push_back((
unsigned char)061,6);
   926                 else if (c == 
']')                 bs->
push_back((
unsigned char)062,6);
   927                 else if (c == 
'%')                 bs->
push_back((
unsigned char)063,6);
   928                 else if (c == 
'\"')                bs->
push_back((
unsigned char)064,6);
   929                 else if (c == 
'_')                 bs->
push_back((
unsigned char)065,6);
   930                 else if (c == 
'!')                 bs->
push_back((
unsigned char)066,6);
   931                 else if (c == 
'&')                 bs->
push_back((
unsigned char)067,6);
   932                 else if (c == 
'\'')                bs->
push_back((
unsigned char)070,6);
   933                 else if (c == 
'?')                 bs->
push_back((
unsigned char)071,6);
   934                 else if (c == 
'<')                 bs->
push_back((
unsigned char)072,6);
   935                 else if (c == 
'>')                 bs->
push_back((
unsigned char)073,6);
   936                 else if (c == 
'@')                 bs->
push_back((
unsigned char)074,6);
   937                 else if (c == 
'\\')                bs->
push_back((
unsigned char)075,6);
   938                 else if (c == 
'^')                 bs->
push_back((
unsigned char)076,6);
   939                 else if (c == 
';')                 bs->
push_back((
unsigned char)077,6);
   940                 else                               bs->
push_back((
unsigned char)071,6);
   945 int MarkerData::UsableDataBits(
int marker_res, 
int hamming) {
   946         if (marker_res < 5) 
return 0;
   947         if (!(marker_res % 2)) 
return 0;
   948         int bits = marker_res * marker_res;
   949         if (marker_res > 5) bits -= 8; 
   952         int tail = bits % hamming; 
   953         if (tail < 3) bits -= tail;    
   957 void MarkerData::SetContent(
MarkerContentType _content_type, 
unsigned long _id, 
const char *_str, 
bool force_strong_hamming, 
bool verbose) {
   959         content_type = _content_type;
   962         if (content_type == MARKER_CONTENT_TYPE_NUMBER) {
   965                 STRCPY(data.str, MAX_MARKER_STRING_LEN, _str);
   968         const int max_marker_res = 127;
   974         if (content_type == MARKER_CONTENT_TYPE_NUMBER) {
   976                 for (
res=5; 
res<max_marker_res; 
res+=2) {
   978                         enc_bits = UsableDataBits(
res, hamming);
   979                         data_bits = BitsetExt::count_hamming_dec_len(hamming, enc_bits);
   980                         if (data_bits >= bs_data.
Length()) 
break;
   981                         if ((
res > 5) && !force_strong_hamming) {
   983                                 enc_bits = UsableDataBits(
res, hamming);
   984                                 data_bits = BitsetExt::count_hamming_dec_len(hamming, enc_bits);
   985                                 if (data_bits >= bs_data.
Length()) 
break;
   991                         cout<<
"Using hamming("<<hamming<<
") for "<<
res<<
"x"<<
res<<
" marker"<<endl;
   992                         cout<<bs_data.
Length()<<
" bits are filled into "<<data_bits;
   993                         cout<<
" bits, and encoded into "<<enc_bits<<
" bits"<<endl;
   994                         cout<<
"data src: "; bs_data.
Output(cout); cout<<endl;
   995                         cout<<
"data enc: "; bs_data.
Output(cout); cout<<endl;
   998                         if (hamming == 16) bs_flags.
push_back(
true);
  1003                                 cout<<
"flags src: "; bs_flags.
Output(cout); cout<<endl;
  1004                                 cout<<
"flags enc: "; bs_flags.
Output(cout); cout<<endl;
  1008                 Add6bitStr(&bs_data, data.str);
  1009                 for (
res=7; 
res<max_marker_res; 
res+=2) {
  1011                         enc_bits = UsableDataBits(
res, hamming);
  1012                         data_bits = BitsetExt::count_hamming_dec_len(hamming, enc_bits);
  1013                         if (data_bits >= bs_data.
Length()) 
break;
  1014                         if (!force_strong_hamming) {
  1016                                 enc_bits = UsableDataBits(
res, hamming);
  1017                                 data_bits = BitsetExt::count_hamming_dec_len(hamming, enc_bits);
  1018                                 if (data_bits >= bs_data.
Length()) 
break;
  1021                 while (bs_data.
Length() < ((data_bits/6)*6)) {
  1022                         bs_data.
push_back((
unsigned char)055,6); 
  1024                 while (bs_data.
Length() < data_bits) {
  1028                 if (hamming == 16) bs_flags.
push_back(
true);
  1030                 if (content_type == MARKER_CONTENT_TYPE_STRING) bs_flags.
push_back((
unsigned long)1,3);
  1031                 else if (content_type == MARKER_CONTENT_TYPE_FILE) bs_flags.
push_back((
unsigned long)2,3);
  1032                 else if (content_type == MARKER_CONTENT_TYPE_HTTP) bs_flags.
push_back((
unsigned long)3,3);
  1035                         cout<<
"Using hamming("<<hamming<<
") for "<<
res<<
"x"<<
res<<
" marker"<<endl;
  1036                         cout<<bs_data.
Length()<<
" bits are filled into "<<data_bits;
  1037                         cout<<
" bits, and encoded into "<<enc_bits<<
" bits"<<endl;
  1038                         cout<<
"data src: "; bs_data.
Output(cout); cout<<endl;
  1039                         cout<<
"data enc: "; bs_data.
Output(cout); cout<<endl;
  1040                         cout<<
"flags src: "; bs_flags.
Output(cout); cout<<endl;
  1041                         cout<<
"flags enc: "; bs_flags.
Output(cout); cout<<endl;
  1046         deque<bool> bs(bs_flags.
GetBits());
  1047         bs.insert(bs.end(), bs_data.
GetBits().begin(), bs_data.
GetBits().end());
  1048         deque<bool>::const_iterator iter = bs.begin();
  1049         SetMarkerSize(edge_length, 
res, 
margin);
  1050         cvSet(marker_content, cvScalar(255));
  1051         for (
int j=0; j<
res; j++) {
  1052                 for (
int i=0; i<
res; i++) {
  1054                                 if (i%2) cvSet2D(marker_content, j, i, cvScalar(0));
  1055                         } 
else if ((i == res/2) && (j < res/2) && (j >= (res/2)-2)) {
  1056                                 cvSet2D(marker_content, j, i, cvScalar(0));
  1057                         } 
else if ((i == res/2) && (j > res/2) && (j <= (res/2)+2)) {
  1058                                 cvSet2D(marker_content, j, i, cvScalar(255));
  1060                                 if (iter != bs.end()) {
  1061                                         if (*iter) cvSet2D(marker_content, j, i, cvScalar(0));
 void clear()
Clear the bits. 
bool pop_back()
Pop the back bit. 
std::vector< PointDouble > marker_corners_img
Marker corners in image coordinates. 
Simple Homography class for finding and projecting points between two planes. 
unsigned long ulong()
The Bitset as 'unsigned long'. 
TFSIMD_FORCE_INLINE const tfScalar & y() const 
std::ostream & Output(std::ostream &os) const 
Output the bits to selected ostream. 
Simple Camera class for calculating distortions, orientation or projections with pre-calibrated camer...
bool pop_front()
Pop the front bit. 
void fill_zeros_left(const size_t bit_count)
Fill the Bitset with non-meaningful zeros. 
Pose pose
The current marker Pose. 
Bitset is a basic class for handling bit sequences 
void ProjectPoints(std::vector< CvPoint3D64f > &pw, Pose *pose, std::vector< CvPoint2D64f > &pi) const 
Project points. 
void Find(const std::vector< PointDouble > &pw, const std::vector< PointDouble > &pi)
Find Homography for two point-sets. 
void push_back_meaningful(const unsigned long l)
Push back meaningful bits from 'long' l. 
EIGEN_MAKE_ALIGNED_OPERATOR_NEW bool valid
TFSIMD_FORCE_INLINE const tfScalar & x() const 
std::vector< PointDouble > ros_marker_points_img
Marker points in image coordinates. 
Basic 2D Marker functionality. 
double PointSquaredDistance(PointType p1, PointType p2)
Returns the squared distance of two points. 
unsigned char uchar()
The Bitset as 'unsigned char'. 
int Length()
The length of the Bitset. 
std::deque< bool > & GetBits()
The Bitset as 'deque<bool>'. 
std::vector< PointDouble > marker_points
Marker color points in marker coordinates. 
void Distort(CvPoint2D32f &point)
Applys the lens distortion for one point on an image plane. 
int hamming_dec(int block_len)
Hamming decoding 'in-place' using the defined block length. 
ALVAR_EXPORT Point< CvPoint2D64f > PointDouble
The default double point type. 
Iterator implementation for traversing templated Marker vector without the template. 
void ProjectPoints(const std::vector< PointDouble > &from, std::vector< PointDouble > &to)
Project points using the Homography. 
void STRCPY(char *to, size_t size, const char *src)
void CalcExteriorOrientation(std::vector< CvPoint3D64f > &pw, std::vector< CvPoint2D64f > &pi, Pose *pose)
Calculate exterior orientation. 
void push_back(const bool bit)
Push back one bit. 
An extended Bitset ( BitsetExt ) for handling e.g. Hamming encoding/decoding. 
This file implements a marker interface as well as ALVAR markers and ARToolKit markers. 
This file defines library export definitions, version numbers and build information. 
double ALVAR_EXPORT Limit(double val, double min_val, double max_val)
Limits a number to between two values. 
ar_track_alvar::ARCloud ros_corners_3D
void Undistort(std::vector< PointDouble > &points)
Unapplys the lens distortion for points on image plane. 
std::vector< PointDouble > marker_corners
Marker corners in marker coordinates. 
void hamming_enc(int block_len)
Hamming encoding 'in-place' using the defined block length.