Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpTemplateTrackerZone.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2025 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 * Template tracker.
32 */
33
34#include <visp3/core/vpConfig.h>
35
36#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
37#include <opencv2/imgproc/imgproc.hpp>
38#endif
39
40#include <visp3/tt/vpTemplateTrackerZone.h>
41
47
52 : Zone(), min_x(-1), min_y(-1), max_x(-1), max_y(-1)
53{
54 *this = z;
55}
56
61{
62 min_x = -1;
63 min_y = -1;
64 max_x = -1;
65 max_y = -1;
66
67 Zone.clear();
68}
69
74{
75 clear();
76
77 this->copy(z);
78 return (*this);
79}
80
104{
105 Zone.clear();
106
107 std::vector<vpImagePoint> vip;
108
109 bool end = false;
110
111 do {
112 vpImagePoint p;
114 if (vpDisplay::getClick(I, p, button, false)) {
115 vip.push_back(p);
116
118
119 if (vip.size() > 1) {
120 if (delaunay) {
121 // Draw a line between the 2 last points
122 vpDisplay::displayLine(I, p, vip[vip.size() - 2], vpColor::blue, 3);
123 }
124 else {
125 if (vip.size() % 3 == 2)
126 // draw line between point 2-1
127 vpDisplay::displayLine(I, p, vip[vip.size() - 2], vpColor::blue, 3);
128 else if (vip.size() % 3 == 0) {
129 // draw line between point 3-2
130 vpDisplay::displayLine(I, p, vip[vip.size() - 2], vpColor::blue, 3);
131 // draw line between point 3-1
132 vpDisplay::displayLine(I, p, vip[vip.size() - 3], vpColor::blue, 3);
133 }
134 }
135 }
136
137 if (button == vpMouseButton::button3)
138 end = true;
139 }
140
141 vpTime::wait(20);
143 } while (!end);
144
145 initFromPoints(I, vip, delaunay);
146}
147
161void vpTemplateTrackerZone::initFromPoints(const vpImage<unsigned char> &I, const std::vector<vpImagePoint> &vip,
162 bool delaunay)
163{
164 if (delaunay) {
165 if (vip.size() == 3) {
166 initFromPoints(I, vip, false);
167 }
168 else if (vip.size() == 4) {
169 std::vector<vpImagePoint> vip_delaunay;
170 vip_delaunay.push_back(vip[0]);
171 vip_delaunay.push_back(vip[1]);
172 vip_delaunay.push_back(vip[2]);
173 vip_delaunay.push_back(vip[2]);
174 vip_delaunay.push_back(vip[3]);
175 vip_delaunay.push_back(vip[0]);
176 initFromPoints(I, vip_delaunay, false);
177 }
178 else {
179#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC)
180 // Init Delaunay
181 cv::Subdiv2D subdiv(cv::Rect(0, 0, static_cast<int>(I.getWidth()), static_cast<int>(I.getHeight())));
182 for (size_t i = 0; i < vip.size(); i++) {
183 cv::Point2f fp(static_cast<float>(vip[i].get_u()), static_cast<float>(vip[i].get_v()));
184 // std::cout << "Click point: " << vip[i] << std::endl;
185 subdiv.insert(fp);
186 }
187
188 // Compute Delaunay triangulation
189 std::vector<cv::Vec6f> triangleList;
190 subdiv.getTriangleList(triangleList);
191
192 // Keep only the Delaunay points that are inside the area
193 vpRect rect(0, 0, I.getWidth(), I.getHeight());
194
195 std::vector<vpImagePoint> vip_delaunay;
196 for (size_t i = 0; i < triangleList.size(); i++) {
197 cv::Vec6f t = triangleList[i];
198 std::vector<vpImagePoint> p(3);
199
200 p[0].set_uv(t[0], t[1]);
201 p[1].set_uv(t[2], t[3]);
202 p[2].set_uv(t[4], t[5]);
203
204 if (p[0].inRectangle(rect) && p[1].inRectangle(rect) && p[2].inRectangle(rect)) {
205 vip_delaunay.push_back(p[0]);
206 vip_delaunay.push_back(p[1]);
207 vip_delaunay.push_back(p[2]);
208 }
209 }
210
211 initFromPoints(I, vip_delaunay, false);
212#else
213 throw vpException(vpException::functionNotImplementedError, "Delaunay triangulation is not available!");
214#endif
215 }
216 }
217 else {
218 Zone.clear();
219 for (unsigned int i = 0; i < vip.size(); i += 3) {
220 vpTemplateTrackerTriangle triangle(vip[i], vip[i + 1], vip[i + 2]);
221 add(triangle);
222
223 // vpDisplay::displayLine(I, vip[i], vip[i+1], vpColor::green,
224 // 1); vpDisplay::displayLine(I, vip[i+1], vip[i+2],
225 // vpColor::green, 1); vpDisplay::displayLine(I, vip[i+2], vip[i],
226 // vpColor::green,1); vpDisplay::flush(I) ;
227
228 // Update the bounding box
229 if ((triangle.getMinx() < min_x) || (min_x == -1))
230 min_x = static_cast<int>(triangle.getMinx());
231 if ((triangle.getMaxx() > max_x) || (max_x == -1))
232 max_x = static_cast<int>(triangle.getMaxx());
233 if ((triangle.getMiny() < min_y) || (min_y == -1))
234 min_y = static_cast<int>(triangle.getMiny());
235 if ((triangle.getMaxy() > max_y) || (max_y == -1))
236 max_y = static_cast<int>(triangle.getMaxy());
237 }
238 }
239}
240
246{
247 Zone.push_back(t);
248
249 // Update the bounding box
250 if ((t.getMinx() < min_x) || (min_x == -1))
251 min_x = static_cast<int>(t.getMinx());
252 if ((t.getMaxx() > max_x) || (max_x == -1))
253 max_x = static_cast<int>(t.getMaxx());
254 if ((t.getMiny() < min_y) || (min_y == -1))
255 min_y = static_cast<int>(t.getMiny());
256 if ((t.getMaxy() > max_y) || (max_y == -1))
257 max_y = static_cast<int>(t.getMaxy());
258}
259
267bool vpTemplateTrackerZone::inZone(const int &i, const int &j) const
268{
269 std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
270 for (Iterateurvecteur = Zone.begin(); Iterateurvecteur != Zone.end(); ++Iterateurvecteur) {
271 if (Iterateurvecteur->inTriangle(i, j))
272 return true;
273 }
274 return false;
275}
276
285bool vpTemplateTrackerZone::inZone(const double &i, const double &j) const
286{
287 std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
288 for (Iterateurvecteur = Zone.begin(); Iterateurvecteur != Zone.end(); ++Iterateurvecteur) {
289 if (Iterateurvecteur->inTriangle(i, j))
290 return true;
291 }
292 return false;
293}
294
305bool vpTemplateTrackerZone::inZone(const int &i, const int &j, unsigned int &id_triangle) const
306{
307 unsigned int id = 0;
308 std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
309 for (Iterateurvecteur = Zone.begin(); Iterateurvecteur != Zone.end(); ++Iterateurvecteur) {
310 if (Iterateurvecteur->inTriangle(i, j)) {
311 id_triangle = id;
312 return true;
313 }
314 id++;
315 }
316 return false;
317}
318
329bool vpTemplateTrackerZone::inZone(const double &i, const double &j, unsigned int &id_triangle) const
330{
331 unsigned int id = 0;
332 std::vector<vpTemplateTrackerTriangle>::const_iterator Iterateurvecteur;
333 for (Iterateurvecteur = Zone.begin(); Iterateurvecteur != Zone.end(); ++Iterateurvecteur) {
334 if (Iterateurvecteur->inTriangle(i, j)) {
335 id_triangle = id;
336 return true;
337 }
338 id++;
339 }
340 return false;
341}
342
362{
363 if (i > getNbTriangle() - 1)
364 throw(vpException(vpException::badValue, "Cannot get triangle with index %u", i));
365
366 T = Zone[i];
367}
368
385{
386 if (i > getNbTriangle() - 1)
387 throw(vpException(vpException::badValue, "Cannot get triangle with index %u", i));
388
389 return Zone[i];
390}
391
396{
397 double xc = 0;
398 double yc = 0;
399 int cpt = 0;
400 for (int i = min_y; i < max_y; i++)
401 for (int j = min_x; j < max_x; j++)
402 if (inZone(i, j)) {
403 xc += j;
404 yc += i;
405 cpt++;
406 }
407 if (!cpt) {
408 throw(vpException(vpException::divideByZeroError, "Cannot compute the zone center: size = 0"));
409 }
410 xc = xc / cpt;
411 yc = yc / cpt;
412 vpImagePoint ip;
413 ip.set_uv(xc, yc);
414 return ip;
415}
416
437
443{
444 vpRect bbox;
447 return bbox;
448}
449
458void vpTemplateTrackerZone::display(const vpImage<unsigned char> &I, const vpColor &col, unsigned int thickness)
459{
460 std::vector<vpImagePoint> ip;
461 for (unsigned int i = 0; i < Zone.size(); i++) {
463 Zone[i].getCorners(ip);
464 vpDisplay::displayLine(I, ip[0], ip[1], col, thickness);
465 vpDisplay::displayLine(I, ip[1], ip[2], col, thickness);
466 vpDisplay::displayLine(I, ip[2], ip[0], col, thickness);
467 }
468}
469
478void vpTemplateTrackerZone::display(const vpImage<vpRGBa> &I, const vpColor &col, unsigned int thickness)
479{
480 std::vector<vpImagePoint> ip;
481 for (unsigned int i = 0; i < Zone.size(); i++) {
483 Zone[i].getCorners(ip);
484 vpDisplay::displayLine(I, ip[0], ip[1], col, thickness);
485 vpDisplay::displayLine(I, ip[1], ip[2], col, thickness);
486 vpDisplay::displayLine(I, ip[2], ip[0], col, thickness);
487 }
488}
489
494
502void vpTemplateTrackerZone::fillTriangle(vpImage<unsigned char> &I, unsigned int id, unsigned char gray_level)
503{
504 assert(id < getNbTriangle());
506 getTriangle(id, triangle);
507 for (int i = 0; i < static_cast<int>(I.getHeight()); i++) {
508 for (int j = 0; j < static_cast<int>(I.getWidth()); j++) {
509 if (triangle.inTriangle(i, j)) {
510 I[i][j] = gray_level;
511 }
512 }
513 }
514}
515
520{
521 vpTemplateTrackerZone tempZone;
524 for (unsigned int i = 0; i < getNbTriangle(); i++) {
525 getTriangle(i, Ttemp);
526 TtempDown = Ttemp.getPyramidDown();
527 tempZone.add(TtempDown);
528 }
529 return tempZone;
530}
531
538{
540 for (unsigned int i = 0; i < z.getNbTriangle(); i++) {
541 z.getTriangle(i, triangle);
542 add(triangle);
543 // Update the bounding box
544 if ((triangle.getMinx() < min_x) || (min_x == -1))
545 min_x = static_cast<int>(triangle.getMinx());
546 if ((triangle.getMaxx() > max_x) || (max_x == -1))
547 max_x = static_cast<int>(triangle.getMaxx());
548 if ((triangle.getMiny() < min_y) || (min_y == -1))
549 min_y = static_cast<int>(triangle.getMiny());
550 if ((triangle.getMaxy() > max_y) || (max_y == -1))
551 max_y = static_cast<int>(triangle.getMaxy());
552 }
553}
554
561
562vpImagePoint vpTemplateTrackerZone::getCenter(int borne_x, int borne_y) const
563{
564 int cpt_pt = 0;
565 double x_center = 0, y_center = 0;
566 for (int j = 0; j < borne_x; j++)
567 for (int i = 0; i < borne_y; i++)
568 if (inZone(i, j)) {
569 x_center += j;
570 y_center += i;
571 cpt_pt++;
572 }
573
574 if (!cpt_pt) {
575 throw(vpException(vpException::divideByZeroError, "Cannot compute the zone center: size = 0"));
576 }
577
578 x_center = x_center / cpt_pt;
579 y_center = y_center / cpt_pt;
580 vpImagePoint center;
581 center.set_uv(x_center, y_center);
582 return center;
583}
584
589{
590 double area = 0;
592 for (unsigned int i = 0; i < getNbTriangle(); i++) {
593 getTriangle(i, triangle);
594 area += triangle.getArea();
595 }
596 return area;
597}
598END_VISP_NAMESPACE
Class to define RGB colors available for display functionalities.
Definition vpColor.h:157
static const vpColor red
Definition vpColor.h:198
static const vpColor blue
Definition vpColor.h:204
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayLine(const vpImage< unsigned char > &I, const vpImagePoint &ip1, const vpImagePoint &ip2, const vpColor &color, unsigned int thickness=1, bool segment=true)
static void displayCross(const vpImage< unsigned char > &I, const vpImagePoint &ip, unsigned int size, const vpColor &color, unsigned int thickness=1)
static void flush(const vpImage< unsigned char > &I)
error that can be emitted by ViSP classes.
Definition vpException.h:60
@ badValue
Used to indicate that a value is not in the allowed range.
Definition vpException.h:73
@ functionNotImplementedError
Function not implemented.
Definition vpException.h:66
@ divideByZeroError
Division by zero.
Definition vpException.h:70
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
void set_uv(double u, double v)
Definition of the vpImage class member functions.
Definition vpImage.h:131
Defines a rectangle in the plane.
Definition vpRect.h:79
void setBottomRight(const vpImagePoint &bottomRight)
Definition vpRect.h:296
void setTopLeft(const vpImagePoint &topLeft)
Definition vpRect.h:366
bool inTriangle(const vpImagePoint &ip) const
vpTemplateTrackerTriangle getPyramidDown() const
vpTemplateTrackerZone getPyramidDown() const
std::vector< vpTemplateTrackerTriangle > Zone
Vector of triangles that defines the zone.
int max_y
Bounding box parameter.
vpTemplateTrackerZone & operator=(const vpTemplateTrackerZone &z)
void initFromPoints(const vpImage< unsigned char > &I, const std::vector< vpImagePoint > &ip, bool delaunay=false)
bool inZone(const int &i, const int &j) const
void getTriangle(unsigned int i, vpTemplateTrackerTriangle &T) const
unsigned int getNbTriangle() const
void copy(const vpTemplateTrackerZone &z)
int max_x
Bounding box parameter.
void fillTriangle(vpImage< unsigned char > &I, unsigned int id, unsigned char gray_level)
void add(const vpTemplateTrackerTriangle &t)
vpImagePoint getCenter() const
void display(const vpImage< unsigned char > &I, const vpColor &col=vpColor::green, unsigned int thickness=3)
int min_y
Bounding box parameter.
void initClick(const vpImage< unsigned char > &I, bool delaunay=false)
int min_x
Bounding box parameter.
VISP_EXPORT int wait(double t0, double t)