40 #include <visp3/core/vpColVector.h>
41 #include <visp3/core/vpMath.h>
42 #include <visp3/me/vpMe.h>
46 #ifndef DOXYGEN_SHOULD_SKIP_THIS
70 template <
class Type>
inline void permute(Type &a, Type &b)
77 static vpDroite2Dt droiteCartesienne(vpPoint2Dt P, vpPoint2Dt Q)
83 PQ.c = (Q.y * P.x) - (Q.x * P.y);
88 static vpPoint2Dt pointIntersection(vpDroite2Dt D1, vpDroite2Dt D2)
93 det = ((D1.a * D2.b) - (D2.a * D1.b));
94 I.x = ((D2.c * D1.b) - (D1.c * D2.b)) / det;
95 I.y = ((D1.c * D2.a) - (D2.c * D1.a)) / det;
100 static void recale(vpPoint2Dt &P,
const vpBBoxt &bbox)
119 static void permute(vpPoint2Dt &A, vpPoint2Dt &B)
132 static bool clipping(vpPoint2Dt A, vpPoint2Dt B,
const vpBBoxt &bbox, vpPoint2Dt &Ac,
135 vpDroite2Dt AB, D[4];
136 const unsigned int index_0 = 0;
137 const unsigned int index_1 = 1;
138 const unsigned int index_2 = 2;
139 const unsigned int index_3 = 3;
140 const unsigned int val_1 = 1;
141 const unsigned int val_2 = 2;
142 const unsigned int val_4 = 4;
143 const unsigned int val_8 = 8;
147 D[index_0].c = -bbox.Xmin;
150 D[index_1].c = -bbox.Xmax;
153 D[index_2].c = -bbox.Ymin;
156 D[index_3].c = -bbox.Ymax;
158 const unsigned int nbP = val_2;
162 unsigned int code_P[nbP],
166 AB = droiteCartesienne(A, B);
172 for (n = 0; n < nbP; ++n) {
175 if (P[n].x < bbox.Xmin) {
179 if (P[n].x > bbox.Xmax) {
183 if (P[n].y < bbox.Ymin) {
187 if (P[n].y > bbox.Ymax) {
194 if ((code_P[0] | code_P[1]) == 0) {
205 if ((code_P[0] & code_P[1]) != 0)
214 if (code_P[0] != 0) {
218 while (!(code_P[0] & bit_i)) {
227 while (!(code_P[1] & bit_i)) {
233 P[n] = pointIntersection(AB, D[i]);
245 static double surfaceRelative(vpPoint2Dt P, vpPoint2Dt Q,
const vpBBoxt &bbox)
256 if ((std::fabs(P.x - bbox.Xmin) <=
257 (
vpMath::maximum(std::fabs(P.x), std::fabs(bbox.Xmin)) * std::numeric_limits<double>::epsilon())) &&
258 (std::fabs(Q.x - bbox.Xmax) <=
259 (
vpMath::maximum(std::fabs(Q.x), std::fabs(bbox.Xmax)) * std::numeric_limits<double>::epsilon()))) {
260 return fabs((bbox.Ymax + bbox.Ymin) - (P.y - Q.y));
264 if (((std::fabs(P.y - bbox.Ymin) <=
265 (
vpMath::maximum(std::fabs(P.y), std::fabs(bbox.Ymin)) * std::numeric_limits<double>::epsilon())) &&
266 (std::fabs(Q.y - bbox.Ymax) <=
267 (
vpMath::maximum(std::fabs(Q.y), std::fabs(bbox.Ymax)) * std::numeric_limits<double>::epsilon()))) ||
268 ((std::fabs(Q.y - bbox.Ymin) <=
269 (
vpMath::maximum(std::fabs(Q.y), std::fabs(bbox.Ymin)) * std::numeric_limits<double>::epsilon())) &&
270 (std::fabs(P.y - bbox.Ymax) <=
271 (
vpMath::maximum(std::fabs(P.y), std::fabs(bbox.Ymax)) * std::numeric_limits<double>::epsilon())))) {
272 return fabs((bbox.Xmax + bbox.Xmin) - (P.x - Q.x));
276 if ((std::fabs(P.x - bbox.Xmin) <=
277 (
vpMath::maximum(std::fabs(P.x), std::fabs(bbox.Xmin)) * std::numeric_limits<double>::epsilon())) &&
278 (std::fabs(Q.y - bbox.Ymax) <=
279 (
vpMath::maximum(std::fabs(Q.y), std::fabs(bbox.Ymax)) * std::numeric_limits<double>::epsilon()))) {
280 return (1 - ((bbox.Ymax - P.y) * (Q.x - bbox.Xmin)));
284 if ((std::fabs(P.x - bbox.Xmin) <=
285 (
vpMath::maximum(std::fabs(P.x), std::fabs(bbox.Xmin)) * std::numeric_limits<double>::epsilon())) &&
286 (std::fabs(Q.y - bbox.Ymin) <=
287 (
vpMath::maximum(std::fabs(Q.y), std::fabs(bbox.Ymin)) * std::numeric_limits<double>::epsilon()))) {
288 return (1 - ((P.y - bbox.Ymin) * (Q.x - bbox.Xmin)));
292 if ((std::fabs(P.y - bbox.Ymin) <=
293 (
vpMath::maximum(std::fabs(P.y), std::fabs(bbox.Ymin)) * std::numeric_limits<double>::epsilon())) &&
294 (std::fabs(Q.x - bbox.Xmax) <=
295 (
vpMath::maximum(std::fabs(Q.x), std::fabs(bbox.Xmax)) * std::numeric_limits<double>::epsilon()))) {
296 return (1 - ((bbox.Xmax - P.x) * (Q.y - bbox.Ymin)));
300 if ((std::fabs(P.y - bbox.Ymax) <=
301 (
vpMath::maximum(std::fabs(P.y), std::fabs(bbox.Ymax)) * std::numeric_limits<double>::epsilon())) &&
302 (std::fabs(Q.x - bbox.Xmax) <=
303 (
vpMath::maximum(std::fabs(Q.x), std::fabs(bbox.Xmax)) * std::numeric_limits<double>::epsilon()))) {
304 return (1 - ((bbox.Xmax - P.x) * (bbox.Ymax - Q.y)));
308 P.x, P.y, Q.x, Q.y, bbox.Xmin, bbox.Ymin, bbox.Xmax, bbox.Ymax));
316 double X, Y, moitie = (
static_cast<double>(n)) / 2.0;
317 vpPoint2Dt P1, Q1, P, Q;
322 double norm = 1.0 / (n * trunc(n / 2.0));
324 unsigned int nb_theta = angle.
getRows();
326 for (
unsigned int i_theta = 0; i_theta < nb_theta; ++i_theta) {
327 double theta = (M_PI / 180) * angle[i_theta];
329 double cos_theta = cos(theta);
330 double sin_theta = sin(theta);
335 const double thetaWhoseTanInfinite = 90.;
336 if (std::fabs(angle[i_theta] - thetaWhoseTanInfinite) <= (
vpMath::maximum(std::fabs(angle[i_theta]), thetaWhoseTanInfinite) *
337 std::numeric_limits<double>::epsilon()))
340 P1.y = -
static_cast<int>(n);
345 double tan_theta = sin_theta / cos_theta;
346 P1.x = -
static_cast<int>(n);
347 P1.y = tan_theta * (-
static_cast<int>(n));
349 Q1.y = tan_theta * n;
356 for (i = 0, Y = (-moitie + 0.5); i < n; ++i, ++Y) {
357 for (j = 0, X = (-moitie + 0.5); j < n; ++j, ++X) {
359 int sgn =
vpMath::sign((cos_theta * Y) - (sin_theta * X));
367 if (clipping(P1, Q1, bbox, P, Q)) {
369 v = surfaceRelative(P, Q, bbox);
375 M[i_theta][i][j] = sgn * v * norm;
385 if (m_mask !=
nullptr) {
389 m_mask =
new vpMatrix[m_mask_number];
393 unsigned int angle_pas = 180 / m_mask_number;
396 for (
unsigned int k = 0; k < m_mask_number; ++k) {
401 calculMasques(angle, m_mask_size, m_mask);
406 std::cout << std::endl;
407 std::cout <<
"Moving edges settings " << std::endl;
408 std::cout << std::endl;
409 std::cout <<
" Size of the convolution masks...." << m_mask_size <<
"x" << m_mask_size <<
" pixels" << std::endl;
410 std::cout <<
" Number of masks.................." << m_mask_number << std::endl;
411 std::cout <<
" Query range +/- J................" << m_range <<
" pixels" << std::endl;
412 std::cout <<
" Likelihood threshold type........" << (m_likelihood_threshold_type ==
NORMALIZED_THRESHOLD ?
"normalized " :
"old threshold (to be avoided)") << std::endl;
414 if (m_useAutomaticThreshold) {
415 std::cout <<
" Likelihood threshold............." <<
"unused" << std::endl;
416 std::cout <<
" Likelihood margin ratio.........." << m_thresholdMarginRatio << std::endl;
417 std::cout <<
" Minimum likelihood threshold....." << m_minThreshold << std::endl;
420 std::cout <<
" Likelihood threshold............." << m_threshold << std::endl;
421 std::cout <<
" Likelihood margin ratio.........." <<
"unused" << std::endl;
422 std::cout <<
" Minimum likelihood threshold....." <<
"unused" << std::endl;
425 const unsigned int val_100 = 100;
426 std::cout <<
" Contrast tolerance +/-..........." << (m_mu1 * val_100) <<
"% and " << (m_mu2 * val_100) <<
"% " << std::endl;
427 std::cout <<
" Sample step......................" << m_sample_step <<
" pixels" << std::endl;
428 std::cout <<
" Strip............................" << m_strip <<
" pixels " << std::endl;
429 std::cout <<
" Min sample step.................." << m_min_samplestep <<
" pixels " << std::endl;
433 : m_likelihood_threshold_type(OLD_THRESHOLD), m_thresholdMarginRatio(-1), m_minThreshold(-1), m_useAutomaticThreshold(false),
434 m_mu1(0.5), m_mu2(0.5), m_anglestep(1), m_mask_sign(0), m_ntotal_sample(0), m_mask(nullptr)
436 const double threshold_default = 1000;
437 const int points_to_track_default = 500;
438 const unsigned int mask_number_default = 180;
439 const unsigned int mask_size_default = 5;
440 const int strip_default = 2;
441 const double min_samplestep_default = 4;
442 const unsigned int flatAngle = 180;
443 const unsigned int range_default = 4;
444 const double sample_step_default = 10;
446 m_threshold = threshold_default;
447 m_points_to_track = points_to_track_default;
448 m_mask_number = mask_number_default;
449 m_mask_size = mask_size_default;
450 m_strip = strip_default;
451 m_min_samplestep = min_samplestep_default;
452 m_range = range_default;
453 m_sample_step = sample_step_default;
455 m_anglestep = (flatAngle / m_mask_number);
461 : m_likelihood_threshold_type(OLD_THRESHOLD), m_thresholdMarginRatio(-1), m_minThreshold(-1), m_useAutomaticThreshold(false),
462 m_mu1(0.5), m_mu2(0.5), m_anglestep(1), m_mask_sign(0), m_ntotal_sample(0), m_mask(nullptr)
464 const double threshold_default = 1000;
465 const int points_to_track_default = 500;
466 const unsigned int mask_number_default = 180;
467 const unsigned int mask_size_default = 5;
468 const int strip_default = 2;
469 const double min_samplestep_default = 4;
470 const unsigned int range_default = 4;
471 const double sample_step_default = 10;
473 m_threshold = threshold_default;
474 m_points_to_track = points_to_track_default;
475 m_mask_number = mask_number_default;
476 m_mask_size = mask_size_default;
477 m_strip = strip_default;
478 m_min_samplestep = min_samplestep_default;
479 m_range = range_default;
480 m_sample_step = sample_step_default;
487 if (m_mask !=
nullptr) {
492 m_likelihood_threshold_type = me.m_likelihood_threshold_type;
493 m_threshold = me.m_threshold;
494 m_thresholdMarginRatio = me.m_thresholdMarginRatio;
495 m_minThreshold = me.m_minThreshold;
496 m_useAutomaticThreshold = me.m_useAutomaticThreshold;
499 m_min_samplestep = me.m_min_samplestep;
500 m_anglestep = me.m_anglestep;
501 m_mask_size = me.m_mask_size;
502 m_mask_number = me.m_mask_number;
503 m_mask_sign = me.m_mask_sign;
504 m_range = me.m_range;
505 m_sample_step = me.m_sample_step;
506 m_ntotal_sample = me.m_ntotal_sample;
507 m_points_to_track = me.m_points_to_track;
508 m_strip = me.m_strip;
514 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
517 if (m_mask !=
nullptr) {
521 m_likelihood_threshold_type = std::move(me.m_likelihood_threshold_type);
522 m_threshold = std::move(me.m_threshold);
523 m_thresholdMarginRatio = std::move(me.m_thresholdMarginRatio);
524 m_minThreshold = std::move(me.m_minThreshold);
525 m_useAutomaticThreshold = std::move(me.m_useAutomaticThreshold);
526 m_mu1 = std::move(me.m_mu1);
527 m_mu2 = std::move(me.m_mu2);
528 m_min_samplestep = std::move(me.m_min_samplestep);
529 m_anglestep = std::move(me.m_anglestep);
530 m_mask_size = std::move(me.m_mask_size);
531 m_mask_number = std::move(me.m_mask_number);
532 m_mask_sign = std::move(me.m_mask_sign);
533 m_range = std::move(me.m_range);
534 m_sample_step = std::move(me.m_sample_step);
535 m_ntotal_sample = std::move(me.m_ntotal_sample);
536 m_points_to_track = std::move(me.m_points_to_track);
537 m_strip = std::move(me.m_strip);
546 if (m_mask !=
nullptr) {
554 const unsigned int flatAngle = 180;
555 m_mask_number = mask_number;
556 m_anglestep = flatAngle / m_mask_number;
562 m_mask_size = mask_size;
void resize(unsigned int nrows, unsigned int ncols, bool flagNullify=true, bool recopy_=true)
unsigned int getRows() const
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
static Type maximum(const Type &a, const Type &b)
static bool equal(double x, double y, double threshold=0.001)
static int sign(double x)
Implementation of a matrix and operations on matrices.
void setMaskNumber(const unsigned int &mask_number)
void setMaskSize(const unsigned int &mask_size)
vpMe & operator=(const vpMe &me)