Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpMeTracker.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2019 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 * Moving edges.
32 */
33
38
39#include <visp3/core/vpColor.h>
40#include <visp3/core/vpDisplay.h>
41#include <visp3/me/vpMeTracker.h>
42
43#include <algorithm>
44#include <visp3/core/vpTrackingException.h>
45
47
49{
51 const unsigned int val_2 = 2;
52 p.resize(val_2);
54}
55
57 : m_meList(), m_me(nullptr), m_nGoodElement(0), m_mask(nullptr), m_maskCandidates(nullptr), m_selectDisplay(vpMeSite::NONE)
58{
59 init();
60}
61
63 : vpTracker(meTracker), m_meList(), m_me(nullptr), m_nGoodElement(0), m_mask(nullptr), m_maskCandidates(nullptr), m_selectDisplay(vpMeSite::NONE)
64{
65 init();
66
67 m_me = meTracker.m_me;
68 m_meList = meTracker.m_meList;
71}
72
74{
76 m_meList.clear();
77}
78
80
82{
83 m_meList = meTracker.m_meList;
84 m_me = meTracker.m_me;
87 return *this;
88}
89
90static bool isSuppressZero(const vpMeSite &P) { return (P.getState() == vpMeSite::NO_SUPPRESSION); }
91
93{
94 unsigned int number_signal = 0;
95
96 // Loop through all the points tracked from the contour
97 number_signal = static_cast<unsigned int>(std::count_if(m_meList.begin(), m_meList.end(), isSuppressZero));
98 return number_signal;
99}
100
101unsigned int vpMeTracker::totalNumberOfSignal() { return static_cast<unsigned int>(m_meList.size()); }
102
103bool vpMeTracker::inRoiMask(const vpImage<bool> *mask, unsigned int i, unsigned int j)
104{
105 try {
106 return ((mask == nullptr) || (mask->getValue(i, j)));
107 }
108 catch (vpException &) {
109 return false;
110 }
111}
112
113bool vpMeTracker::inMeMaskCandidates(const vpImage<bool> *meMaskCandidates, unsigned int i, unsigned int j)
114{
115 if (meMaskCandidates == nullptr) {
116 return true;
117 }
118 else {
119 const unsigned int kernelSize = 3;
120 const unsigned int halfKernelSize = (kernelSize - 1) / 2;
121 const unsigned int nbRows = meMaskCandidates->getRows();
122 const unsigned int nbCols = meMaskCandidates->getCols();
123
124 if ((i >= nbRows) || (j >= nbCols)) {
125 // The asked point is outside the mask
126 return false;
127 }
128 if ((*meMaskCandidates)[i][j]) {
129 // The asked point is a candidate
130 return true;
131 }
132 unsigned int iStart = 0, jStart = 0;
133 unsigned int iStop = nbRows - 1, jStop = nbCols - 1;
134 // Ensuring we won't go outside the limits of the mask
135 if (i >= halfKernelSize) {
136 iStart = i - halfKernelSize;
137 }
138 if (j >= halfKernelSize) {
139 jStart = j - halfKernelSize;
140 }
141 if ((i + halfKernelSize) < nbRows) {
142 iStop = i + halfKernelSize;
143 }
144 if ((j + halfKernelSize) < nbCols) {
145 jStop = j + halfKernelSize;
146 }
147 // Looking in its neighborhood
148 bool isACandidate = false;
149 unsigned int iter_i = iStart, iter_j = jStart;
150
151 while ((!isACandidate) && (iter_i <= iStop)) {
152 iter_j = jStart;
153 while ((!isACandidate) && (iter_j <= jStop)) {
154 isACandidate = (*meMaskCandidates)[iter_i][iter_j];
155 ++iter_j;
156 }
157 ++iter_i;
158 }
159
160 return isACandidate;
161 }
162}
163
164bool vpMeTracker::outOfImage(int i, int j, int border, int nrows, int ncols)
165{
166 int borderWith2SparedPixels = border + 2;
167 return (!((i > borderWith2SparedPixels) && (i < (nrows - borderWith2SparedPixels))
168 && (j > borderWith2SparedPixels) && (j < (ncols - borderWith2SparedPixels))
169 ));
170}
171
172bool vpMeTracker::outOfImage(const vpImagePoint &iP, int border, int nrows, int ncols)
173{
174 const int borderPlus2 = border + 2;
175 int i = vpMath::round(iP.get_i());
176 int j = vpMath::round(iP.get_j());
177 return (!((i > borderPlus2) && (i < (nrows - borderPlus2)) && (j > borderPlus2) && (j < (ncols - borderPlus2))));
178}
179
181{
182 if (!m_me) {
183 throw(vpTrackingException(vpTrackingException::initializationError, "Moving edges not initialized"));
184 }
185
186 // Must set range to 0
187 unsigned int range_tmp = m_me->getRange();
188 m_me->setRange(m_me->getInitRange());
189
190 m_nGoodElement = 0;
191
192 // Loop through list of sites to track
193 std::list<vpMeSite>::iterator end = m_meList.end();
194 for (std::list<vpMeSite>::iterator it = m_meList.begin(); it != end; ++it) {
195 vpMeSite refp = *it; // current reference pixel
196
197 // If element hasn't been suppressed
198 if (refp.getState() == vpMeSite::NO_SUPPRESSION) {
199
200 refp.track(I, m_me, false);
201
202 if (refp.getState() == vpMeSite::NO_SUPPRESSION) {
204 }
205 }
206
207 *it = refp;
208 }
209
210 m_me->setRange(range_tmp);
211}
212
214{
215 if (!m_me) {
216 throw(vpTrackingException(vpTrackingException::initializationError, "Moving edges not initialized"));
217 }
218
219 if (m_meList.empty()) {
220 throw(vpTrackingException(vpTrackingException::notEnoughPointError, "Too few pixel to track"));
221 }
222
223 m_nGoodElement = 0;
224
225 // Loop through list of sites to track
226 std::list<vpMeSite>::iterator it = m_meList.begin();
227 std::list<vpMeSite>::iterator end = m_meList.end();
228 while (it != end) {
229 vpMeSite s = *it; // current reference pixel
230
231 // If element hasn't been suppressed
232 if (s.getState() == vpMeSite::NO_SUPPRESSION) {
233 s.track(I, m_me, true);
234
235
236 if (vpMeTracker::inRoiMask(m_mask, s.get_i(), s.get_j())) {
237 if (s.getState() == vpMeSite::NO_SUPPRESSION) {
239 }
240 }
241 else {
242 // Site outside mask
243 s.setState(vpMeSite::OUTSIDE_ROI_MASK);
244 }
245 }
246
247 *it = s;
248 ++it;
249 }
250}
251
253{
254 std::list<vpMeSite>::const_iterator end = m_meList.end();
255 for (std::list<vpMeSite>::const_iterator it = m_meList.begin(); it != end; ++it) {
256 vpMeSite p_me = *it;
257 p_me.display(I);
258 }
259}
260
262{
263 std::list<vpMeSite>::const_iterator end = m_meList.end();
264 for (std::list<vpMeSite>::const_iterator it = m_meList.begin(); it != end; ++it) {
265 vpMeSite p_me = *it;
266 p_me.display(I);
267 }
268}
269
270void vpMeTracker::display(const vpImage<unsigned char> &I, vpColVector &w, unsigned int &index_w)
271{
272 std::list<vpMeSite>::iterator end = m_meList.end();
273 for (std::list<vpMeSite>::iterator it = m_meList.begin(); it != end; ++it) {
274 vpMeSite P = *it;
275
277 P.setWeight(w[index_w]);
278 ++index_w;
279 }
280
281 *it = P;
282 }
283 display(I);
284}
285
286END_VISP_NAMESPACE
Implementation of column vector and the associated operations.
error that can be emitted by ViSP classes.
Definition vpException.h:60
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
double get_j() const
double get_i() const
Definition of the vpImage class member functions.
Definition vpImage.h:131
Type getValue(unsigned int i, unsigned int j) const
unsigned int getCols() const
Definition vpImage.h:171
unsigned int getRows() const
Definition vpImage.h:212
static int round(double x)
Definition vpMath.h:413
Performs search in a given direction(normal) for a given distance(pixels) for a given 'site'....
Definition vpMeSite.h:75
@ OUTSIDE_ROI_MASK
Point is outside the region of interest mask, but retained in the ME list.
Definition vpMeSite.h:102
@ NO_SUPPRESSION
Point successfully tracked.
Definition vpMeSite.h:93
void display(const vpImage< unsigned char > &I) const
Definition vpMeSite.cpp:547
void setWeight(const double &weight)
Definition vpMeSite.h:313
@ NONE
Not displayed.
Definition vpMeSite.h:82
vpMeSiteState getState() const
Definition vpMeSite.h:306
void track(const vpImage< unsigned char > &I, const vpMe *me, const bool &test_contrast=true)
Definition vpMeSite.cpp:330
void initTracking(const vpImage< unsigned char > &I)
const vpImage< bool > * m_mask
Mask used to disable tracking on a part of image.
unsigned int numberOfSignal()
vpMeSite::vpMeSiteDisplayType m_selectDisplay
Moving-edges display type.
void track(const vpImage< unsigned char > &I)
unsigned int totalNumberOfSignal()
vpMe * m_me
Moving edges initialisation parameters.
vpMeTracker & operator=(vpMeTracker &meTracker)
static bool inRoiMask(const vpImage< bool > *mask, unsigned int i, unsigned int j)
void display(const vpImage< unsigned char > &I)
int m_nGoodElement
Number of good moving-edges that are tracked.
bool outOfImage(int i, int j, int border, int nrows, int ncols)
const vpImage< bool > * m_maskCandidates
Mask used to determine candidate points for initialization in an image.
virtual ~vpMeTracker() VP_OVERRIDE
std::list< vpMeSite > m_meList
static bool inMeMaskCandidates(const vpImage< bool > *meMaskCandidates, unsigned int i, unsigned int j)
void init()
Default initialization.
Definition vpTracker.cpp:43
vpTracker()
Default constructor.
Definition vpTracker.cpp:45
vpColVector p
Definition vpTracker.h:69
Error that can be emitted by the vpTracker class and its derivatives.
@ notEnoughPointError
Not enough point to track.
@ initializationError
Tracker initialization error.