UsTK : Ultrasound ToolKit  version 2.0.1 under development (2023-12-07)
usDenseTracker2D.cpp
1 /****************************************************************************
2  *
3  * This file is part of the ustk software.
4  * Copyright (C) 2016 - 2017 by Inria. All rights reserved.
5  *
6  * This software is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * ("GPL") version 2 as published by the Free Software Foundation.
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 ustk 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  * This software was developed at:
17  * Inria Rennes - Bretagne Atlantique
18  * Campus Universitaire de Beaulieu
19  * 35042 Rennes Cedex
20  * France
21  *
22  * If you have questions regarding the use of this file, please contact
23  * Inria at ustk@inria.fr
24  *
25  * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26  * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27  *
28  * Authors:
29  * Pierre Chatelain
30  * Alexandre Krupa
31  *
32  *****************************************************************************/
33 
34 #include <visp3/ustk_template_tracking/usDenseTracker2D.h>
35 
36 #include <visp3/core/vpImageTools.h>
37 
38 #include <visp3/core/vpImageFilter.h>
39 
43 usDenseTracker2D::usDenseTracker2D() { m_isInit = false; }
44 
49 
56 void usDenseTracker2D::init(const vpImage<unsigned char> &I, const vpRectOriented &R)
57 {
58  vpImageTools::extract(I, m_template, R);
59  vpImageTools::extract(I, m_region, R);
60  m_target = R;
61  m_height = m_template.getHeight();
62  m_width = m_template.getWidth();
63  m_size = m_template.getSize();
64  s_desired.resize(m_size);
65  s_current.resize(m_size);
66  m_LI.resize(m_size, 3);
67 
68  // compute gradients
69  vpImageFilter::getGradY(m_template, m_gradX);
70  vpImageFilter::getGradX(m_template, m_gradY);
71 
72  // center of the target
73  double u0 = m_target.getHeight() / 2.0;
74  double v0 = m_target.getWidth() / 2.0;
75 
76  // filling desired col vector with pixels values of template region
77  // filling interaction matrix
78  for (unsigned int u = 0; u < m_height; ++u)
79  for (unsigned int v = 0; v < m_width; ++v) {
80  s_desired[u * m_width + v] = m_template[u][v];
81  s_current[u * m_width + v] = m_region[u][v];
82  m_LI[u * m_width + v][0] = m_gradX[u][v];
83  m_LI[u * m_width + v][1] = m_gradY[u][v];
84  m_LI[u * m_width + v][2] =
85  (static_cast<double>(u) - u0) * m_gradY[u][v] - (static_cast<double>(v) - v0) * m_gradX[u][v];
86  }
87  // pseudo inverse of interaction matrix
88  m_LI_inverse = m_LI.pseudoInverse();
89  m_isInit = true;
90 }
91 
96 void usDenseTracker2D::update(const vpImage<unsigned char> &I)
97 {
98  if (m_isInit) {
99  double gain = 0.6;
100 
101  unsigned int max_iter = 40;
102  unsigned int i = 0;
103  double rms = 1.0;
104  double rms0 = 0.0;
105  double drms = 1.0e-5;
106 
107  while ((i < max_iter) && (std::abs(rms - rms0) > drms)) {
108  // extract new region from previous target rectangle
109  vpImageTools::extract(I, m_region, m_target);
110 
111  // filling current features colVector
112  for (unsigned int u = 0; u < m_height; ++u)
113  for (unsigned int v = 0; v < m_width; ++v)
114  s_current[u * m_width + v] = m_region[u][v];
115 
116  // compute error and velocity command
117  vpColVector e = s_current - s_desired;
118  vpColVector v = -gain * m_LI_inverse * e;
119 
120  rms0 = rms;
121  rms = e.frobeniusNorm() / m_size;
122 
123  // extract deplacements to apply to follow the region
124  double alpha = m_target.getOrientation();
125  double dx = v[0] * cos(alpha) + v[1] * sin(alpha);
126  double dy = v[1] * cos(alpha) - v[0] * sin(alpha);
127  double da = -v[2];
128 
129  // update target with old values and deplacements previously comuted
130  m_target.setCenter(
131  vpImagePoint(m_target.getCenter().get_i() + gain * dx, m_target.getCenter().get_j() + gain * dy));
132  m_target.setOrientation(alpha + gain * da);
133 
134  ++i;
135  }
136  }
137 }
138 
143 vpRectOriented usDenseTracker2D::getTarget() const
144 {
145  if (!m_isInit)
146  throw(vpException(vpException::fatalError, "usDenseTracker2D not initialized !"));
147  return m_target;
148 }
149 
150 vpImage<unsigned char> &usDenseTracker2D::getTemplate() { return m_template; }
151 
152 vpImage<unsigned char> &usDenseTracker2D::getRegion() { return m_region; }
153 
154 bool usDenseTracker2D::isInit() { return m_isInit; }
void update(const vpImage< unsigned char > &I)
Tracking method, to call at every new frame to track.
void init(const vpImage< unsigned char > &I, const vpRectOriented &R)
Initialisation of the tracker : to call to set the region to track (R) in the image (I) before starti...
vpImage< unsigned char > & getTemplate()
vpRectOriented getTarget() const
To call after update() at each new frame, to get the position of the ROI in the last acquired frame.
vpImage< unsigned char > & getRegion()