Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
vpTutoSegmentation.cpp
1/*
2 * ViSP, open source Visual Servoing Platform software.
3 * Copyright (C) 2005 - 2024 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
31#include "vpTutoSegmentation.h"
32
33#include <visp3/core/vpGaussRand.h>
34#include <visp3/core/vpHSV.h>
35
36#if (VISP_CXX_STANDARD >= VISP_CXX_STANDARD_11)
37#ifndef DOXYGEN_SHOULD_SKIP_THIS
38namespace tutorial
39{
40#ifdef ENABLE_VISP_NAMESPACE
41using namespace VISP_NAMESPACE_NAME;
42#endif
43
44void performSegmentationHSV(vpTutoCommonData &data)
45{
46 vpImage<vpHSV<unsigned char, true>> Ihsv;
47
48 vpImageConvert::convert(data.m_I_orig, Ihsv);
49
50 vpImageTools::inRange(Ihsv, data.m_hsv_values, data.m_mask);
51
52 vpImageTools::inMask(data.m_I_orig, data.m_mask, data.m_I_segmented);
53}
54
55std::vector< VISP_NAMESPACE_ADDRESSING vpImagePoint > extractSkeleton(vpTutoCommonData &data)
56{
57 const int height = data.m_mask.getHeight();
58 const int width = data.m_mask.getWidth();
59 data.m_Iskeleton.resize(height, width, 0);
60 std::vector<vpImagePoint> points;
61 // Edge thinning along the horizontal direction
62 for (int y = 0; y < height; ++y) {
63 int left = -1;
64 for (int x = 0; x < width - 1; ++x) {
65 if ((data.m_mask[y][x] > 0) && (data.m_mask[y][x + 1] > 0)) {
66 if (left < 0) {
67 left = x;
68 }
69 }
70 else if (data.m_mask[y][x] > 0) {
71 int cx = x; // Case 1 pix wide
72 if (left >= 0) {
73 // Case more than 1 pix wide
74 cx = static_cast<int>(((left + x) - 1) * 0.5f);
75 }
76 vpImagePoint pt(y, cx);
77 points.push_back(pt);
78 data.m_Iskeleton[y][cx] = 255;
79 left = -1;
80 }
81 }
82 }
83
84 // Edge thinning along the vertical direction
85 for (int x = 0; x < width; ++x) {
86 int top = -1;
87 for (int y = 0; y < height - 1; ++y) {
88 if ((data.m_mask[y][x] > 0) && (data.m_mask[y + 1][x] > 0)) {
89 if (top < 0) {
90 top = y;
91 }
92 }
93 else if (data.m_mask[y][x] > 0) {
94 int cy = y; // Case 1 pix wide
95 if (top >= 0) {
96 cy = static_cast<int>(((top + y) - 1) * 0.5f); // Case more than 1 pix wide
97 }
98 if (data.m_Iskeleton[cy][x] == 0) {
99 vpImagePoint pt(cy, x);
100 points.push_back(pt);
101 data.m_Iskeleton[cy][x] = 255;
102 }
103 top = -1;
104 }
105 }
106 }
107 return points;
108}
109
110std::vector< vpImagePoint > addSaltAndPepperNoise(const std::vector< vpImagePoint > &noisefreePts, vpTutoCommonData &data)
111{
112 const unsigned int nbNoiseFreePts = static_cast<unsigned int>(noisefreePts.size());
113 const unsigned int nbPtsToAdd = static_cast<unsigned int>(data.m_ratioSaltPepperNoise * nbNoiseFreePts);
114 const double width = data.m_Iskeleton.getWidth();
115 const double height = data.m_Iskeleton.getHeight();
116 data.m_IskeletonNoisy = data.m_Iskeleton;
117 vpGaussRand rngX(0.1666, 0.5, static_cast<long>(vpTime::measureTimeMicros()));
118 vpGaussRand rngY(0.1666, 0.5, static_cast<long>(vpTime::measureTimeMicros() + 4224));
119 std::vector<vpImagePoint> noisyPts = noisefreePts;
120 for (unsigned int i = 0; i < nbPtsToAdd + 1; ++i) {
121 double uNormalized = rngX();
122 double vNormalized = rngY();
123 // Clamp to interval[0, 1[
124 uNormalized = std::max(uNormalized, 0.);
125 uNormalized = std::min(uNormalized, 0.99999);
126 vNormalized = std::max(vNormalized, 0.);
127 vNormalized = std::min(vNormalized, 0.99999);
128 // Scale to image size
129 double u = uNormalized * width;
130 double v = vNormalized * height;
131 // Create corresponding image point
132 vpImagePoint pt(v, u);
133 noisyPts.push_back(pt);
134 data.m_IskeletonNoisy[static_cast<int>(v)][static_cast<int>(u)] = 255;
135 }
136 return noisyPts;
137}
138}
139#endif
140#else
141void dummy_vpTutoSegmentation() { }
142#endif
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
static int inMask(const vpImage< vpRGBa > &I, const vpImage< bool > &mask, vpImage< vpRGBa > &I_mask)
static int inRange(const unsigned char *hue, const unsigned char *saturation, const unsigned char *value, const vpColVector &hsv_range, unsigned char *mask, unsigned int size)
VISP_EXPORT double measureTimeMicros()