Visual Servoing Platform version 3.7.0
Loading...
Searching...
No Matches
tutorial-canny-hsv.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
32
33#include <visp3/core/vpConfig.h>
34
35#include <visp3/core/vpCannyEdgeDetection.h>
36#include <visp3/core/vpHSV.h>
37#include <visp3/core/vpImageConvert.h>
38#include <visp3/core/vpImageFilter.h>
39#include <visp3/core/vpIoTools.h>
40#include <visp3/core/vpRGBa.h>
41#include <visp3/gui/vpDisplayFactory.h>
42#include <visp3/io/vpImageIo.h>
43
44#ifdef ENABLE_VISP_NAMESPACE
45using namespace VISP_NAMESPACE_NAME;
46#endif
47
48#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_11)
49template <typename FilterType>
50void computeAbsoluteGradient(const vpImage<FilterType> &GIx, const vpImage<FilterType> &GIy, vpImage<FilterType> &GI, FilterType &min, FilterType &max)
51{
52 const unsigned int h = GIx.getHeight(), w = GIx.getWidth();
53 GI.resize(h, w);
54 max = -1.;
55 min = std::numeric_limits<FilterType>::max();
56 for (unsigned int r = 0; r < h; ++r) {
57 for (unsigned int c = 0; c < w; ++c) {
58 GI[r][c] = std::abs(GIx[r][c]) + std::abs(GIy[r][c]);
59 max = std::max(max, GI[r][c]);
60 min = std::min(min, GI[r][c]);
61 }
62 }
63}
64
65template<typename FilterType>
66vpImage<unsigned char> convertToDisplay(const vpImage<FilterType> &GI, const FilterType &min, const FilterType &max)
67{
68 const unsigned int h = GI.getHeight(), w = GI.getWidth();
69 const FilterType range = max - min;
70 const FilterType step = range / static_cast<FilterType>(256);
72 for (unsigned int r = 0; r < h; ++r) {
73 for (unsigned int c = 0; c < w; ++c) {
74 Idisp[r][c] = static_cast<unsigned char>(std::floor((GI[r][c] - min) / step));
75 }
76 }
77 return Idisp;
78}
79
80typedef struct SoftwareArguments
81{
82 std::string m_img;
91 bool m_useDisplay;
92 bool m_useMask;
94
96 : m_img("")
98 , m_gaussianStdev(1.)
99 , m_lowerThresh(-1.)
100 , m_upperThresh(-1.)
101 , m_lowerThreshRatio(0.6f)
102 , m_upperThreshRatio(0.8f)
103 , m_filteringType(vpImageFilter::CANNY_GBLUR_SCHARR_FILTERING)
104 , m_saveImages(false)
105#ifdef VISP_HAVE_DISPLAY
106 , m_useDisplay(true)
107#else
108 , m_useDisplay(false)
109#endif
110 , m_useMask(false)
111 , m_nbThread(-1)
112 { }
114
115void usage(const std::string &softName, const SoftwareArguments &options)
116{
117 std::cout << "NAME" << std::endl;
118 std::cout << softName << ": software to test the vpCannyEdgeComputation class and vpImageFilter::canny method" << std::endl;
119 std::cout << "SYNOPSIS" << std::endl;
120 std::cout << "\t" << softName
121 << " [-i, --image <pathToImg>]"
122 << " [-g, --gradient <kernelSize stdev>]"
123 << " [-t, --thresh <lowerThresh upperThresh>]"
124 << " [-f, --filter " << vpImageFilter::vpGetCannyFiltAndGradTypes("<", " | ", ">") << "]"
125 << " [-r, --ratio <lowerThreshRatio upperThreshRatio>]"
126 << " [-n, --nb-threads <number of threads>]"
127 << " [-s, --save]" << std::endl
128 << " [-d, --no-display]" << std::endl
129 << " [-m, --use-mask]" << std::endl
130 << " [-h, --help]" << std::endl
131 << std::endl;
132 std::cout << "DESCRIPTION" << std::endl;
133 std::cout << "\t-i, --image <pathToImg>" << std::endl
134 << "\t\tPermits to load an image on which will be tested the vpCanny class." << std::endl
135 << "\t\tWhen empty uses a simulated image." << std::endl
136 << std::endl;
137 std::cout << "\t-g, --gradient <kernelSize stdev>" << std::endl
138 << "\t\tPermits to compute the gradients of the image outside the vpCanny class." << std::endl
139 << "\t\tFirst parameter is the size of the Gaussian kernel used to compute the gradients." << std::endl
140 << "\t\tSecond parameter is the standard deviation of the Gaussian kernel used to compute the gradients." << std::endl
141 << "\t\tDefault: " << options.m_gaussianKernelSize << " " << options.m_gaussianStdev << std::endl
142 << std::endl;
143 std::cout << "\t-t, --thresh <lowerThresh upperThresh>" << std::endl
144 << "\t\tPermits to set the lower and upper thresholds of the vpCanny class." << std::endl
145 << "\t\tFirst parameter is the lower threshold." << std::endl
146 << "\t\tSecond parameter is the upper threshold." << std::endl
147 << "\t\tWhen set to -1 thresholds are computed automatically." << std::endl
148 << "\t\tDefault: " << options.m_lowerThresh << " " << options.m_upperThresh << std::endl
149 << std::endl;
150 std::cout << "\t-r, --ratio <lowerThreshRatio upperThreshRatio>" << std::endl
151 << "\t\tPermits to set the lower and upper thresholds ratio of the vpCanny class." << std::endl
152 << "\t\tFirst parameter is the lower threshold ratio." << std::endl
153 << "\t\tSecond parameter is the upper threshold ratio." << std::endl
154 << "\t\tDefault: " << options.m_lowerThreshRatio << " " << options.m_upperThreshRatio << std::endl
155 << std::endl;
156 std::cout << "\t-f, --filter <filterName>" << std::endl
157 << "\t\tPermits to choose the type of filter to apply to compute the gradient." << std::endl
158 << "\t\tAvailable values: " << vpImageFilter::vpGetCannyFiltAndGradTypes("<", " | ", ">") << std::endl
159 << "\t\tDefault: " << vpImageFilter::vpCannyFiltAndGradTypeToStr(options.m_filteringType) << std::endl
160 << std::endl;
161 std::cout << "\t-n, --nb-threads <number of threads>" << std::endl
162 << "\t\tPermits to choose the number of threads to use for the Canny." << std::endl
163 << "\t\tUse -1 to automatically choose the highest possible number of threads." << std::endl
164 << "\t\tDefault: " << options.m_nbThread << std::endl
165 << std::endl;
166 std::cout << "\t-s, --save" << std::endl
167 << "\t\tPermits to save the different images." << std::endl
168 << std::endl;
169 std::cout << " -d, --no-display" << std::endl
170 << " Deactivate display." << std::endl
171 << " Default: display is "
172#ifdef VISP_HAVE_DISPLAY
173 << "ON" << std::endl
174#else
175 << "OFF" << std::endl
176#endif
177 << std::endl;
178 std::cout << " -m, --use-mask" << std::endl
179 << " If true, use a predifined boolean mask that determines which pixels should be considered and which should be ignored" << std::endl
180 << std::endl;
181 std::cout << "\t-h, --help" << std::endl
182 << "\t\tPermits to display the different arguments this software handles." << std::endl
183 << std::endl;
184}
185
186int main(int argc, const char *argv[])
187{
188 SoftwareArguments options;
189 for (int i = 1; i < argc; i++) {
190 std::string argv_str = std::string(argv[i]);
191 if ((argv_str == "-i" || argv_str == "--image") && i + 1 < argc) {
192 options.m_img = std::string(argv[i + 1]);
193 i++;
194 }
195 else if ((argv_str == "-g" || argv_str == "--gradient") && i + 2 < argc) {
196 options.m_gaussianKernelSize = atoi(argv[i + 1]);
197 options.m_gaussianStdev = static_cast<float>(atof(argv[i + 2]));
198 i += 2;
199 }
200 else if ((argv_str == "-t" || argv_str == "--thresh") && i + 2 < argc) {
201 options.m_lowerThresh = static_cast<float>(atof(argv[i + 1]));
202 options.m_upperThresh = static_cast<float>(atof(argv[i + 2]));
203 i += 2;
204 }
205 else if ((argv_str == "-r" || argv_str == "--ratio") && i + 2 < argc) {
206 options.m_lowerThreshRatio = static_cast<float>(std::atof(argv[i + 1]));
207 options.m_upperThreshRatio = static_cast<float>(std::atof(argv[i + 2]));
208 i += 2;
209 }
210 else if ((argv_str == "-f" || argv_str == "--filter") && i + 1 < argc) {
211 options.m_filteringType = vpImageFilter::vpCannyFiltAndGradTypeFromStr(std::string(argv[i + 1]));
212 i++;
213 }
214 else if ((argv_str == "-n" || argv_str == "--nb-threads") && i + 1 < argc) {
215 options.m_nbThread = std::atoi(argv[i + 1]);
216 i++;
217 }
218 else if (argv_str == "-s" || argv_str == "--save") {
219 options.m_saveImages = true;
220 }
221 else if (argv_str == "-d" || argv_str == "--no-display") {
222 options.m_useDisplay = false;
223 }
224 else if (argv_str == "-m" || argv_str == "--use-mask") {
225 options.m_useMask = true;
226 }
227 else if (argv_str == "-h" || argv_str == "--help") {
228 usage(std::string(argv[0]), SoftwareArguments());
229 return EXIT_SUCCESS;
230 }
231 else {
232 std::cerr << "Argument \"" << argv_str << "\" is unknown." << std::endl;
233 return EXIT_FAILURE;
234 }
235 }
236
237 std::string configAsTxt("Canny Configuration:\n");
238 configAsTxt += "\tFiltering + gradient operators = " + vpImageFilter::vpCannyFiltAndGradTypeToStr(options.m_filteringType) + "\n";
239 configAsTxt += "\tGaussian filter kernel size = " + std::to_string(options.m_gaussianKernelSize) + "\n";
240 configAsTxt += "\tGaussian filter standard deviation = " + std::to_string(options.m_gaussianStdev) + "\n";
241 configAsTxt += "\tCanny edge filter thresholds = [" + std::to_string(options.m_lowerThresh) + " ; " + std::to_string(options.m_upperThresh) + "]\n";
242 configAsTxt += "\tCanny edge filter thresholds ratio (for auto-thresholding) = [" + std::to_string(options.m_lowerThreshRatio) + " ; " + std::to_string(options.m_upperThreshRatio) + "]\n";
243 configAsTxt += "\tCanny edge filter nb threads = " + (options.m_nbThread > 0 ? std::to_string(options.m_nbThread) : std::string("auto")) + "\n";
244 std::cout << configAsTxt << std::endl;
245
246 unsigned int uselessAperture = 3;
247 vpCannyEdgeDetection cannyDetector(options.m_gaussianKernelSize, options.m_gaussianStdev, uselessAperture,
248 options.m_lowerThresh, options.m_upperThresh, options.m_lowerThreshRatio, options.m_upperThreshRatio, options.m_filteringType);
249 vpImage<vpRGBa> Iload;
251 vpImage<vpHSV<double>> Iin_hsvd;
252 if (!options.m_img.empty()) {
253 // Detection on the user image
254 vpImageIo::read(Iload, options.m_img);
255 }
256 else {
257 std::cout << "This example only works on a real image. Please use the -i option." << std::endl;
258 return EXIT_SUCCESS;
259 }
260
261 vpImage<bool> mask(Iload.getRows(), Iload.getCols(), false);
262 int height = Iload.getRows()/4;
263 int width = Iload.getCols()/4;
264 int midHeight = Iload.getRows()/2;
265 int midWidth = Iload.getCols()/2;
266 for (int r = 0; r < height; ++r) {
267 for (int c = 0; c < width; ++c) {
268 mask[midHeight - r][midWidth - c] = true;
269 mask[midHeight + r][midWidth - c] = true;
270 mask[midHeight - r][midWidth + c] = true;
271 mask[midHeight + r][midWidth + c] = true;
272 }
273 }
274
275 vpImage<bool> *p_mask = (options.m_useMask ? &mask : nullptr);
276 cannyDetector.setMask(p_mask);
277 cannyDetector.setNbThread(options.m_nbThread);
278
279 double tStartHSVuc = vpTime::measureTimeMicros();
280 vpImageConvert::convert(Iload, Iin_hsvuc);
281 vpImage<unsigned char> I_canny_hsvuc = cannyDetector.detect(Iin_hsvuc);
282 double tEndHSVuc = vpTime::measureTimeMicros();
283 std::cout << "Time to convert RGBa into HSV uchar + compute the edge-map: " << (tEndHSVuc - tStartHSVuc) / 1000. << " ms" << std::endl;
284
285 double tStartHSVd = vpTime::measureTimeMicros();
286 vpImageConvert::convert(Iload, Iin_hsvd);
287 cannyDetector.reinit();
288 cannyDetector.setMask(p_mask);
289 vpImage<unsigned char> I_canny_hsvd = cannyDetector.detect(Iin_hsvd);
290 double tEndHSVd = vpTime::measureTimeMicros();
291 std::cout << "Time to convert RGBa into HSV double + compute the edge-map: " << (tEndHSVd - tStartHSVd) / 1000. << " ms" << std::endl;
292
293 vpCannyEdgeDetection cannyDetectorUC(options.m_gaussianKernelSize, options.m_gaussianStdev, uselessAperture,
294 options.m_lowerThresh, options.m_upperThresh, options.m_lowerThreshRatio, options.m_upperThreshRatio);
295 cannyDetectorUC.setMask(p_mask);
296 cannyDetectorUC.setNbThread(options.m_nbThread);
297 vpImage<unsigned char> Iin_convert;
298 double tStartChar = vpTime::measureTimeMicros();
299 vpImageConvert::convert(Iload, Iin_convert);
300 vpImage<unsigned char> I_canny_uc = cannyDetectorUC.detect(Iin_convert);
301 double tEndChar = vpTime::measureTimeMicros();
302 std::cout << "Time to convert RGBa into uchar + compute the edge-map for RGBa: " << (tEndChar - tStartChar) / 1000. << " ms" << std::endl;
303
304 // Initialization of the displays
305 using FilterType = float;
306 vpImage<FilterType> GIx, GIy, GI;
308 double tStartBlurHSVUC = vpTime::measureTimeMicros();
309 vpImageFilter::gaussianBlur(Iin_hsvuc, Iblur_hsvuc, options.m_gaussianKernelSize, options.m_gaussianStdev, true, p_mask);
310 double tEndBlurHSVUC = vpTime::measureTimeMicros();
311
312 double tStartGradientHSVUC = vpTime::measureTimeMicros();
313 vpImageFilter::gradientFilter(Iblur_hsvuc, GIx, GIy, options.m_nbThread, p_mask, options.m_filteringType);
314 double tEndGradientHSVUC = vpTime::measureTimeMicros();
315 FilterType min = 0., max = 0.;
316 computeAbsoluteGradient(GIx, GIy, GI, min, max);
317 vpImage<unsigned char> GIdisp_hsvuc_imgfilter = convertToDisplay(GI, min, max);
318
320 double tStartBlurHSVd = vpTime::measureTimeMicros();
321 vpImageFilter::gaussianBlur(Iin_hsvd, Iblur_hsvd, options.m_gaussianKernelSize, options.m_gaussianStdev, true, p_mask);
322 double tEndBlurHSVd = vpTime::measureTimeMicros();
323 double tStartGradientHSVd = vpTime::measureTimeMicros();
324 vpImageFilter::gradientFilter(Iblur_hsvd, GIx, GIy, options.m_nbThread, p_mask, options.m_filteringType);
325 double tEndGradientHSVd = vpTime::measureTimeMicros();
326 computeAbsoluteGradient(GIx, GIy, GI, min, max);
327 vpImage<unsigned char> GIdisp_hsvd_imgfilter = convertToDisplay(GI, min, max);
328
329 vpImage<FilterType> IblurUC, GIx_uc, GIy_uc, GI_uc;
330 double tStartBlurUC = vpTime::measureTimeMicros();
331 vpImageFilter::gaussianBlur(Iin_convert, IblurUC, options.m_gaussianKernelSize, (FilterType)options.m_gaussianStdev, true, p_mask);
332 double tEndBlurUC = vpTime::measureTimeMicros();
333 vpArray2D<FilterType> derFilterX(3, 3), derFilterY(3, 3);
334 FilterType scaleX, scaleY;
335 switch (options.m_filteringType) {
337 scaleX = vpImageFilter::getScharrKernelX(derFilterX.data, 1);
338 scaleY = vpImageFilter::getScharrKernelY(derFilterY.data, 1);
339 break;
341 scaleX = vpImageFilter::getSobelKernelX(derFilterX.data, 1);
342 scaleY = vpImageFilter::getSobelKernelY(derFilterY.data, 1);
343 break;
344 default:
345 throw vpException(vpException::notImplementedError, "Other type of filter not handled for uchar");
346 }
347 auto scaleFilter = [](vpArray2D<FilterType> &array, const FilterType &scale) {
348 for (unsigned int r = 0; r < array.getRows(); ++r) {
349 for (unsigned int c = 0; c < array.getCols(); ++c) {
350 array[r][c] = array[r][c] / scale;
351 }
352 }
353 };
354 scaleFilter(derFilterX, scaleX);
355 scaleFilter(derFilterY, scaleY);
356 // Computing the gradients
357 double tStartGradientUC = vpTime::measureTimeMicros();
358 vpImageFilter::filter(IblurUC, GIx_uc, derFilterX, true, p_mask);
359 vpImageFilter::filter(IblurUC, GIy_uc, derFilterY, true, p_mask);
360 double tEndGradientUC = vpTime::measureTimeMicros();
361 computeAbsoluteGradient(GIx_uc, GIy_uc, GI_uc, min, max);
362 vpImage<unsigned char> GIdisp_uc = convertToDisplay(GI_uc, min, max);
363
364 std::cout << "[vpHSV<uchar>]" << std::endl;
365 std::cout <<"\tgblur = " << (tEndBlurHSVUC - tStartBlurHSVUC) / 1000. << std::endl;
366 std::cout <<"\tgrad = " << (tEndGradientHSVUC - tStartGradientHSVUC) / 1000. << std::endl;
367 std::cout << std::endl;
368
369 std::cout << "[vpHSV<double>]" << std::endl;
370 std::cout <<"\tgblur = " << (tEndBlurHSVd - tStartBlurHSVd) / 1000. << std::endl;
371 std::cout <<"\tgrad = " << (tEndGradientHSVd - tStartGradientHSVd) / 1000. << std::endl;
372 std::cout << std::endl;
373
374 std::cout << "[uchar]" << std::endl;
375 std::cout <<"\tgblur = " << (tEndBlurUC - tStartBlurUC) / 1000. << std::endl;
376 std::cout <<"\tgrad = " << (tEndGradientUC - tStartGradientUC) / 1000. << std::endl;
377 std::cout << std::endl;
378
379#ifdef VISP_HAVE_DISPLAY
380 if (options.m_useDisplay) {
381 std::shared_ptr<vpDisplay> disp_input = vpDisplayFactory::createDisplay(Iload, -1, -1, "Input color image", vpDisplay::SCALE_AUTO);
382 int posX = disp_input->getWidth() + 20;
383 int posY = disp_input->getHeight() + 20;
384 std::shared_ptr<vpDisplay> disp_canny = vpDisplayFactory::createDisplay(I_canny_hsvuc, posX, -1, "HSV UC Canny", vpDisplay::SCALE_AUTO);
385 std::shared_ptr<vpDisplay> disp_input_uc = vpDisplayFactory::createDisplay(Iin_convert, -1, posY, "Input converted image", vpDisplay::SCALE_AUTO);
386 std::shared_ptr<vpDisplay> disp_canny_uc = vpDisplayFactory::createDisplay(I_canny_uc, posX, posY, "UC Canny", vpDisplay::SCALE_AUTO);
387
388 std::shared_ptr<vpDisplay> disp_GI_hsvuc_imgfilter = vpDisplayFactory::createDisplay(GIdisp_hsvuc_imgfilter, 2 * posX, -1, "Gradient HSV");
389 vpDisplay::display(GIdisp_hsvuc_imgfilter);
390 vpDisplay::flush(GIdisp_hsvuc_imgfilter);
391
392 std::shared_ptr<vpDisplay> disp_GI_uc = vpDisplayFactory::createDisplay(GIdisp_uc, 2 * posX, posY, "Gradient (unsigned char)");
393 vpDisplay::display(GIdisp_uc);
394 vpDisplay::flush(GIdisp_uc);
395
396 vpDisplay::display(Iin_convert);
397 vpDisplay::flush(Iin_convert);
398 vpDisplay::display(I_canny_uc);
399 vpDisplay::flush(I_canny_uc);
400 vpDisplay::display(I_canny_hsvuc);
401 vpDisplay::flush(I_canny_hsvuc);
402
403 vpDisplay::display(Iload);
404 vpDisplay::displayText(Iload, vpImagePoint(20, 20), "Click to leave.", vpColor::red);
405 vpDisplay::flush(Iload);
406 vpDisplay::getClick(Iload);
407 }
408#else
409 options.m_saveImages = true;
410#endif
411 if (options.m_saveImages) {
412 std::string basename = vpIoTools::getNameWE(options.m_img);
413 vpImageIo::write(I_canny_hsvuc, "Canny_HSVUC_" + basename + ".jpg");
414 vpImageIo::write(I_canny_hsvd, "Canny_HSVD_" + basename + ".jpg");
415 vpImageIo::write(I_canny_uc, "Canny_UC_" + basename + ".jpg");
416 vpImageIo::write(GIdisp_hsvuc_imgfilter, "Gradient_HSVUC_" + basename + ".jpg");
417 vpImageIo::write(GIdisp_hsvd_imgfilter, "Gradient_HSVD_" + basename + ".jpg");
418 vpImageIo::write(GIdisp_uc, "Gradient_UC_" + basename + ".jpg");
419 }
420 return EXIT_SUCCESS;
421}
422#else
423int main()
424{
425 std::cout << "C++11 is needed to work with vpHSV." << std::endl;
426 return EXIT_SUCCESS;
427}
428#endif
Implementation of a generic 2D array used as base class for matrices and vectors.
Definition vpArray2D.h:146
unsigned int getCols() const
Definition vpArray2D.h:423
unsigned int getRows() const
Definition vpArray2D.h:433
Class that implements the Canny's edge detector. It is possible to use a boolean mask to ignore some ...
static const vpColor red
Definition vpColor.h:198
static bool getClick(const vpImage< unsigned char > &I, bool blocking=true)
static void display(const vpImage< unsigned char > &I)
static void flush(const vpImage< unsigned char > &I)
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.
Definition vpException.h:60
@ notImplementedError
Not implemented.
Definition vpException.h:69
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
Various image filter, convolution, etc...
static FilterType getSobelKernelX(FilterType *filter, unsigned int size)
static std::string vpCannyFiltAndGradTypeToStr(const vpCannyFilteringAndGradientType &type)
Cast a vpImageFilter::vpCannyFilteringAndGradientType into a string, to know its name.
static void gradientFilter(const vpImage< vpHSV< ArithmeticType, useFullScale > > &I, vpImage< FilterType > &GIx, vpImage< FilterType > &GIy, const int &nbThread=-1, const vpImage< bool > *p_mask=nullptr, const vpImageFilter::vpCannyFilteringAndGradientType &type=CANNY_GBLUR_SCHARR_FILTERING)
Compute the horizontal and vertical gradients for HSV images.
vpCannyFilteringAndGradientType
Canny filter and gradient operators to apply on the image before the edge detection stage.
@ CANNY_GBLUR_SOBEL_FILTERING
Apply Gaussian blur + Sobel operator on the input image.
@ CANNY_GBLUR_SCHARR_FILTERING
Apply Gaussian blur + Scharr operator on the input image.
static void filter(const vpImage< ImageType > &I, vpImage< FilterType > &If, const vpArray2D< FilterType > &M, bool convolve=false, const vpImage< bool > *p_mask=nullptr)
static void gaussianBlur(const vpImage< ImageType > &I, vpImage< OutputType > &GI, unsigned int size=7, FilterType sigma=0., bool normalize=true, const vpImage< bool > *p_mask=nullptr)
static vpCannyFilteringAndGradientType vpCannyFiltAndGradTypeFromStr(const std::string &name)
Cast a string into a vpImageFilter::vpCannyFilteringAndGradientType.
static FilterType getScharrKernelY(FilterType *filter, unsigned int size)
static FilterType getSobelKernelY(FilterType *filter, unsigned int size)
static FilterType getScharrKernelX(FilterType *filter, unsigned int size)
static std::string vpGetCannyFiltAndGradTypes(const std::string &pref="<", const std::string &sep=" , ", const std::string &suf=">")
Get the list of available vpCannyFilteringAndGradientType.
static void read(vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
static void write(const vpImage< unsigned char > &I, const std::string &filename, int backend=IO_DEFAULT_BACKEND)
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.
Definition vpImage.h:131
unsigned int getWidth() const
Definition vpImage.h:242
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
Definition vpImage.h:544
unsigned int getCols() const
Definition vpImage.h:171
unsigned int getHeight() const
Definition vpImage.h:181
unsigned int getRows() const
Definition vpImage.h:212
static std::string getNameWE(const std::string &pathname)
std::shared_ptr< vpDisplay > createDisplay()
Return a smart pointer vpDisplay specialization if a GUI library is available or nullptr otherwise.
VISP_EXPORT double measureTimeMicros()
bool m_useDisplay
If true, activate the plot and the renderer if VISP_HAVE_DISPLAY is defined.
vpImageFilter::vpCannyFilteringAndGradientType m_filteringType
bool m_useMask
If true, use a predifined boolean mask that determines which pixels should be considered and which sh...