17 #include <mrpt/otherlibs/do_opencv_includes.h> 38 std::vector< std::vector<CvPoint2D32f> > &out_corners)
48 const size_t expected_quads_count = ((pattern_size.width + 1)*(pattern_size.height + 1) + 1)/2;
56 vector<CvCBQuadPtr> quads;
57 vector<CvCBCornerPtr> corners;
58 list< vector<CvCBQuadPtr> > good_quad_groups;
60 if( pattern_size.width < 2 || pattern_size.height < 2 )
62 std::cerr <<
"Pattern should have at least 2x2 size" << endl;
65 if( pattern_size.width > 127 || pattern_size.height > 127 )
67 std::cerr <<
"Pattern should not have a size larger than 127 x 127" << endl;
72 IplConvKernel *kernel_cross = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CROSS,NULL);
73 IplConvKernel *kernel_rect = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_RECT,NULL);
75 static int kernel_diag1_vals[9] = {
79 IplConvKernel *kernel_diag1 = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_diag1_vals);
80 static int kernel_diag2_vals[9] = {
84 IplConvKernel *kernel_diag2 = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_diag2_vals);
85 static int kernel_horz_vals[9] = {
89 IplConvKernel *kernel_horz = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_horz_vals);
90 static int kernel_vert_vals[9] = {
94 IplConvKernel *kernel_vert = cvCreateStructuringElementEx(3,3,1,1,CV_SHAPE_CUSTOM,kernel_vert_vals);
99 int block_size = cvRound(
MIN(
img.getWidth(),
img.getHeight())*0.2)|1;
101 cvAdaptiveThreshold(
img.getAs<IplImage>(), thresh_img.getAs<IplImage>(), 255, CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, block_size, 0 );
103 cvCopy( thresh_img.getAs<IplImage>(), thresh_img_save.getAs<IplImage>());
113 bool last_dilation =
false;
115 for(
int dilations = 0; !last_dilation; dilations++ )
118 cvCopy( thresh_img_save.getAs<IplImage>(), thresh_img.getAs<IplImage>() );
121 last_dilation =
do_special_dilation(thresh_img, dilations,kernel_cross,kernel_rect,kernel_diag1,kernel_diag2, kernel_horz,kernel_vert);
127 cvRectangle( thresh_img.getAs<IplImage>(), cvPoint(0,0),
128 cvPoint(thresh_img.getWidth()-1,thresh_img.getHeight()-1),
129 CV_RGB(255,255,255), 3, 8);
133 int quad_count =
icvGenerateQuads( quads, corners, thresh_img, flags, dilations,
true );
134 if( quad_count <= 0 )
145 quad_centers.resize(quads.size());
146 for (
size_t i=0;i<quads.size();i++)
149 quad_centers[i][0] = 0.25 * (
q->corners[0]->pt.x +
q->corners[1]->pt.x +
q->corners[2]->pt.x +
q->corners[3]->pt.x);
150 quad_centers[i][1] = 0.25 * (
q->corners[0]->pt.y +
q->corners[1]->pt.y +
q->corners[2]->pt.y +
q->corners[3]->pt.y);
154 static const size_t MAX_NUM_CLUSTERS = 4;
155 for (
size_t nClusters=1;nClusters<MAX_NUM_CLUSTERS;nClusters++)
157 vector<size_t> num_quads_by_cluster(nClusters);
159 vector<int> assignments;
163 (nClusters,quad_centers,assignments);
166 for (
size_t i=0;i<nClusters;i++)
167 num_quads_by_cluster[i] =
std::count(assignments.begin(),assignments.end(), i);
173 (
unsigned)quad_centers.size(),
174 (unsigned)nClusters ));
177 for (
size_t i=0;i<quad_centers.size();i++)
179 static const TColor colors[4] = {
TColor(255,0,0),
TColor(0,0,255),
TColor(255,0,255),
TColor(0,255,0) };
180 im.
cross(quad_centers[i][0],quad_centers[i][1], colors[assignments[i]%4],
'+', 10);
190 for (
size_t i=0;i<nClusters;i++)
192 if (num_quads_by_cluster[i]<
size_t(pattern_size.height*pattern_size.width))
196 vector<CvCBQuadPtr> ith_quads;
197 for (
size_t q=0;
q<quads.size();
q++)
198 if (
size_t(assignments[
q])==i)
199 ith_quads.push_back(quads[
q]);
212 for(
int group_idx = 0; ; group_idx++ )
214 vector<CvCBQuadPtr> quad_group;
217 if( quad_group.empty() )
221 size_t count = quad_group.size();
223 if(
count == expected_quads_count )
231 for (
size_t i=0;i<quad_group.size();i++)
233 static const TColor colors[4] = {
TColor(255,0,0),
TColor(0,0,255),
TColor(255,0,255),
TColor(0,255,0) };
234 const double x=0.25*(quad_group[i]->corners[0]->pt.x+quad_group[i]->corners[1]->pt.x+quad_group[i]->corners[2]->pt.x+quad_group[i]->corners[3]->pt.x);
235 const double y=0.25*(quad_group[i]->corners[0]->pt.y+quad_group[i]->corners[1]->pt.y+quad_group[i]->corners[2]->pt.y+quad_group[i]->corners[3]->pt.y);
236 im.
cross(
x,
y, colors[group_idx%4],
'+', 10);
248 good_quad_groups.push_back(quad_group);
265 vector<TPoint2D> out_boards_centers;
266 for (list<vector<CvCBQuadPtr> >::
const_iterator it=good_quad_groups.begin();it!=good_quad_groups.end();++it)
270 for (
size_t i=0;i<it->size();i++)
273 (*it)[i]->corners[0]->pt.x+(*it)[i]->corners[1]->pt.x+(*it)[i]->corners[2]->pt.x+(*it)[i]->corners[3]->pt.x,
274 (*it)[i]->corners[0]->pt.y+(*it)[i]->corners[1]->pt.y+(*it)[i]->corners[2]->pt.y+(*it)[i]->corners[3]->pt.y );
278 double min_dist = std::numeric_limits<double>::max();
279 for (
size_t b=0;
b<out_boards_centers.size();
b++)
282 if (out_corners.empty() || min_dist > 80 )
284 vector<CvPoint2D32f> pts;
288 out_corners.push_back(pts);
290 out_boards_centers.push_back(boardCenter);
297 cvReleaseStructuringElement(&kernel_cross);
298 cvReleaseStructuringElement(&kernel_rect);
299 cvReleaseStructuringElement(&kernel_diag1);
300 cvReleaseStructuringElement(&kernel_diag2);
301 cvReleaseStructuringElement(&kernel_horz);
302 cvReleaseStructuringElement(&kernel_vert);
304 return !out_corners.empty();
308 #endif // MRPT_HAS_OPENCV int waitForKey(bool ignoreControlKeys=true, mrptKeyModifier *out_pushModifier=NULL)
Waits for any key to be pushed on the image or the console, and returns the key code.
GLuint GLuint GLsizei count
bool find_chessboard_corners_multiple(const mrpt::utils::CImage &img_, CvSize pattern_size, std::vector< std::vector< CvPoint2D32f > > &out_corners)
Classes for serialization, sockets, ini-file manipulation, streams, list of properties-values, timewatch, extensions to STL.
bool do_special_dilation(mrpt::utils::CImage &thresh_img, const int dilations, IplConvKernel *kernel_cross, IplConvKernel *kernel_rect, IplConvKernel *kernel_diag1, IplConvKernel *kernel_diag2, IplConvKernel *kernel_horz, IplConvKernel *kernel_vert)
A class for storing images as grayscale or RGB bitmaps.
void mrFindQuadNeighbors2(std::vector< CvCBQuadPtr > &quads, int dilation)
GLdouble GLdouble GLdouble GLdouble q
void icvCleanFoundConnectedQuads(std::vector< CvCBQuadPtr > &quad_group, const CvSize &pattern_size)
const Scalar * const_iterator
int myQuads2Points(const std::vector< CvCBQuadPtr > &output_quads, const CvSize &pattern_size, std::vector< CvPoint2D32f > &out_corners)
void icvFindConnectedQuads(std::vector< CvCBQuadPtr > &quad, std::vector< CvCBQuadPtr > &out_group, const int group_idx, const int dilation)
double kmeanspp(const size_t k, const LIST_OF_VECTORS1 &points, std::vector< int > &assignments, LIST_OF_VECTORS2 *out_centers=NULL, const size_t attempts=3)
k-means++ algorithm to cluster a list of N points of arbitrary dimensionality into exactly K clusters...
void mrLabelQuadGroup(std::vector< CvCBQuadPtr > &quad_group, const CvSize &pattern_size, bool firstRun)
This base provides a set of functions for maths stuff.
void cross(int x0, int y0, const mrpt::utils::TColor color, char type, unsigned int size=5, unsigned int width=1)
Draw a cross.
This class creates a window as a graphical user interface (GUI) for displaying images to the user...
std::string BASE_IMPEXP format(const char *fmt,...) MRPT_printf_format_check(1
A std::string version of C sprintf.
void showImage(const mrpt::utils::CImage &img)
Show a given color or grayscale image on the window.
This is the global namespace for all Mobile Robot Programming Toolkit (MRPT) libraries.
void keep_min(T &var, const K test_val)
If the second argument is below the first one, set the first argument to this lower value...
void setWindowTitle(const std::string &str) MRPT_OVERRIDE
Changes the window title text.
void quadListMakeUnique(std::vector< CvCBQuadPtr > &quads)
void colorImage(CImage &ret) const
Returns a RGB version of the grayscale image, or itself if it is already a RGB image.
int icvGenerateQuads(vector< CvCBQuadPtr > &out_quads, vector< CvCBCornerPtr > &out_corners, const mrpt::utils::CImage &image, int flags, int dilation, bool firstRun)
double BASE_IMPEXP distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.