17 #include <mrpt/otherlibs/do_opencv_includes.h> 35 std::vector<std::vector<CvPoint2D32f>>& out_corners)
46 const size_t expected_quads_count =
47 ((pattern_size.width + 1) * (pattern_size.height + 1) + 1) / 2;
55 vector<CvCBQuad::Ptr> quads;
56 vector<CvCBCorner::Ptr> corners;
57 list<vector<CvCBQuad::Ptr>>
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" 73 IplConvKernel* kernel_cross =
74 cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_CROSS,
nullptr);
75 IplConvKernel* kernel_rect =
76 cvCreateStructuringElementEx(3, 3, 1, 1, CV_SHAPE_RECT,
nullptr);
78 static int kernel_diag1_vals[9] = {1, 0, 0, 0, 1, 0, 0, 0, 1};
79 IplConvKernel* kernel_diag1 = cvCreateStructuringElementEx(
80 3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_diag1_vals);
81 static int kernel_diag2_vals[9] = {0, 0, 1, 0, 1, 0, 1, 0, 0};
82 IplConvKernel* kernel_diag2 = cvCreateStructuringElementEx(
83 3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_diag2_vals);
84 static int kernel_horz_vals[9] = {0, 0, 0, 1, 1, 1, 0, 0, 0};
85 IplConvKernel* kernel_horz = cvCreateStructuringElementEx(
86 3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_horz_vals);
87 static int kernel_vert_vals[9] = {0, 1, 0, 0, 1, 0, 0, 1, 0};
88 IplConvKernel* kernel_vert = cvCreateStructuringElementEx(
89 3, 3, 1, 1, CV_SHAPE_CUSTOM, kernel_vert_vals);
95 int block_size = cvRound(
MIN(
img.getWidth(),
img.getHeight()) * 0.2) | 1;
98 img.getAs<IplImage>(), thresh_img.getAs<IplImage>(), 255,
99 CV_ADAPTIVE_THRESH_GAUSSIAN_C, CV_THRESH_BINARY, block_size, 0);
101 cvCopy(thresh_img.getAs<IplImage>(), thresh_img_save.getAs<IplImage>());
112 bool last_dilation =
false;
114 for (
int dilations = 0; !last_dilation; dilations++)
118 cvCopy(thresh_img_save.getAs<IplImage>(), thresh_img.getAs<IplImage>());
122 thresh_img, dilations, kernel_cross, kernel_rect, kernel_diag1,
123 kernel_diag2, kernel_horz, kernel_vert);
130 thresh_img.getAs<IplImage>(), cvPoint(0, 0),
131 cvPoint(thresh_img.getWidth() - 1, thresh_img.getHeight() - 1),
132 CV_RGB(255, 255, 255), 3, 8);
137 quads, corners, thresh_img, flags, dilations,
true);
138 if (quad_count <= 0)
continue;
150 quad_centers.resize(quads.size());
151 for (
size_t i = 0; i < quads.size(); i++)
155 0.25 * (
q->corners[0]->pt.x +
q->corners[1]->pt.x +
156 q->corners[2]->pt.x +
q->corners[3]->pt.x);
158 0.25 * (
q->corners[0]->pt.y +
q->corners[1]->pt.y +
159 q->corners[2]->pt.y +
q->corners[3]->pt.y);
163 static const size_t MAX_NUM_CLUSTERS = 4;
164 for (
size_t nClusters = 1; nClusters < MAX_NUM_CLUSTERS; nClusters++)
166 vector<size_t> num_quads_by_cluster(nClusters);
168 vector<int> assignments;
170 vector<CArrayDouble<2>,
172 vector<CArrayDouble<2>,
174 nClusters, quad_centers, assignments);
177 for (
size_t i = 0; i < nClusters; i++)
178 num_quads_by_cluster[i] =
179 std::count(assignments.begin(), assignments.end(), i);
186 "All quads (%u) | %u clusters",
187 (
unsigned)quad_centers.size(), (unsigned)nClusters));
190 for (
size_t i = 0; i < quad_centers.size(); i++)
192 static const TColor colors[4] = {
196 quad_centers[i][0], quad_centers[i][1],
197 colors[assignments[i] % 4],
'+', 10);
206 for (
size_t i = 0; i < nClusters; i++)
208 if (num_quads_by_cluster[i] <
209 size_t(pattern_size.height * pattern_size.width))
213 vector<CvCBQuad::Ptr> ith_quads;
214 for (
size_t q = 0;
q < quads.size();
q++)
215 if (
size_t(assignments[
q]) == i)
216 ith_quads.push_back(quads[
q]);
233 for (
int group_idx = 0;; group_idx++)
235 vector<CvCBQuad::Ptr> quad_group;
238 ith_quads, quad_group, group_idx, dilations);
239 if (quad_group.empty())
break;
242 size_t count = quad_group.size();
244 if (
count == expected_quads_count)
251 "Candidate group #%i (%i)", (
int)group_idx,
252 (
int)quad_group.size()));
255 for (
size_t i = 0; i < quad_group.size(); i++)
257 static const TColor colors[4] = {
261 0.25 * (quad_group[i]->corners[0]->pt.x +
262 quad_group[i]->corners[1]->pt.x +
263 quad_group[i]->corners[2]->pt.x +
264 quad_group[i]->corners[3]->pt.x);
266 0.25 * (quad_group[i]->corners[0]->pt.y +
267 quad_group[i]->corners[1]->pt.y +
268 quad_group[i]->corners[2]->pt.y +
269 quad_group[i]->corners[3]->pt.y);
270 im.
cross(
x,
y, colors[group_idx % 4],
'+', 10);
284 good_quad_groups.push_back(quad_group);
303 good_quad_groups.begin();
304 it != good_quad_groups.end(); ++it)
308 for (
size_t i = 0; i < it->size(); i++)
312 (*it)[i]->corners[0]->pt.x +
313 (*it)[i]->corners[1]->pt.x + (*it)[i]->corners[2]->pt.x +
314 (*it)[i]->corners[3]->pt.x,
315 (*it)[i]->corners[0]->pt.y +
316 (*it)[i]->corners[1]->pt.y + (*it)[i]->corners[2]->pt.y +
317 (*it)[i]->corners[3]->pt.y);
322 double min_dist = std::numeric_limits<double>::max();
323 for (
size_t b = 0;
b < out_boards_centers.size();
b++)
328 if (out_corners.empty() || min_dist > 80)
330 vector<CvPoint2D32f> pts;
335 out_corners.push_back(pts);
337 out_boards_centers.push_back(boardCenter);
343 cvReleaseStructuringElement(&kernel_cross);
344 cvReleaseStructuringElement(&kernel_rect);
345 cvReleaseStructuringElement(&kernel_diag1);
346 cvReleaseStructuringElement(&kernel_diag2);
347 cvReleaseStructuringElement(&kernel_horz);
348 cvReleaseStructuringElement(&kernel_vert);
350 return !out_corners.empty();
353 #endif // MRPT_HAS_OPENCV void mrFindQuadNeighbors2(std::vector< CvCBQuad::Ptr > &quads, int dilation)
GLuint GLuint GLsizei count
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.
int waitForKey(bool ignoreControlKeys=true, mrptKeyModifier *out_pushModifier=nullptr)
Waits for any key to be pushed on the image or the console, and returns the key code.
void mrLabelQuadGroup(std::vector< CvCBQuad::Ptr > &quad_group, const CvSize &pattern_size, bool firstRun)
GLdouble GLdouble GLdouble GLdouble q
void icvCleanFoundConnectedQuads(std::vector< CvCBQuad::Ptr > &quad_group, const CvSize &pattern_size)
const Scalar * const_iterator
void setWindowTitle(const std::string &str) override
Changes the window title text.
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...
int myQuads2Points(const std::vector< CvCBQuad::Ptr > &output_quads, const CvSize &pattern_size, std::vector< CvPoint2D32f > &out_corners)
double kmeanspp(const size_t k, const LIST_OF_VECTORS1 &points, std::vector< int > &assignments, LIST_OF_VECTORS2 *out_centers=nullptr, const size_t attempts=3)
k-means++ algorithm to cluster a list of N points of arbitrary dimensionality into exactly K clusters...
std::string 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.
int icvGenerateQuads(vector< CvCBQuad::Ptr > &out_quads, vector< CvCBCorner::Ptr > &out_corners, const mrpt::utils::CImage &image, int flags, int dilation, bool firstRun)
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 icvFindConnectedQuads(std::vector< CvCBQuad::Ptr > &quad, std::vector< CvCBQuad::Ptr > &out_group, const int group_idx, const int dilation)
void colorImage(CImage &ret) const
Returns a RGB version of the grayscale image, or itself if it is already a RGB image.
void quadListMakeUnique(std::vector< CvCBQuad::Ptr > &quads)
double distance(const TPoint2D &p1, const TPoint2D &p2)
Gets the distance between two points in a 2D space.
bool find_chessboard_corners_multiple(const mrpt::utils::CImage &img_, CvSize pattern_size, std::vector< std::vector< CvPoint2D32f >> &out_corners)