#include <visp3/core/vpConfig.h>
#include <visp3/core/vpCannyEdgeDetection.h>
#include <visp3/core/vpHSV.h>
#include <visp3/core/vpImageConvert.h>
#include <visp3/core/vpImageFilter.h>
#include <visp3/core/vpIoTools.h>
#include <visp3/core/vpRGBa.h>
#include <visp3/gui/vpDisplayFactory.h>
#include <visp3/io/vpImageIo.h>
#ifdef ENABLE_VISP_NAMESPACE
#endif
#if (VISP_CXX_STANDARD > VISP_CXX_STANDARD_11)
template <typename FilterType>
{
max = -1.;
min = std::numeric_limits<FilterType>::max();
for (unsigned int r = 0; r < h; ++r) {
for (unsigned int c = 0; c < w; ++c) {
GI[r][c] = std::abs(GIx[r][c]) + std::abs(GIy[r][c]);
max = std::max(max, GI[r][c]);
min = std::min(min, GI[r][c]);
}
}
}
template<typename FilterType>
{
const FilterType range = max - min;
const FilterType step = range / static_cast<FilterType>(256);
for (unsigned int r = 0; r < h; ++r) {
for (unsigned int c = 0; c < w; ++c) {
Idisp[r][c] = static_cast<unsigned char>(std::floor((GI[r][c] - min) / step));
}
}
}
{
#ifdef VISP_HAVE_DISPLAY
#else
#endif
{ }
{
std::cout << "NAME" << std::endl;
std::cout << softName << ": software to test the vpCannyEdgeComputation class and vpImageFilter::canny method" << std::endl;
std::cout << "SYNOPSIS" << std::endl;
std::cout << "\t" << softName
<< " [-i, --image <pathToImg>]"
<< " [-g, --gradient <kernelSize stdev>]"
<< " [-t, --thresh <lowerThresh upperThresh>]"
<< " [-r, --ratio <lowerThreshRatio upperThreshRatio>]"
<< " [-n, --nb-threads <number of threads>]"
<< " [-s, --save]" << std::endl
<< " [-d, --no-display]" << std::endl
<< " [-m, --use-mask]" << std::endl
<< " [-h, --help]" << std::endl
<< std::endl;
std::cout << "DESCRIPTION" << std::endl;
std::cout << "\t-i, --image <pathToImg>" << std::endl
<< "\t\tPermits to load an image on which will be tested the vpCanny class." << std::endl
<< "\t\tWhen empty uses a simulated image." << std::endl
<< std::endl;
std::cout << "\t-g, --gradient <kernelSize stdev>" << std::endl
<< "\t\tPermits to compute the gradients of the image outside the vpCanny class." << std::endl
<< "\t\tFirst parameter is the size of the Gaussian kernel used to compute the gradients." << std::endl
<< "\t\tSecond parameter is the standard deviation of the Gaussian kernel used to compute the gradients." << std::endl
<< std::endl;
std::cout << "\t-t, --thresh <lowerThresh upperThresh>" << std::endl
<< "\t\tPermits to set the lower and upper thresholds of the vpCanny class." << std::endl
<< "\t\tFirst parameter is the lower threshold." << std::endl
<< "\t\tSecond parameter is the upper threshold." << std::endl
<< "\t\tWhen set to -1 thresholds are computed automatically." << std::endl
<< std::endl;
std::cout << "\t-r, --ratio <lowerThreshRatio upperThreshRatio>" << std::endl
<< "\t\tPermits to set the lower and upper thresholds ratio of the vpCanny class." << std::endl
<< "\t\tFirst parameter is the lower threshold ratio." << std::endl
<< "\t\tSecond parameter is the upper threshold ratio." << std::endl
<< std::endl;
std::cout << "\t-f, --filter <filterName>" << std::endl
<< "\t\tPermits to choose the type of filter to apply to compute the gradient." << std::endl
<< std::endl;
std::cout << "\t-n, --nb-threads <number of threads>" << std::endl
<< "\t\tPermits to choose the number of threads to use for the Canny." << std::endl
<< "\t\tUse -1 to automatically choose the highest possible number of threads." << std::endl
<<
"\t\tDefault: " << options.
m_nbThread << std::endl
<< std::endl;
std::cout << "\t-s, --save" << std::endl
<< "\t\tPermits to save the different images." << std::endl
<< std::endl;
std::cout << " -d, --no-display" << std::endl
<< " Deactivate display." << std::endl
<< " Default: display is "
#ifdef VISP_HAVE_DISPLAY
<< "ON" << std::endl
#else
<< "OFF" << std::endl
#endif
<< std::endl;
std::cout << " -m, --use-mask" << std::endl
<< " If true, use a predifined boolean mask that determines which pixels should be considered and which should be ignored" << std::endl
<< std::endl;
std::cout << "\t-h, --help" << std::endl
<< "\t\tPermits to display the different arguments this software handles." << std::endl
<< std::endl;
}
int main(int argc, const char *argv[])
{
for (
int i = 1;
i < argc;
i++) {
std::string argv_str = std::string(argv[i]);
if ((argv_str == "-i" || argv_str == "--image") && i + 1 < argc) {
options.
m_img = std::string(argv[i + 1]);
}
else if ((argv_str == "-g" || argv_str == "--gradient") && i + 2 < argc) {
}
else if ((argv_str == "-t" || argv_str == "--thresh") && i + 2 < argc) {
}
else if ((argv_str == "-r" || argv_str == "--ratio") && i + 2 < argc) {
}
else if ((argv_str == "-f" || argv_str == "--filter") && i + 1 < argc) {
}
else if ((argv_str == "-n" || argv_str == "--nb-threads") && i + 1 < argc) {
}
else if (argv_str == "-s" || argv_str == "--save") {
}
else if (argv_str == "-d" || argv_str == "--no-display") {
}
else if (argv_str == "-m" || argv_str == "--use-mask") {
}
else if (argv_str == "-h" || argv_str == "--help") {
return EXIT_SUCCESS;
}
else {
std::cerr << "Argument \"" << argv_str << "\" is unknown." << std::endl;
return EXIT_FAILURE;
}
}
std::string configAsTxt("Canny Configuration:\n");
configAsTxt +=
"\tGaussian filter kernel size = " + std::to_string(options.
m_gaussianKernelSize) +
"\n";
configAsTxt +=
"\tGaussian filter standard deviation = " + std::to_string(options.
m_gaussianStdev) +
"\n";
configAsTxt +=
"\tCanny edge filter thresholds = [" + std::to_string(options.
m_lowerThresh) +
" ; " + std::to_string(options.
m_upperThresh) +
"]\n";
configAsTxt +=
"\tCanny edge filter thresholds ratio (for auto-thresholding) = [" + std::to_string(options.
m_lowerThreshRatio) +
" ; " + std::to_string(options.
m_upperThreshRatio) +
"]\n";
configAsTxt +=
"\tCanny edge filter nb threads = " + (options.
m_nbThread > 0 ? std::to_string(options.
m_nbThread) : std::string(
"auto")) +
"\n";
std::cout << configAsTxt << std::endl;
unsigned int uselessAperture = 3;
if (!options.
m_img.empty()) {
}
else {
std::cout << "This example only works on a real image. Please use the -i option." << std::endl;
return EXIT_SUCCESS;
}
for (
int c = 0; c <
width; ++c) {
mask[midHeight -
r][midWidth - c] =
true;
mask[midHeight +
r][midWidth - c] =
true;
mask[midHeight -
r][midWidth + c] =
true;
mask[midHeight +
r][midWidth + c] =
true;
}
}
cannyDetector.setMask(p_mask);
std::cout << "Time to convert RGBa into HSV uchar + compute the edge-map: " << (tEndHSVuc - tStartHSVuc) / 1000. << " ms" << std::endl;
cannyDetector.reinit();
cannyDetector.setMask(p_mask);
std::cout << "Time to convert RGBa into HSV double + compute the edge-map: " << (tEndHSVd - tStartHSVd) / 1000. << " ms" << std::endl;
cannyDetectorUC.setMask(p_mask);
std::cout << "Time to convert RGBa into uchar + compute the edge-map for RGBa: " << (tEndChar - tStartChar) / 1000. << " ms" << std::endl;
using FilterType = float;
FilterType min = 0., max = 0.;
computeAbsoluteGradient(GIx, GIy, GI, min, max);
computeAbsoluteGradient(GIx, GIy, GI, min, max);
FilterType scaleX, scaleY;
break;
break;
default:
}
for (
unsigned int r = 0;
r < array.
getRows(); ++
r) {
for (
unsigned int c = 0; c < array.
getCols(); ++c) {
array[
r][c] = array[
r][c] / scale;
}
}
};
scaleFilter(derFilterX, scaleX);
scaleFilter(derFilterY, scaleY);
computeAbsoluteGradient(GIx_uc, GIy_uc, GI_uc, min, max);
std::cout << "[vpHSV<uchar>]" << std::endl;
std::cout <<"\tgblur = " << (tEndBlurHSVUC - tStartBlurHSVUC) / 1000. << std::endl;
std::cout <<"\tgrad = " << (tEndGradientHSVUC - tStartGradientHSVUC) / 1000. << std::endl;
std::cout << std::endl;
std::cout << "[vpHSV<double>]" << std::endl;
std::cout <<"\tgblur = " << (tEndBlurHSVd - tStartBlurHSVd) / 1000. << std::endl;
std::cout <<"\tgrad = " << (tEndGradientHSVd - tStartGradientHSVd) / 1000. << std::endl;
std::cout << std::endl;
std::cout << "[uchar]" << std::endl;
std::cout <<"\tgblur = " << (tEndBlurUC - tStartBlurUC) / 1000. << std::endl;
std::cout <<"\tgrad = " << (tEndGradientUC - tStartGradientUC) / 1000. << std::endl;
std::cout << std::endl;
#ifdef VISP_HAVE_DISPLAY
int posX = disp_input->getWidth() + 20;
int posY = disp_input->getHeight() + 20;
}
#else
#endif
vpImageIo::write(GIdisp_hsvuc_imgfilter,
"Gradient_HSVUC_" + basename +
".jpg");
}
return EXIT_SUCCESS;
}
#else
int main()
{
std::cout << "C++11 is needed to work with vpHSV." << std::endl;
return EXIT_SUCCESS;
}
#endif
Implementation of a generic 2D array used as base class for matrices and vectors.
unsigned int getCols() const
unsigned int getRows() const
Class that implements the Canny's edge detector. It is possible to use a boolean mask to ignore some ...
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.
@ notImplementedError
Not implemented.
static void convert(const vpImage< unsigned char > &src, vpImage< vpRGBa > &dest)
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.
unsigned int getWidth() const
void resize(unsigned int h, unsigned int w)
resize the image : Image initialization
unsigned int getCols() const
unsigned int getHeight() const
unsigned int getRows() const
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...