cvcalibinit_lowres.cpp
Go to the documentation of this file.
00001 /*
00002  *  plug.cpp
00003  *
00004  *
00005  *  Created by Victor  Eruhimov on 9/5/09.
00006  *  Copyright 2009 Argus Corp. All rights reserved.
00007  *
00008  */
00009 
00010 #include "checkerboard_pose_estimation/cvcalibinit_lowres.h"
00011 
00012 #include <stdio.h>
00013 #include <highgui.h>
00014 
00015 #include <outlet_pose_estimation/detail/features.h>
00016 
00017 using namespace std;
00018 
00019 //#define _DEBUG_WINDOWS
00020 
00021 struct chessboard_feature_t : public feature_t
00022 {
00023     int idx1, idx2;
00024 };
00025 
00026 void SelectNeighborFeatures(const vector<feature_t>& features, vector<feature_t>& neighbors, cv::Point2f point, float max_dist)
00027 {
00028     neighbors.resize(0);
00029     for(int i = 0; i < (int)features.size(); i++)
00030     {
00031         if(length(features[i].pt - point) < max_dist)
00032         {
00033             neighbors.push_back(features[i]);
00034         }
00035     }
00036 }
00037 
00038 template <class T>
00039 int Find1NN(const vector<T>& features, cv::Point2f point, int exclude_point = 0)
00040 {
00041     int min_idx = -1;
00042     float min_dist = 1e10;
00043     const float min_flt_dist = 1e-5;
00044     for(size_t i = 0; i < features.size(); i++)
00045     {
00046         if(exclude_point && norm(features[i].pt - point) < min_flt_dist)
00047             continue;
00048         float dist = length(features[i].pt - point);
00049         if(dist < min_dist)
00050         {
00051             min_dist = dist;
00052             min_idx = i;
00053         }
00054     }
00055 
00056     return min_idx;
00057 }
00058 
00059 int find(const vector<int>& indices, int idx)
00060 {
00061     for(size_t j = 0; j < indices.size(); j++)
00062     {
00063         if(indices[j] == idx)
00064         {
00065             return j;
00066         }
00067     }
00068 
00069     return -1;
00070 }
00071 
00072 int Find1NNEx(const vector<feature_t>& features, cv::Point2f point, const vector<int>& exclude_points)
00073 {
00074     int min_idx = -1;
00075     float min_dist = 1e10;
00076     const float min_flt_dist = 1e-5;
00077     for(size_t i = 0; i < features.size(); i++)
00078     {
00079         if(norm(features[i].pt - point) < min_flt_dist)
00080             continue;
00081         if(find(exclude_points, i) >= 0) continue;
00082 
00083         float dist = length(features[i].pt - point);
00084         if(dist < min_dist)
00085         {
00086             min_dist = dist;
00087             min_idx = i;
00088         }
00089     }
00090 
00091     return min_idx;
00092 }
00093 
00094 int Find2NNPerp(const vector<feature_t>& features, cv::Point2f point, cv::Point2f dir)
00095 {
00096     int idx = -1;
00097     float min_dist = 1e10;
00098     float dir_norm = norm(dir);
00099     const float min_perp_dist = dir_norm*0.5f;
00100 
00101     for(size_t i = 0; i < features.size(); i++)
00102     {
00103         if(norm(features[i].pt - point) < 1e-5)
00104             continue;
00105         cv::Point2f pdir = features[i].pt - point;
00106         float perp_dist = norm(pdir - dir*pdir.dot(dir)*(1.0f/(dir_norm*dir_norm)));
00107         if(perp_dist < min_perp_dist) continue; // filter out points on the dir line
00108 
00109         float dist = norm(pdir);
00110         if(dist < min_dist)
00111         {
00112             min_dist = dist;
00113             idx = i;
00114         }
00115     }
00116 
00117     return idx;
00118 }
00119 
00120 int CountPoints(const vector<feature_t>& features, cv::Point2f point, cv::Point2f dir,
00121                 int dir_sign = 0, int* border_point_idx = 0)
00122 {
00123     if(dir_sign == 0)
00124     {
00125         int count1 = CountPoints(features, point, dir, 1);
00126         int count2 = CountPoints(features, point, dir, -1);
00127         return count1 + count2;
00128     }
00129 
00130     int count = 1;
00131     float dir_norm = norm(dir);
00132     const float min_dist = dir_norm*0.2f;
00133     for(;;count++)
00134     {
00135         cv::Point2f new_point = point + dir*float(count*dir_sign);
00136         int idx = Find1NN(features, new_point);
00137         cv::Point2f offset = new_point - features[idx].pt;
00138 
00139         if(norm(offset) > min_dist)
00140         {
00141             break;
00142         }
00143         else
00144         {
00145             if(border_point_idx) *border_point_idx = idx;
00146         }
00147     }
00148 
00149     return count - 1;
00150 }
00151 
00152 int IsBorderPoint(const vector<feature_t>& features, cv::Point2f point, cv::Point2f dir_border, cv::Point2f dir_second)
00153 {
00154     cv::Point2f dir1 = (dir_border - dir_second)*0.5f;
00155     cv::Point2f dir2 = (dir_border + dir_second)*0.5f;
00156     float min_dist = 0.2f*MAX(norm(dir1), norm(dir2));
00157 
00158     int idx1 = Find1NN(features, point + dir1);
00159     int idx2 = Find1NN(features, point + dir2);
00160     cv::Point2f offset1 = features[idx1].pt - point - dir1;
00161     cv::Point2f offset2 = features[idx2].pt - point - dir2;
00162     if(norm(offset1) > min_dist && norm(offset2) > min_dist)
00163     {
00164         return 1;
00165     }
00166     else
00167     {
00168         return 0;
00169     }
00170 }
00171 
00172 bool helper_corner_less(chessboard_feature_t f1, chessboard_feature_t f2)
00173 {
00174     return f1.angle < f2.angle;
00175 }
00176 
00177 float calc_corner_weight(const cv::Point2f& point, const cv::Point2f& origin, const cv::Point2f& dir1, const cv::Point2f& dir2,
00178             float weight_coeff)
00179 {
00180     cv::Point2f cp = point - origin;
00181     cv::Point2f corner_pointm = cv::Point2f(-cp.y, cp.x);
00182     float sprod1 = corner_pointm.dot(dir2)/(- dir2.x*dir1.y + dir2.y*dir1.x)*2;//*norm(dir1);
00183     float sprod2 = corner_pointm.dot(dir1)/(dir2.x*dir1.y - dir2.y*dir1.x)*2;//*norm(dir2);
00184     //                            printf("cpm = %f,%f, sprod1 = %f, sprod2 = %f\n",
00185     //                                   corner_point.pt.x*2, corner_point.pt.y*2, sprod1, sprod2);
00186     sprod1 = round(sprod1);
00187     sprod2 = round(sprod2);
00188 
00189     float weight = sprod2*weight_coeff + sprod1;
00190     return weight;
00191 }
00192 
00193 void ShowFeatures(IplImage* img, const vector<feature_t>& features)
00194 {
00195     IplImage* test = cvCloneImage(img);
00196 
00197     for(size_t i = 0; i < features.size(); i++)
00198     {
00199         cvCircle(test, features[i].pt, features[i].size, cvScalar(255));
00200         printf("feature %d: %f,%f\n", (int)i, features[i].pt.x, features[i].pt.y);
00201     }
00202     cvNamedWindow("1", 1);
00203     cvShowImage("1", test);
00204     cvWaitKey(0);
00205 
00206     cvSaveImage("features.jpg", test);
00207 
00208     cvReleaseImage(&test);
00209 }
00210 
00211 void FilterOutliers(vector<chessboard_feature_t>& corners, cv::Point2f dir1, cv::Point2f dir2, float min_dist)
00212 {
00213     vector<chessboard_feature_t> corners_filtered;
00214     for(size_t i = 0; i < corners.size(); i++)
00215     {
00216         cv::Point2f p = corners[i].pt;
00217         int count_neighbors = 0;
00218 
00219         for(int sign2 = -1; sign2 <= 1; sign2 += 2)
00220         {
00221             for(int sign1 = -1; sign1 <= 1; sign1 += 2)
00222             {
00223                 int _sign1 = (sign1 + sign2)/2;
00224                 int _sign2 = (sign1 - sign2)/2;
00225                 cv::Point2f pnn = p + dir1*float(_sign1) + dir2*float(_sign2);
00226                 int idx = Find1NN(corners, pnn);
00227                 cv::Point2f offset = corners[idx].pt - pnn;
00228                 if(norm(offset) < min_dist)
00229                 {
00230                     count_neighbors++;
00231                 }
00232             }
00233         }
00234 
00235         if(count_neighbors > 1)
00236         {
00237             corners_filtered.push_back(corners[i]);
00238         }
00239     }
00240 
00241     corners = corners_filtered;
00242 }
00243 
00244 void updateSpanVector(vector<chessboard_feature_t>::const_iterator it_begin, vector<chessboard_feature_t>::const_iterator it_end,
00245                     vector<chessboard_feature_t>::const_iterator& it_origin, cv::Point2f& dir)
00246 {
00247     vector<chessboard_feature_t>::const_iterator it_min = it_end, it_max = it_end;
00248     float min_weight = 1e10;
00249     float max_weight = -1e10;
00250     cv::Point2f origin = it_begin->pt;
00251     for(vector<chessboard_feature_t>::const_iterator it = it_begin; it != it_end; it++)
00252     {
00253         cv::Point2f offset = it->pt - origin;
00254         float weight = dir.dot(offset);
00255         if(weight < min_weight)
00256         {
00257             min_weight = weight;
00258             it_min = it;
00259         }
00260         if(weight > max_weight)
00261         {
00262             max_weight = weight;
00263             it_max = it;
00264         }
00265     }
00266 
00267     dir = it_max->pt - it_min->pt;
00268     it_origin = it_min;
00269 }
00270 
00271 float sortSpannedFeatures(vector<chessboard_feature_t>::iterator it_begin, vector<chessboard_feature_t>::iterator it_end,
00272     cv::Point2f origin, cv::Point2f dir)
00273 {
00274     float max_dist = 0;
00275     for(vector<chessboard_feature_t>::iterator it = it_begin; it != it_end; it++)
00276     {
00277         cv::Point2f p = it->pt - origin;
00278         cv::Point2f p_dir = dir*p.dot(dir)*(1.0f/(dir.dot(dir)));
00279         it->angle = p.dot(dir)/sqrt(dir.dot(dir));
00280         float dist = sqrt((p - p_dir).dot(p - p_dir));
00281         max_dist = MAX(max_dist, dist);
00282     }
00283 
00284     sort(it_begin, it_end, helper_corner_less);
00285 
00286     return max_dist;
00287 }
00288 
00289 int CountBorderPoints(const vector<feature_t>& features, cv::Point2f origin, cv::Point2f dir)
00290 {
00291     int counts[2] = {0, 0};
00292     for(size_t i = 0; i < features.size(); i++)
00293     {
00294         cv::Point2f offset = features[i].pt - origin;
00295         float prod = offset.x*dir.y - offset.y*dir.x;
00296         counts[prod > 0]++;
00297     }
00298 
00299     return MIN(counts[0], counts[1]);
00300 }
00301 
00302 int cvFindChessboardCornersLowres(IplImage* img, CvSize size, CvPoint2D32f* corners, int* corner_count)
00303 {
00304     vector<feature_t> features;
00305     const float contrast = 1.2f;
00306     IplImage* smoothed = cvCloneImage(img);
00307     cvSmooth(img, smoothed);
00308     GetHoleFeatures(smoothed, features, contrast);
00309     vector<feature_t> filtered_features;
00310     FilterFeaturesOnEdges(img, features, filtered_features, 2, 10);
00311     cvReleaseImage(&smoothed);
00312     
00313     features = filtered_features;
00314 
00315 #if defined(_DEBUG_WINDOWS)
00316     ShowFeatures(img, features);
00317 #endif
00318     int board_length = MAX(size.width, size.height);
00319     float weight_coeff = board_length*1.0f;
00320 
00321     const float max_square_size = 20.0;
00322 
00323     for(size_t i = 0; i < features.size(); i++)
00324     {
00325         vector<feature_t> neighbors;
00326         SelectNeighborFeatures(features, neighbors, features[i].pt, max_square_size*board_length*sqrt(2.0f));
00327 //        if(neighbors.size() < size.width*size.height) continue;
00328 //        printf("Neighbors number %d\n", neighbors.size());
00329         if(neighbors.size() < (size_t)(size.width - 1)*(size.height - 1))
00330         {
00331             // this is not a chessboard point
00332             continue;
00333         }
00334         
00335         if(abs(features[i].pt.x - 413) < 5 && abs(features[i].pt.y - 214) < 5)
00336         {
00337             int w = 1;
00338         }
00339 
00340         int idx1 = Find1NN(neighbors, features[i].pt, 1);
00341         assert(idx1 >= 0);
00342         cv::Point2f dir1_diag = neighbors[idx1].pt - features[i].pt;
00343 
00344         vector<int> exclude_points;
00345         exclude_points.push_back(idx1);
00346         int idx1m = Find1NN(neighbors, features[i].pt - dir1_diag, 1);
00347         if(idx1m >= 0)
00348         {
00349             exclude_points.push_back(idx1m);
00350         }
00351         for(int k = 0; k < 3; k++)
00352         {
00353             int idx2 = Find1NNEx(neighbors, features[i].pt, exclude_points);
00354 
00355             //        int idx2 = Find2NNPerp(neighbors, features[i].pt, dir1_diag);
00356             if(idx2 < 0) continue;
00357             exclude_points.push_back(idx2);
00358             cv::Point2f dir2_diag = neighbors[idx2].pt - features[i].pt;
00359 
00360             // we have found diagonal directions, now let's convert them to board axes
00361             cv::Point2f dir1 = dir1_diag + dir2_diag;
00362             cv::Point2f dir2 = dir1_diag - dir2_diag;
00363 
00364             if(length(dir1) < 1.0f || length(dir2) < 1.0f) continue;
00365 
00366             int border1plus = -1, border1minus = -1, border2plus = -1, border2minus = -1;
00367             int count1plus = CountPoints(neighbors, features[i].pt, dir1, 1, &border1plus);
00368             int count1minus = CountPoints(neighbors, features[i].pt, dir1, -1, &border1minus);
00369             int count2plus = CountPoints(neighbors, features[i].pt, dir2, 1, &border2plus);
00370             int count2minus = CountPoints(neighbors, features[i].pt, dir2, -1, &border2minus);
00371             //        printf("%d,%d,%d,%d\n", border1plus, border1minus, border2plus, border2minus);
00372             int count1 = count1plus + count1minus + 1;
00373             int count2 = count2plus + count2minus + 1;
00374 
00375             int count_corner1 = 2*count1;
00376             // test the borders
00377             cv::Point2f point1plus = features[i].pt + dir1*float(count1plus);
00378             if(IsBorderPoint(neighbors, point1plus, dir1, dir2))
00379             {
00380                 count_corner1--;
00381             }
00382             cv::Point2f point1minus = features[i].pt - dir1*float(count1minus);
00383             if(IsBorderPoint(neighbors, point1minus, -dir1, dir2))
00384             {
00385                 count_corner1--;
00386             }
00387 
00388             int count_corner2 = 2*count2;
00389             cv::Point2f point2plus = features[i].pt + dir2*float(count2plus);
00390             if(IsBorderPoint(neighbors, point2plus, dir2, dir1))
00391             {
00392                 count_corner2--;
00393             }
00394             cv::Point2f point2minus = features[i].pt - dir2*float(count2minus);
00395             if(IsBorderPoint(neighbors, point2minus, -dir2, dir1))
00396             {
00397                 count_corner2--;
00398             }
00399 
00400 
00401             if(border1plus >= 0 && border1minus >= 0)
00402             {
00403                 dir1 = (neighbors[border1plus].pt - neighbors[border1minus].pt)*(1.0f/(count1 - 1));
00404             }
00405             if(border2plus >= 0 && border2minus >= 0)
00406             {
00407                 dir2 = (neighbors[border2plus].pt - neighbors[border2minus].pt)*(1.0f/(count2 - 1));
00408             }
00409             if(count_corner1 == size.height && count_corner2 == size.width)
00410             {
00411                 count_corner1 = size.width;
00412                 count_corner2 = size.height;
00413                 cv::Point2f _dir = dir1;
00414                 dir1 = dir2;
00415                 dir2 = _dir;
00416             }
00417             else if(count_corner1 != size.width || count_corner2 != size.height)
00418             {
00419                 continue;
00420             }
00421 
00422             if(dir1.x < 0) dir1 = -dir1;
00423             if(dir2.y < 0) dir2 = -dir2;
00424             float min_dist = 0.3*MAX(norm(dir1), norm(dir2));
00425 
00426             //printf("dir1 = %f,%f, dir2 = %f,%f\n", dir1.x, dir1.y, dir2.x, dir2.y);
00427 
00428             // find the corners
00429             vector<chessboard_feature_t> corner_points;
00430             for(size_t j1 = 0; j1 < neighbors.size(); j1++)
00431             {
00432                 cv::Point2f p = neighbors[j1].pt;
00433 
00434                 for(int sign2 = -1; sign2 <= 1; sign2 += 2)
00435                 {
00436                     for(int sign1 = -1; sign1 <= 1; sign1 += 2)
00437                     {
00438                         cv::Point2f pnn = p + (dir1*float(sign1) + dir2*float(sign2))*0.5f;
00439                         int idx = Find1NN(neighbors, pnn);
00440                         cv::Point2f offset = neighbors[idx].pt - pnn;
00441                         if(norm(offset) < min_dist)
00442                         {
00443                             chessboard_feature_t corner_point;
00444                             corner_point.pt = (p + pnn)*0.5f;
00445                             if(corner_points.size() == 0)
00446                             {
00447                                 corner_point.angle = 0;
00448                             }
00449                             else
00450                             {
00451                                 corner_point.angle = calc_corner_weight(corner_point.pt, corner_points[0].pt,
00452                                                                         dir1, dir2, weight_coeff);
00453                             }
00454                             // check if this corner is already present
00455                             int corner_idx = Find1NN(corner_points, corner_point.pt);
00456                             if(corner_idx >= 0)
00457                             {
00458                                 cv::Point2f offset = corner_point.pt - corner_points[corner_idx].pt;
00459                                 if(norm(offset) < min_dist)
00460                                 {
00461                                     continue;
00462                                 }
00463                             }
00464 
00465                             corner_point.idx1 = j1;
00466                             corner_point.idx2 = idx;
00467                             corner_points.push_back(corner_point);
00468                             //                        printf("Added point %f,%f, weight %f, sprod1 = %f, sprod2 = %f\n",
00469                             //                               corner_point.pt.x*2, corner_point.pt.y*2, corner_point.angle,
00470                             //                                sprod1, sprod2);
00471                         }
00472                     }
00473                 }
00474             }
00475 
00476 #if defined(_DEBUG_WINDOWS)
00477             IplImage* test = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
00478             cvCvtColor(img, test, CV_GRAY2BGR);
00479 
00480             for(size_t i = 0; i < corner_points.size(); i++)
00481             {
00482                 cvCircle(test, corner_points[i].pt, 3, cvScalar(255, 0, 0));
00483             }
00484             cvNamedWindow("1", 1);
00485             cvShowImage("1", test);
00486             cvWaitKey(0);
00487             
00488             cvSaveImage("test.png", test);
00489 
00490             cvReleaseImage(&test);
00491 #endif //_DEBUG_WINDOWS
00492 
00493             FilterOutliers(corner_points, dir1*0.5f, dir2*0.5f, min_dist);
00494 
00495 #if defined(_DEBUG_WINDOWS)
00496             test = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 3);
00497             cvCvtColor(img, test, CV_GRAY2BGR);
00498 
00499             for(size_t i = 0; i < corner_points.size(); i++)
00500             {
00501                 cvCircle(test, corner_points[i].pt, 3, cvScalar(0, 255, 0));
00502             }
00503             cvNamedWindow("1", 1);
00504             cvShowImage("1", test);
00505             cvWaitKey(0);
00506 
00507             cvReleaseImage(&test);
00508 #endif //_DEBUG_WINDOWS
00509 
00510 
00511             if(corner_points.size() != size.width*size.height)
00512             {
00513                 continue;
00514             }
00515 
00516             sort(corner_points.begin(), corner_points.end(), helper_corner_less);
00517 
00518 #if 1
00519             vector<chessboard_feature_t>::const_iterator it_origin;
00520             updateSpanVector(corner_points.begin(), corner_points.begin() + 4, it_origin, dir1);
00521             int origin_idx = it_origin - corner_points.begin();
00522 
00523             // now recalculate the weights and sort again
00524 
00525             //        dir1 = (corner_points[size.width - 1].pt - corner_points[0].pt);
00526             //        dir2 = (corner_points[(size.height - 1)*size.width].pt - corner_points[0].pt);
00527             dir1 = dir1*(1.0f/(size.width - 1));
00528             //        dir2 = dir2*(1.0f/(size.height - 1));
00529             dir2 = dir2*0.5f;
00530 //            if(dir1.y < 0) dir1 = -dir1;
00531 //            if(dir2.x > 0) dir2 = -dir2;
00532 
00533             if(size.height % 2 == 0)
00534             {
00535                 if(dir1.x < 0) dir1 = -dir1;
00536                 //if(dir2.y < 0) dir2 = -dir2;
00537                 if(dir1.x*dir2.y - dir1.y*dir2.x < 0) dir2 = -dir2;
00538             }
00539             else
00540             {
00541                 cv::Point2f black_diag = neighbors[corner_points[0].idx1].pt -
00542                     neighbors[corner_points[0].idx2].pt;
00543                 if(black_diag.dot(dir1) < 0) black_diag = -black_diag;
00544                 if(black_diag.dot(dir2) < 0) dir2 = -dir2;
00545                 if(dir1.x*dir2.y - dir1.y*dir2.x < 0) dir1 = -dir1;
00546 //                printf("oirgin = %f,%f, black_diag = %f,%f, dir1 = %f,%f, dir2 = %f,%f\n",
00547 //                    corner_points[0].pt.x, corner_points[0].pt.y, black_diag.x, black_diag.y,
00548 //                    dir1.x, dir1.y, dir2.x, dir2.y);
00549             }
00550 
00551 
00552             corner_points[origin_idx].angle = 0.0f;
00553             for(size_t j1 = 0; j1 < corner_points.size(); j1++)
00554             {
00555                 if(j1 == origin_idx) continue;
00556                 corner_points[j1].angle = calc_corner_weight(corner_points[j1].pt,
00557                                                              corner_points[origin_idx].pt, dir1, dir2, weight_coeff);
00558             }
00559 
00560             sort(corner_points.begin(), corner_points.end(), helper_corner_less);
00561 
00562             // now reorder inside each line
00563             int valid_flag = 1;
00564             cv::Point2f origin = it_origin->pt;
00565             for(int jh = 0; jh < size.height; jh++)
00566             {
00567                 float offset = sortSpannedFeatures(corner_points.begin() + size.width*jh,
00568                                     corner_points.begin() + size.width*(jh + 1), origin, dir1);
00569                 if(offset > min_dist)
00570                 {
00571                     valid_flag = 0;
00572                     break;
00573                 }
00574 
00575                 // looking for the next line
00576                 cv::Point2f new_origin = origin + dir2;
00577                 int idx = Find1NN(corner_points, new_origin);
00578                 if(length(new_origin - corner_points[idx].pt) > min_dist && jh < size.height - 1)
00579                 {
00580                     valid_flag = 0;
00581                     break;
00582                 }
00583 
00584                 // found the new line
00585                 origin = corner_points[idx].pt;
00586             }
00587 
00588             if(!valid_flag)
00589             {
00590                 //printf("invalid\n");
00591                 continue;
00592             }
00593 
00594             // test the new origin for ordering
00595             if(size.height % 2 != 0)
00596             {
00597                 cv::Point2f black_diag = neighbors[corner_points[0].idx1].pt -
00598                     neighbors[corner_points[0].idx2].pt;
00599                 if(black_diag.dot(dir1) < 0) black_diag = -black_diag;
00600                 assert(dir1.x*dir2.y - dir1.y*dir2.x > 0);
00601                 if(black_diag.dot(dir2) < 0)
00602                 {
00603                     continue; // this is not right!
00604                 }
00605 
00606             }
00607 #endif
00608 
00609             for(int jh = 0; jh < size.height; jh++)
00610             {
00611                 for(int jw = 0; jw < size.width; jw++)
00612                 {
00613                     corners[jh*size.width + jw] = corner_points[jh*size.width + jw].pt;
00614                 }
00615             }
00616 
00617             if(corner_count) *corner_count = size.width*size.height;
00618             //printf("dir1 = %f,%f, dir2 = %f,%f\n", dir1.x, dir1.y, dir2.x, dir2.y);
00619             //        printf("Neighbors number: %d\n", neighbors.size());
00620 
00621             return 1;
00622         }
00623     }
00624 
00625     if(corner_count) *corner_count = 0;
00626     return 0;
00627 }
00628 


checkerboard_pose_estimation
Author(s): Patrick Mihelich
autogenerated on Thu Aug 27 2015 14:30:00