Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpDot2_search.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 by Inria. All rights reserved.
4 *
5 * This software is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * See the file LICENSE.txt at the root directory of this source
10 * distribution for additional information about the GNU GPL.
11 *
12 * For using ViSP with software that can not be combined with the GNU
13 * GPL, please contact Inria about acquiring a ViSP Professional
14 * Edition License.
15 *
16 * See https://visp.inria.fr for more information.
17 *
18 * This software was developed at:
19 * Inria Rennes - Bretagne Atlantique
20 * Campus Universitaire de Beaulieu
21 * 35042 Rennes Cedex
22 * France
23 *
24 * If you have questions regarding the use of this file, please contact
25 * Inria at visp@inria.fr
26 *
27 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
28 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
29 *
30 * Description:
31 * Search a dot in an area.
32 */
33
34#include <visp3/core/vpConfig.h>
35#include <visp3/core/vpDisplay.h>
36#include <visp3/blob/vpDot2.h>
37
39
45 void vpDot2::searchDotsAreaGoodGerm(vpSearchDotsInAreaGoodGermData &data)
46{
47// Compute the right border position for this possible germ
48 unsigned int border_u;
49 unsigned int border_v;
50 bool good_germ = true;
51 std::list<vpDot2>::iterator itbad;
52 std::list<vpDot2>::iterator itnice;
53 vpDot2 *dotToTest = nullptr;
54 vpDot2 tmpDot;
55 vpImagePoint cogTmpDot;
56 if (findFirstBorder(data.m_I, data.m_u, data.m_v, border_u, border_v) == false) {
57 // germ is not good.
58 // Jump all the pixels between v,u and v,
59 // dotToTest->getFirstBorder_u()
60 data.m_u = border_u;
61 data.m_v = border_v;
62 }
63 else {
64 itbad = data.m_badDotsVector.begin();
65 vpImagePoint cogBadDot;
66
67 while ((itbad != data.m_badDotsVector.end()) && (good_germ == true)) {
68 if ((static_cast<double>(data.m_u) >= (*itbad).m_bbox_u_min) && (static_cast<double>(data.m_u) <= (*itbad).m_bbox_u_max) &&
69 (static_cast<double>(data.m_v) >= (*itbad).m_bbox_v_min) && (static_cast<double>(data.m_v) <= (*itbad).m_bbox_v_max)) {
70 std::list<vpImagePoint>::const_iterator it_edges = m_ip_edges_list.begin();
71 while ((it_edges != m_ip_edges_list.end()) && (good_germ == true)) {
72 // Test if the germ belong to a previously detected dot:
73 // - from the germ go right to the border and compare this
74 // position to the list of pixels of previously detected dots
75 cogBadDot = *it_edges;
76 if ((std::fabs(border_u - cogBadDot.get_u()) <=
77 (vpMath::maximum(std::fabs(static_cast<double>(border_u)), std::fabs(cogBadDot.get_u())) *
78 std::numeric_limits<double>::epsilon())) &&
79 (std::fabs(data.m_v - cogBadDot.get_v()) <=
80 (vpMath::maximum(std::fabs(static_cast<double>(data.m_v)), std::fabs(cogBadDot.get_v())) *
81 std::numeric_limits<double>::epsilon()))) {
82 good_germ = false;
83 }
84 ++it_edges;
85 }
86 }
87 ++itbad;
88 }
89
90 if (!good_germ) {
91 // Jump all the pixels between v,u and v,
92 // dotToTest->getFirstBorder_u()
93 data.m_u = border_u;
94 data.m_v = border_v;
95 }
96 else {
97 vpImagePoint germ;
98 germ.set_u(data.m_u);
99 germ.set_v(data.m_v);
100
101 // otherwise estimate the width, height and surface of the dot we
102 // created, and test it.
103 if (dotToTest != nullptr) {
104 delete dotToTest;
105 }
106 dotToTest = getInstance();
107 dotToTest->setCog(germ);
108 dotToTest->setGrayLevelMin(getGrayLevelMin());
109 dotToTest->setGrayLevelMax(getGrayLevelMax());
112 dotToTest->setGraphics(m_graphics);
113 dotToTest->setGraphicsThickness(m_thickness);
114 dotToTest->setComputeMoments(true);
115 dotToTest->setArea(m_area);
116 dotToTest->setEllipsoidShapePrecision(m_ellipsoidShapePrecision);
117 dotToTest->setEllipsoidBadPointsPercentage(m_allowedBadPointsPercentage);
118
119 // first compute the parameters of the dot.
120 // if for some reasons this caused an error tracking
121 // (dot partially out of the image...), check the next intersection
122 if (dotToTest->computeParameters(data.m_I) == false) {
123 // Jump all the pixels between v,u and v,
124 // dotToTest->getFirstBorder_u()
125 data.m_u = border_u;
126 data.m_v = border_v;
127 }
128 else {
129 // if the dot to test is valid,
130 if (dotToTest->isValid(data.m_I, *this)) {
131 vpImagePoint cogDotToTest = dotToTest->getCog();
132 // Compute the distance to the center. The center used here is not the
133 // area center available by area.getCenter(area_center_u,
134 // area_center_v) but the center of the input area which may be
135 // partially outside the image.
136
137 double area_center_u = (data.m_area.getLeft() + (data.m_area.getWidth() / 2.0)) - 0.5;
138 double area_center_v = (data.m_area.getTop() + (data.m_area.getHeight() / 2.0)) - 0.5;
139
140 double thisDiff_u = cogDotToTest.get_u() - area_center_u;
141 double thisDiff_v = cogDotToTest.get_v() - area_center_v;
142 double thisDist = sqrt((thisDiff_u * thisDiff_u) + (thisDiff_v * thisDiff_v));
143
144 bool stopLoop = false;
145 itnice = data.m_niceDots.begin();
146
147 while ((itnice != data.m_niceDots.end()) && (stopLoop == false)) {
148 tmpDot = *itnice;
149
150 // --comment: epsilon equals 0.001 -- detecte +sieurs points
151 double epsilon = 3.0;
152 // if the center of the dot is the same than the current
153 // don't add it, test the next point of the grid
154 cogTmpDot = tmpDot.getCog();
155
156 if ((fabs(cogTmpDot.get_u() - cogDotToTest.get_u()) < epsilon) &&
157 (fabs(cogTmpDot.get_v() - cogDotToTest.get_v()) < epsilon)) {
158 stopLoop = true;
159 // Jump all the pixels between v,u and v,
160 // tmpDot->getFirstBorder_u()
161 data.m_u = border_u;
162 data.m_v = border_v;
163 }
164 else {
165 double otherDiff_u = cogTmpDot.get_u() - area_center_u;
166 double otherDiff_v = cogTmpDot.get_v() - area_center_v;
167 double otherDist = sqrt((otherDiff_u * otherDiff_u) + (otherDiff_v * otherDiff_v));
168
169 // if the distance of the curent vector element to the center
170 // is greater than the distance of this dot to the center,
171 // then add this dot before the current vector element.
172 if (otherDist > thisDist) {
173 data.m_niceDots.insert(itnice, *dotToTest);
174 stopLoop = true;
175 // Jump all the pixels between v,u and v,
176 // tmpDot->getFirstBorder_u()
177 data.m_u = border_u;
178 data.m_v = border_v;
179 }
180 ++itnice;
181 }
182 }
183
184 // if we reached the end of the vector without finding the dot
185 // or inserting it, insert it now.
186 if ((itnice == data.m_niceDots.end()) && (stopLoop == false)) {
187 data.m_niceDots.push_back(*dotToTest);
188 }
189 }
190 else {
191 // Store bad dots
192 data.m_badDotsVector.push_front(*dotToTest);
193 }
194 }
195 }
196 }
197 if (dotToTest != nullptr) {
198 delete dotToTest;
199 }
200}
201
224void vpDot2::searchDotsInArea(const vpImage<unsigned char> &I, int area_u, int area_v, unsigned int area_w,
225 unsigned int area_h, std::list<vpDot2> &niceDots)
226
227{
228 // clear the list of nice dots
229 niceDots.clear();
230
231 // Fit the input area in the image; we keep only the common part between
232 // this area and the image.
233 setArea(I, area_u, area_v, area_w, area_h);
234
235 // compute the size of the search grid
236 unsigned int gridWidth;
237 unsigned int gridHeight;
238 getGridSize(gridWidth, gridHeight);
239
240 if (m_graphics) {
241 // Display the area were the dot is search
242 vpDisplay::displayRectangle(I, m_area, vpColor::blue, false, m_thickness);
243 }
244
245#ifdef DEBUG
248#endif
249 // start the search loop; for all points of the search grid,
250 // test if the pixel belongs to a valid dot.
251 // if it is so eventually add it to the vector of valid dots.
252 std::list<vpDot2> badDotsVector;
253 std::list<vpDot2>::iterator itnice;
254
255 vpDot2 tmpDot;
256
257 unsigned int area_u_min = static_cast<unsigned int>(m_area.getLeft());
258 unsigned int area_u_max = static_cast<unsigned int>(m_area.getRight());
259 unsigned int area_v_min = static_cast<unsigned int>(m_area.getTop());
260 unsigned int area_v_max = static_cast<unsigned int>(m_area.getBottom());
261
262 unsigned int u, v;
263 vpImagePoint cogTmpDot;
264
265 v = area_v_min;
266 while (v < area_v_max) {
267 u = area_u_min;
268 while (u < area_u_max) {
269 // if the pixel we're in doesn't have the right color (outside the
270 // graylevel interval), no need to check further, just get to the
271 // next grid intersection.
272 if (hasGoodLevel(I, u, v)) {
273
274 // Test if an other germ is inside the bounding box of a dot previously
275 // detected
276 bool good_germ = true;
277
278 itnice = niceDots.begin();
279 while ((itnice != niceDots.end()) && (good_germ == true)) {
280 tmpDot = *itnice;
281
282 cogTmpDot = tmpDot.getCog();
283 double u0 = cogTmpDot.get_u();
284 double v0 = cogTmpDot.get_v();
285 double half_w = tmpDot.getWidth() / 2.;
286 double half_h = tmpDot.getHeight() / 2.;
287
288 if ((u >= (u0 - half_w)) && (u <= (u0 + half_w)) && (v >= (v0 - half_h)) && (v <= (v0 + half_h))) {
289 // Germ is in a previously detected dot
290 good_germ = false;
291 }
292 ++itnice;
293 }
294
295 if (good_germ) {
296 vpRect area(area_u, area_v, area_w, area_h);
297 vpSearchDotsInAreaGoodGermData data(I, area, u, v, niceDots, badDotsVector);
298 searchDotsAreaGoodGerm(data);
299 }
300 }
301 u = u + gridWidth;
302 }
303 v = v + gridHeight;
304 }
305}
306
307END_VISP_NAMESPACE
static const vpColor blue
Definition vpColor.h:204
static void flush(const vpImage< unsigned char > &I)
static void displayRectangle(const vpImage< unsigned char > &I, const vpImagePoint &topLeft, unsigned int width, unsigned int height, const vpColor &color, bool fill=false, unsigned int thickness=1)
unsigned int getGrayLevelMin() const
Definition vpDot2.h:221
vpDot2()
Definition vpDot2.cpp:109
unsigned int getGrayLevelMax() const
Definition vpDot2.h:227
void setGraphics(bool activate)
Definition vpDot2.h:320
void setGraphicsThickness(unsigned int thickness)
Definition vpDot2.h:328
void searchDotsInArea(const vpImage< unsigned char > &I, int area_u, int area_v, unsigned int area_w, unsigned int area_h, std::list< vpDot2 > &niceDots)
void setGrayLevelMax(const unsigned int &max)
Definition vpDot2.h:359
void setSizePrecision(const double &sizePrecision)
Definition vpDot2.cpp:745
void setGrayLevelPrecision(const double &grayLevelPrecision)
Definition vpDot2.cpp:715
void setGrayLevelMin(const unsigned int &min)
Definition vpDot2.h:340
void setCog(const vpImagePoint &ip)
Definition vpDot2.h:263
vpImagePoint getCog() const
Definition vpDot2.h:183
double getSizePrecision() const
Definition vpDot2.cpp:631
double getGrayLevelPrecision() const
Definition vpDot2.cpp:624
void setEllipsoidBadPointsPercentage(const double &percentage=0.0)
Definition vpDot2.h:292
double getWidth() const
Definition vpDot2.cpp:603
void setEllipsoidShapePrecision(const double &ellipsoidShapePrecision)
Definition vpDot2.cpp:790
void setArea(const double &area)
Definition vpDot2.cpp:696
void setComputeMoments(bool activate)
Definition vpDot2.h:278
double getHeight() const
Definition vpDot2.cpp:610
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
double get_u() const
void set_u(double u)
void set_v(double v)
double get_v() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
static Type maximum(const Type &a, const Type &b)
Definition vpMath.h:257
Defines a rectangle in the plane.
Definition vpRect.h:79