40#include <visp3/core/vpColVector.h>
41#include <visp3/core/vpMath.h>
42#include <visp3/me/vpMe.h>
46#ifndef DOXYGEN_SHOULD_SKIP_THIS
70template <
class Type>
inline void permute(Type &a, Type &b)
77static vpDroite2Dt droiteCartesienne(vpPoint2Dt P, vpPoint2Dt Q)
83 PQ.c = (
Q.y * P.x) - (
Q.x * P.y);
88static 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;
100static void recale(vpPoint2Dt &P,
const vpBBoxt &bbox)
119static void permute(vpPoint2Dt &A, vpPoint2Dt &B)
132static 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]);
245static 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 <<
" Init step query range +/- J......" << m_init_range <<
" pixels" << std::endl;
412 std::cout <<
" Query range +/- J................" << m_range <<
" pixels" << std::endl;
413 std::cout <<
" Likelihood threshold type........" << (m_likelihood_threshold_type ==
NORMALIZED_THRESHOLD ?
"normalized " :
"old threshold (to be avoided)") << std::endl;
415 if (m_useAutomaticThreshold) {
416 std::cout <<
" Likelihood threshold............." <<
"unused" << std::endl;
417 std::cout <<
" Likelihood margin ratio.........." << m_thresholdMarginRatio << std::endl;
418 std::cout <<
" Minimum likelihood threshold....." << m_minThreshold << std::endl;
421 std::cout <<
" Likelihood threshold............." << m_threshold << std::endl;
422 std::cout <<
" Likelihood margin ratio.........." <<
"unused" << std::endl;
423 std::cout <<
" Minimum likelihood threshold....." <<
"unused" << std::endl;
426 const unsigned int val_100 = 100;
427 std::cout <<
" Contrast tolerance +/-..........." << (m_mu1 * val_100) <<
"% and " << (m_mu2 * val_100) <<
"% " << std::endl;
428 std::cout <<
" Sample step......................" << m_sample_step <<
" pixels" << std::endl;
429 std::cout <<
" Strip............................" << m_strip <<
" pixels " << std::endl;
430 std::cout <<
" Min sample step.................." << m_min_samplestep <<
" pixels " << std::endl;
434 : m_likelihood_threshold_type(
OLD_THRESHOLD), m_thresholdMarginRatio(-1), m_minThreshold(-1), m_useAutomaticThreshold(false),
435 m_mu1(0.5), m_mu2(0.5), m_anglestep(1), m_mask_sign(0), m_init_range(1), m_ntotal_sample(0), m_mask(nullptr)
437 const double threshold_default = 1000;
438 const int points_to_track_default = 500;
439 const unsigned int mask_number_default = 180;
440 const unsigned int mask_size_default = 5;
441 const int strip_default = 2;
442 const double min_samplestep_default = 4;
443 const unsigned int flatAngle = 180;
444 const unsigned int range_default = 4;
445 const double sample_step_default = 10;
447 m_threshold = threshold_default;
448 m_points_to_track = points_to_track_default;
449 m_mask_number = mask_number_default;
450 m_mask_size = mask_size_default;
451 m_strip = strip_default;
452 m_min_samplestep = min_samplestep_default;
453 m_range = range_default;
454 m_sample_step = sample_step_default;
456 m_anglestep = (flatAngle / m_mask_number);
462 : m_likelihood_threshold_type(
OLD_THRESHOLD), m_thresholdMarginRatio(-1), m_minThreshold(-1), m_useAutomaticThreshold(false),
463 m_mu1(0.5), m_mu2(0.5), m_anglestep(1), m_mask_sign(0), m_init_range(1), m_ntotal_sample(0), m_mask(nullptr)
465 const double threshold_default = 1000;
466 const int points_to_track_default = 500;
467 const unsigned int mask_number_default = 180;
468 const unsigned int mask_size_default = 5;
469 const int strip_default = 2;
470 const double min_samplestep_default = 4;
471 const unsigned int range_default = 4;
472 const double sample_step_default = 10;
474 m_threshold = threshold_default;
475 m_points_to_track = points_to_track_default;
476 m_mask_number = mask_number_default;
477 m_mask_size = mask_size_default;
478 m_strip = strip_default;
479 m_min_samplestep = min_samplestep_default;
480 m_range = range_default;
481 m_sample_step = sample_step_default;
488 if (m_mask !=
nullptr) {
493 m_likelihood_threshold_type = me.m_likelihood_threshold_type;
494 m_threshold = me.m_threshold;
495 m_thresholdMarginRatio = me.m_thresholdMarginRatio;
496 m_minThreshold = me.m_minThreshold;
497 m_useAutomaticThreshold = me.m_useAutomaticThreshold;
500 m_min_samplestep = me.m_min_samplestep;
501 m_anglestep = me.m_anglestep;
502 m_mask_size = me.m_mask_size;
503 m_mask_number = me.m_mask_number;
504 m_mask_sign = me.m_mask_sign;
505 m_init_range = me.m_init_range;
506 m_range = me.m_range;
507 m_sample_step = me.m_sample_step;
508 m_ntotal_sample = me.m_ntotal_sample;
509 m_points_to_track = me.m_points_to_track;
510 m_strip = me.m_strip;
516#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
519 if (m_mask !=
nullptr) {
523 m_likelihood_threshold_type = std::move(me.m_likelihood_threshold_type);
524 m_threshold = std::move(me.m_threshold);
525 m_thresholdMarginRatio = std::move(me.m_thresholdMarginRatio);
526 m_minThreshold = std::move(me.m_minThreshold);
527 m_useAutomaticThreshold = std::move(me.m_useAutomaticThreshold);
528 m_mu1 = std::move(me.m_mu1);
529 m_mu2 = std::move(me.m_mu2);
530 m_min_samplestep = std::move(me.m_min_samplestep);
531 m_anglestep = std::move(me.m_anglestep);
532 m_mask_size = std::move(me.m_mask_size);
533 m_mask_number = std::move(me.m_mask_number);
534 m_mask_sign = std::move(me.m_mask_sign);
535 m_init_range = std::move(me.m_init_range);
536 m_range = std::move(me.m_range);
537 m_sample_step = std::move(me.m_sample_step);
538 m_ntotal_sample = std::move(me.m_ntotal_sample);
539 m_points_to_track = std::move(me.m_points_to_track);
540 m_strip = std::move(me.m_strip);
549 if (m_mask !=
nullptr) {
557 const unsigned int flatAngle = 180;
558 m_mask_number = mask_number;
559 m_anglestep = flatAngle / m_mask_number;
565 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)
@ OLD_THRESHOLD
Old likelihood ratio threshold (to be avoided).