30 #ifndef VP_COMMMON_DATA_H
31 #define VP_COMMMON_DATA_H
35 #include <visp3/core/vpConfig.h>
36 #include <visp3/core/vpImage.h>
37 #include <visp3/core/vpImageFilter.h>
38 #include <visp3/core/vpIoTools.h>
39 #include <visp3/gui/vpDisplayFactory.h>
40 #include <visp3/io/vpVideoReader.h>
42 #if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
43 #ifndef DOXYGEN_SHOULD_SKIP_THIS
46 inline void log(std::ostream &os,
const std::string &filename,
const std::string &funName,
const std::string &arrayName,
const VISP_NAMESPACE_ADDRESSING
vpArray2D<double> &array,
const unsigned int &level = 0)
48 os <<
"[" << filename <<
"::" << funName <<
"] ";
49 for (
unsigned int i = 0; i < level; ++i) {
52 os << arrayName <<
":=" << std::endl;
53 for (
unsigned int r = 0; r < array.getRows(); ++r) {
54 for (
unsigned int i = 0; i < level; ++i) {
58 for (
unsigned int c = 0; c < array.getCols() - 1; ++c) {
59 os << std::setprecision(3) << std::scientific << array[r][c] <<
"\t; ";
61 os << array[r][array.getCols() - 1] <<
"]\n";
66 typedef struct vpTutoCommonData
68 static const int SOFTWARE_CONTINUE = 4221;
69 const VISP_NAMESPACE_ADDRESSING
vpColor m_colorLegend = VISP_NAMESPACE_ADDRESSING
vpColor::red;
72 std::string m_seqFilename;
74 std::string m_hsvFilename;
77 double m_ratioSaltPepperNoise;
78 unsigned int m_degree;
86 #if defined(VISP_HAVE_DISPLAY)
87 std::shared_ptr<VISP_NAMESPACE_ADDRESSING vpDisplay> m_displayOrig;
88 std::shared_ptr<VISP_NAMESPACE_ADDRESSING vpDisplay> m_displaySegmented;
89 std::shared_ptr<VISP_NAMESPACE_ADDRESSING vpDisplay> m_displayNoisy;
93 double m_pfMaxDistanceForLikelihood;
95 std::vector<double> m_pfRatiosAmpliMax;
100 : m_seqFilename(VISP_NAMESPACE_ADDRESSING
vpIoTools::createFilePath(
"data",
"color_image_%04d.png"))
101 , m_hsvFilename(VISP_NAMESPACE_ADDRESSING
vpIoTools::createFilePath(
"calib",
"hsv-thresholds.yml"))
103 , m_ratioSaltPepperNoise(0.15)
105 , m_pfMaxDistanceForLikelihood(40)
107 , m_pfRatiosAmpliMax({ 0.25, 0.25, 0.25 })
117 inline void printHelp(
const char *softName)
119 std::cout <<
"\nSYNOPSIS " << std::endl
121 <<
" [--video <input video>] [--hsv-thresholds <filename.yml>] [--noise <ratio>]" << std::endl
122 <<
" [--degree <uint>]" << std::endl
123 <<
" [--max-distance-likelihood <double>] [-N, --nb-particles <uint>] [--seed <int>] [--nb-threads <int>] [--state-noise-ratio <ratio>]" << std::endl
126 std::cout <<
"\nOPTIONS " << std::endl
127 <<
" [General params]" << std::endl
128 <<
" --video <input video>" << std::endl
129 <<
" Name of the input video filename." << std::endl
130 <<
" If name is set to \"generate-simulated\" a simulated image is generated." << std::endl
131 <<
" Example: --video " << this->m_seqFilename << std::endl
133 <<
" --hsv-thresholds <filename.yaml>" << std::endl
134 <<
" Path to a yaml filename that contains H <min,max>, S <min,max>, V <min,max> threshold values." << std::endl
135 <<
" For an example, have a look to the file \"" << this->m_hsvFilename <<
"\"" << std::endl
137 <<
" --noise <ratio, [0; 1.[ >" << std::endl
138 <<
" Ratio of noisy points added to the image resulting from the skeletonization of the segmented image, to simulate sensor noise." << std::endl
139 <<
" Default = " << this->m_ratioSaltPepperNoise << std::endl
141 <<
" --degree <uint>" << std::endl
142 <<
" Choose the degree of the polynomials to use." << std::endl
143 <<
" Default = " << this->m_degree << std::endl
146 <<
" [PF params]" << std::endl
147 <<
" --max-distance-likelihood" << std::endl
148 <<
" Maximum mean square distance between a particle with the measurements." << std::endl
149 <<
" Above this value, the likelihood of the particle is 0." << std::endl
150 <<
" NOTE: M-estimation is used to make the likelihood function robust against outliers." << std::endl
151 <<
" Default: " << m_pfMaxDistanceForLikelihood << std::endl
153 <<
" -N, --nb-particles" << std::endl
154 <<
" Number of particles of the Particle Filter." << std::endl
155 <<
" Default: " << m_pfN << std::endl
157 <<
" --seed" << std::endl
158 <<
" Seed to initialize the Particle Filter." << std::endl
159 <<
" Use a negative value makes to use the current timestamp instead." << std::endl
160 <<
" Default: " << m_pfSeed << std::endl
162 <<
" --nb-threads" << std::endl
163 <<
" Set the number of threads to use in the Particle Filter (only if OpenMP is available)." << std::endl
164 <<
" Use a negative value to use the maximum number of threads instead." << std::endl
165 <<
" Default: " << m_pfNbThreads << std::endl
167 <<
" --state-noise-ratio <ratio>" << std::endl
168 <<
" Ratio of the initial guess of the curve coefficients to use as maximal amplitude of the noise added to the particles." << std::endl
169 <<
" Default: " << m_pfRatiosAmpliMax[0] << std::endl
170 <<
" --help, -h" << std::endl
171 <<
" Display this helper message." << std::endl
183 inline int init(
const int &argc,
const char *argv[])
188 std::string argname(argv[i]);
189 if ((argname == std::string(
"--video")) && ((i + 1) < argc)) {
191 m_seqFilename = std::string(argv[i]);
193 else if ((argname == std::string(
"--hsv-thresholds")) && ((i + 1) < argc)) {
195 m_hsvFilename = std::string(argv[i]);
197 else if ((argname ==
"--noise") && ((i + 1) < argc)) {
199 m_ratioSaltPepperNoise = std::atof(argv[i]);
201 else if ((argname == std::string(
"--degree")) && ((i + 1) < argc)) {
203 m_degree = std::atoi(argv[i]);
205 else if ((argname ==
"--max-distance-likelihood") && ((i+1) < argc)) {
207 m_pfMaxDistanceForLikelihood = std::atof(argv[i]);
209 else if (((argname ==
"-N") || (argname ==
"--nb-particles")) && ((i+1) < argc)) {
211 m_pfN = std::atoi(argv[i]);
213 else if ((argname ==
"--seed") && ((i+1) < argc)) {
215 m_pfSeed = std::atoi(argv[i]);
217 else if ((argname ==
"--nb-threads") && ((i+1) < argc)) {
219 m_pfNbThreads = std::atoi(argv[i]);
221 else if ((argname ==
"--state-noise-ratio") && ((i+1) < argc)) {
223 m_pfRatiosAmpliMax[0] = std::atof(argv[i]);
225 else if ((argname == std::string(
"-h")) || (argname == std::string(
"--help"))) {
226 vpTutoCommonData helpPrinter;
227 helpPrinter.printHelp(argv[0]);
231 std::cerr <<
"Unknown argument \"" << argname <<
"\"" << std::endl;
238 m_pfRatiosAmpliMax.resize(m_degree, m_pfRatiosAmpliMax[0]);
242 std::cout <<
"Load HSV threshold values from " << m_hsvFilename << std::endl;
243 std::cout <<
"HSV low/high values: " << m_hsv_values.t() << std::endl;
246 std::cout <<
"ERROR: unable to load HSV thresholds values from " << m_hsvFilename << std::endl;
252 m_grabber.setFileName(m_seqFilename);
253 m_grabber.open(m_I_orig);
255 catch (
const VISP_NAMESPACE_ADDRESSING
vpException &e) {
256 std::cout << e.getStringMessage() << std::endl;
260 m_I_segmented.resize(m_I_orig.getHeight(), m_I_orig.getWidth());
261 m_mask.resize(m_I_orig.getHeight(), m_I_orig.getWidth());
262 m_Iskeleton.resize(m_I_orig.getHeight(), m_I_orig.getWidth());
263 m_IskeletonNoisy.resize(m_I_orig.getHeight(), m_I_orig.getWidth());
266 #if defined(VISP_HAVE_DISPLAY)
267 const int horOffset = 20, vertOffset = 25;
268 std::string skeletonTitle(
"Skeletonized image (");
269 skeletonTitle += (m_ratioSaltPepperNoise == 0 ?
"without" : std::to_string(
static_cast<unsigned int>(m_ratioSaltPepperNoise * 100.)) +
"%");
270 skeletonTitle +=
" noise)";
272 m_displaySegmented = VISP_NAMESPACE_ADDRESSING
vpDisplayFactory::createDisplay(m_I_segmented, 2 * horOffset + m_I_orig.getWidth(), vertOffset,
"Segmented image");
273 m_displayNoisy = VISP_NAMESPACE_ADDRESSING
vpDisplayFactory::createDisplay(m_IskeletonNoisy, 2 * horOffset + m_I_orig.getWidth(), 2 * vertOffset + m_I_orig.getHeight(), skeletonTitle);
275 return SOFTWARE_CONTINUE;
278 #ifdef VISP_HAVE_DISPLAY
280 void displayLegend(
const VISP_NAMESPACE_ADDRESSING
vpImage<T> &I)
287 VISP_NAMESPACE_ADDRESSING
vpDisplay::displayText(I, ip + offset, std::string(
"Middle click to switch to ") + (m_stepbystep ? std::string(
"video mode") : std::string(
"step-by-step mode")), VISP_NAMESPACE_ADDRESSING
vpColor::red);
292 bool manageClicks(
const VISP_NAMESPACE_ADDRESSING
vpImage<T> &I,
bool &stepbystep)
297 if (button == VISP_NAMESPACE_ADDRESSING vpMouseButton::vpMouseButtonType::button3) {
300 if (button == VISP_NAMESPACE_ADDRESSING vpMouseButton::vpMouseButtonType::button2) {
301 stepbystep = stepbystep ^
true;
static bool loadYAML(const std::string &filename, vpArray2D< double > &A, char *header=nullptr)
Implementation of column vector and the associated operations.
Class to define RGB colors available for display functionalities.
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void displayText(const vpImage< unsigned char > &I, const vpImagePoint &ip, const std::string &s, const vpColor &color)
error that can be emitted by ViSP classes.
Class that defines a 2D point in an image. This class is useful for image processing and stores only ...
Definition of the vpImage class member functions.
Class that enables to manipulate easily a video file or a sequence of images. As it inherits from the...
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.