From 1ac0aae53f7db0f16e51f1166d9021b0f4fb1982 Mon Sep 17 00:00:00 2001 From: Fabien Spindler Date: Tue, 29 Aug 2023 14:13:47 +0200 Subject: [PATCH] Minor changes - code indentation - doxygen doc improvements - alphabetical order in vpImageFilter.h --- .../image/tutorial-image-filtering.dox | 18 +- .../core/include/visp3/core/vpImageFilter.h | 274 ++++++++---------- modules/core/src/image/vpImageFilter.cpp | 200 ++++++------- 3 files changed, 219 insertions(+), 273 deletions(-) diff --git a/doc/tutorial/image/tutorial-image-filtering.dox b/doc/tutorial/image/tutorial-image-filtering.dox index 617bf85859..237d9eee9e 100644 --- a/doc/tutorial/image/tutorial-image-filtering.dox +++ b/doc/tutorial/image/tutorial-image-filtering.dox @@ -91,17 +91,13 @@ The resulting image \c C is the following: To apply a convolution to an image, we first have to define a kernel. For example, let us consider the 3x3 Sobel kernel defined in \c K. - \f[ - {\bf K} = \begin{tabular}{|c|c|c|} - \hline - 1 & 0 & -1 \\ - \hline - 2 & 0 & -2 \\ - \hline - 1 & 0 & -1 \\ - \hline - \end{tabular} - \f] +\f[ +{\bf K} = \left[ \begin{matrix} +1 & 0 & -1 \\ +2 & 0 & -2 \\ +1 & 0 & -1 \\ +\end{matrix} \right] +\f] \snippet tutorial-image-filter.cpp Convolution kernel diff --git a/modules/core/include/visp3/core/vpImageFilter.h b/modules/core/include/visp3/core/vpImageFilter.h index 183f26d71b..7e3e2d22ec 100644 --- a/modules/core/include/visp3/core/vpImageFilter.h +++ b/modules/core/include/visp3/core/vpImageFilter.h @@ -70,58 +70,51 @@ class VISP_EXPORT vpImageFilter { public: #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) - static double median(const cv::Mat &cv_I); - static double median(const vpImage &Isrc); - static std::vector median(const vpImage &Isrc); static void canny(const vpImage &I, vpImage &Ic, unsigned int gaussianFilterSize, double thresholdCanny, unsigned int apertureSobel); #endif /*! - Apply a 1x3 derivative filter to an image pixel. + Apply a 1x3 derivative filter to an image pixel. - \param I : Image to filter - \param r : coordinates (row) of the pixel - \param c : coordinates (column) of the pixel - */ + \param I : Image to filter + \param r : coordinates (row) of the pixel + \param c : coordinates (column) of the pixel + */ template static double derivativeFilterX(const vpImage &I, unsigned int r, unsigned int c) { return (2047.0 * (I[r][c + 1] - I[r][c - 1]) + 913.0 * (I[r][c + 2] - I[r][c - 2]) + - 112.0 * (I[r][c + 3] - I[r][c - 3])) / - 8418.0; + 112.0 * (I[r][c + 3] - I[r][c - 3])) / 8418.0; } /*! - Apply a 3x1 derivative filter to an image pixel. + Apply a 3x1 derivative filter to an image pixel. - \param I : Image to filter - \param r : coordinates (row) of the pixel - \param c : coordinates (column) of the pixel - */ + \param I : Image to filter + \param r : coordinates (row) of the pixel + \param c : coordinates (column) of the pixel + */ template static double derivativeFilterY(const vpImage &I, unsigned int r, unsigned int c) { return (2047.0 * (I[r + 1][c] - I[r - 1][c]) + 913.0 * (I[r + 2][c] - I[r - 2][c]) + - 112.0 * (I[r + 3][c] - I[r - 3][c])) / - 8418.0; + 112.0 * (I[r + 3][c] - I[r - 3][c])) / 8418.0; } /*! - Apply a 1 x size Derivative Filter in X to an image pixel. + Apply a 1 x size Derivative Filter in X to an image pixel. - \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. - \param I : Image to filter - \param r : coordinates (row) of the pixel - \param c : coordinates (column) of the pixel - \param filter : coefficients of the filter to be initialized using - vpImageFilter::getGaussianDerivativeKernel(). \param size : size of the - filter - - \sa vpImageFilter::getGaussianDerivativeKernel() - */ + \tparam FilterType : Either float, to accelerate the computation time, or double, to have greater precision. + \param I : Image to filter + \param r : Coordinates (row) of the pixel + \param c : Coordinates (column) of the pixel + \param filter : Coefficients of the filter to be initialized using + vpImageFilter::getGaussianDerivativeKernel(). + \param size : Size of the filter. + \sa vpImageFilter::getGaussianDerivativeKernel() + */ template - static FilterType derivativeFilterX(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + static FilterType derivativeFilterX(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size) { unsigned int i; FilterType result; @@ -135,21 +128,19 @@ class VISP_EXPORT vpImageFilter } /*! - Apply a size x 1 Derivative Filter in Y to an image pixel. + Apply a size x 1 Derivative Filter in Y to an image pixel. - \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. - \param I : Image to filter - \param r : coordinates (row) of the pixel - \param c : coordinates (column) of the pixel - \param filter : coefficients of the filter to be initialized using - vpImageFilter::getGaussianDerivativeKernel(). \param size : size of the - filter + \tparam FilterType : Either float, to accelerate the computation time, or double, to have greater precision. + \param I : Image to filter + \param r : Coordinates (row) of the pixel + \param c : Coordinates (column) of the pixel + \param filter : Coefficients of the filter to be initialized using vpImageFilter::getGaussianDerivativeKernel(). + \param size : Size of the filter. - \sa vpImageFilter::getGaussianDerivativeKernel() + \sa vpImageFilter::getGaussianDerivativeKernel() */ template - static FilterType derivativeFilterY(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + static FilterType derivativeFilterY(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size) { unsigned int i; FilterType result; @@ -163,32 +154,32 @@ class VISP_EXPORT vpImageFilter } /*! - Apply a filter to an image. - \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. - \param I : Image to filter - \param If : Filtered image. - \param M : Filter kernel. - \param convolve : If true, perform a convolution otherwise a correlation. - - \note By default it performs a correlation: - \f[ - \textbf{I\_filtered} \left( u,v \right) = - \sum_{y=0}^{\textbf{kernel\_h}} - \sum_{x=0}^{\textbf{kernel\_w}} - \textbf{M} \left( x,y \right ) \times - \textbf{I} \left( - u-\frac{\textbf{kernel\_w}}{2}+x,v-\frac{\textbf{kernel\_h}}{2}+y \right) - \f] - The convolution is almost the same operation: - \f[ - \textbf{I\_filtered} \left( u,v \right) = - \sum_{y=0}^{\textbf{kernel\_h}} - \sum_{x=0}^{\textbf{kernel\_w}} - \textbf{M} \left( x,y \right ) \times - \textbf{I} \left( - u+\frac{\textbf{kernel\_w}}{2}-x,v+\frac{\textbf{kernel\_h}}{2}-y \right) - \f] - Only pixels in the input image fully covered by the kernel are considered. + Apply a filter to an image. + \tparam FilterType : Either float, to accelerate the computation time, or double, to have greater precision. + \param I : Image to filter + \param If : Filtered image. + \param M : Filter kernel. + \param convolve : If true, perform a convolution otherwise a correlation. + + \note By default it performs a correlation: + \f[ + \textbf{I\_filtered} \left( u,v \right) = + \sum_{y=0}^{\textbf{kernel\_h}} + \sum_{x=0}^{\textbf{kernel\_w}} + \textbf{M} \left( x,y \right ) \times + \textbf{I} \left( + u-\frac{\textbf{kernel\_w}}{2}+x,v-\frac{\textbf{kernel\_h}}{2}+y \right) + \f] + The convolution is almost the same operation: + \f[ + \textbf{I\_filtered} \left( u,v \right) = + \sum_{y=0}^{\textbf{kernel\_h}} + \sum_{x=0}^{\textbf{kernel\_w}} + \textbf{M} \left( x,y \right ) \times + \textbf{I} \left( + u+\frac{\textbf{kernel\_w}}{2}-x,v+\frac{\textbf{kernel\_h}}{2}-y \right) + \f] + Only pixels in the input image fully covered by the kernel are considered. */ template static void filter(const vpImage &I, vpImage &If, const vpArray2D &M, bool convolve = false) @@ -231,16 +222,16 @@ class VISP_EXPORT vpImageFilter } /*! - Apply a filter to an image: - \f[ - \textbf{I}_u = \textbf{M} \ast \textbf{I} \textbf{ and } \textbf{I}_v = - \textbf{M}^t \ast \textbf{I} \f] - \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. - \param I : Image to filter - \param Iu : Filtered image along the horizontal axis (u = columns). - \param Iv : Filtered image along the vertical axis (v = rows). - \param M : Filter kernel. - \param convolve : If true, perform a convolution otherwise a correlation. + Apply a filter to an image: + \f[ + \textbf{I}_u = \textbf{M} \ast \textbf{I} \textbf{ and } \textbf{I}_v = + \textbf{M}^t \ast \textbf{I} \f] + \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. + \param I : Image to filter + \param Iu : Filtered image along the horizontal axis (u = columns). + \param Iv : Filtered image along the vertical axis (v = rows). + \param M : Filter kernel. + \param convolve : If true, perform a convolution otherwise a correlation. */ template static void filter(const vpImage &I, vpImage &Iu, vpImage &Iv, const vpArray2D &M, @@ -290,8 +281,7 @@ class VISP_EXPORT vpImageFilter } } - static void sepFilter(const vpImage &I, vpImage &If, const vpColVector &kernelH, - const vpColVector &kernelV); + static void sepFilter(const vpImage &I, vpImage &If, const vpColVector &kernelH, const vpColVector &kernelV); /*! Apply a separable filter. @@ -302,8 +292,7 @@ class VISP_EXPORT vpImageFilter \param size: The size of the filter. */ template - static void filter(const vpImage &I, vpImage &GI, const FilterType *filter, - unsigned int size) + static void filter(const vpImage &I, vpImage &GI, const FilterType *filter, unsigned int size) { vpImage GIx; filterX(I, GIx, filter, size); @@ -380,8 +369,7 @@ class VISP_EXPORT vpImageFilter static void filterXB(const vpImage &I, vpImage &dIx, const double *filter, unsigned int size); template - static inline FilterType filterX(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + static inline FilterType filterX(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size) { FilterType result; @@ -393,8 +381,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c]; } - static inline double filterXR(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + static inline double filterXR(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -406,8 +393,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c].R; } - static inline double filterXG(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + static inline double filterXG(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -419,8 +405,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c].G; } - static inline double filterXB(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + static inline double filterXB(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -434,7 +419,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterXLeftBorder(const vpImage &I, unsigned int r, unsigned int c, - const FilterType *filter, unsigned int size) + const FilterType *filter, unsigned int size) { FilterType result; @@ -499,7 +484,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterXRightBorder(const vpImage &I, unsigned int r, unsigned int c, - const FilterType *filter, unsigned int size) + const FilterType *filter, unsigned int size) { FilterType result; @@ -564,7 +549,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterX(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + unsigned int size) { FilterType result; @@ -578,7 +563,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterXLeftBorder(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + unsigned int size) { FilterType result; @@ -595,7 +580,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterXRightBorder(const vpImage &I, unsigned int r, unsigned int c, - const FilterType *filter, unsigned int size) + const FilterType *filter, unsigned int size) { FilterType result; @@ -611,8 +596,7 @@ class VISP_EXPORT vpImageFilter } template - static void filterY(const vpImage &I, vpImage &dIy, const FilterType *filter, - unsigned int size) + static void filterY(const vpImage &I, vpImage &dIy, const FilterType *filter, unsigned int size) { dIy.resize(I.getHeight(), I.getWidth()); for (unsigned int i = 0; i < (size - 1) / 2; i++) { @@ -659,8 +643,7 @@ class VISP_EXPORT vpImageFilter } template - static inline FilterType filterY(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + static inline FilterType filterY(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, unsigned int size) { FilterType result; @@ -672,8 +655,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c]; } - static inline double filterYR(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + static inline double filterYR(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -684,8 +666,7 @@ class VISP_EXPORT vpImageFilter } return result + filter[0] * I[r][c].R; } - static inline double filterYG(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + static inline double filterYG(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -696,8 +677,8 @@ class VISP_EXPORT vpImageFilter } return result + filter[0] * I[r][c].G; } - static inline double filterYB(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + + static inline double filterYB(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -711,7 +692,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterYTopBorder(const vpImage &I, unsigned int r, unsigned int c, - const FilterType *filter, unsigned int size) + const FilterType *filter, unsigned int size) { FilterType result; @@ -726,8 +707,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c]; } - double static inline filterYTopBorderR(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + double static inline filterYTopBorderR(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -742,8 +722,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c].R; } - double static inline filterYTopBorderG(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + double static inline filterYTopBorderG(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -758,8 +737,7 @@ class VISP_EXPORT vpImageFilter return result + filter[0] * I[r][c].G; } - double static inline filterYTopBorderB(const vpImage &I, unsigned int r, unsigned int c, const double *filter, - unsigned int size) + double static inline filterYTopBorderB(const vpImage &I, unsigned int r, unsigned int c, const double *filter, unsigned int size) { double result; @@ -776,7 +754,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterYBottomBorder(const vpImage &I, unsigned int r, unsigned int c, - const FilterType *filter, unsigned int size) + const FilterType *filter, unsigned int size) { FilterType result; @@ -840,8 +818,8 @@ class VISP_EXPORT vpImageFilter } template - static inline FilterType filterYTopBorder(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + static inline FilterType filterYTopBorder(const vpImage &I, unsigned int r, unsigned int c, + const FilterType *filter, unsigned int size) { FilterType result; @@ -858,7 +836,7 @@ class VISP_EXPORT vpImageFilter template static inline FilterType filterYBottomBorder(const vpImage &I, unsigned int r, unsigned int c, - const FilterType *filter, unsigned int size) + const FilterType *filter, unsigned int size) { FilterType result; @@ -874,8 +852,8 @@ class VISP_EXPORT vpImageFilter } template - static inline FilterType filterY(const vpImage &I, unsigned int r, unsigned int c, const FilterType *filter, - unsigned int size) + static inline FilterType filterY(const vpImage &I, unsigned int r, unsigned int c, + const FilterType *filter, unsigned int size) { FilterType result; @@ -895,14 +873,12 @@ class VISP_EXPORT vpImageFilter \param size : Filter size. This value should be odd. \param sigma : Gaussian standard deviation. If it is equal to zero or negative, it is computed from filter size as sigma = (size-1)/6. - \param normalize : Flag indicating whether to normalize the filter coefficients or - not. + \param normalize : Flag indicating whether to normalize the filter coefficients or not. \sa getGaussianKernel() to know which kernel is used. */ template - static void gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size = 7, FilterType sigma = 0., - bool normalize = true) + static void gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size = 7, FilterType sigma = 0., bool normalize = true) { FilterType *fg = new FilterType[(size + 1) / 2]; vpImageFilter::getGaussianKernel(fg, size, sigma, normalize); @@ -913,8 +889,7 @@ class VISP_EXPORT vpImageFilter delete[] fg; } - static void gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size = 7, double sigma = 0., - bool normalize = true); + static void gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size = 7, double sigma = 0., bool normalize = true); /*! Apply a Gaussian blur to a double image. @@ -929,8 +904,7 @@ class VISP_EXPORT vpImageFilter \sa getGaussianKernel() to know which kernel is used. */ template - static void gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size = 7, FilterType sigma = 0., - bool normalize = true) + static void gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size = 7, FilterType sigma = 0., bool normalize = true) { FilterType *fg = new FilterType[(size + 1) / 2]; vpImageFilter::getGaussianKernel(fg, size, sigma, normalize); @@ -942,15 +916,14 @@ class VISP_EXPORT vpImageFilter } /*! - Apply a 5x5 Gaussian filter to an image pixel. + Apply a 5x5 Gaussian filter to an image pixel. - \param fr : Image to filter - \param r : coordinates (row) of the pixel - \param c : coordinates (column) of the pixel - */ + \param fr : Image to filter + \param r : coordinates (row) of the pixel + \param c : coordinates (column) of the pixel + */ template static double gaussianFilter(const vpImage &fr, unsigned int r, unsigned int c) { - // filter Gaussien return (15.0 * fr[r][c] + 12.0 * (fr[r - 1][c] + fr[r][c - 1] + fr[r + 1][c] + fr[r][c + 1]) + 9.0 * (fr[r - 1][c - 1] + fr[r + 1][c - 1] + fr[r - 1][c + 1] + fr[r + 1][c + 1]) + 5.0 * (fr[r - 2][c] + fr[r][c - 2] + fr[r + 2][c] + fr[r][c + 2]) + @@ -959,7 +932,7 @@ class VISP_EXPORT vpImageFilter 2.0 * (fr[r - 2][c - 2] + fr[r + 2][c - 2] + fr[r - 2][c + 2] + fr[r + 2][c + 2])) / 159.0; } - // Gaussain pyramid operation + // Gaussian pyramid operation static void getGaussPyramidal(const vpImage &I, vpImage &GI); static void getGaussXPyramidal(const vpImage &I, vpImage &GI); static void getGaussYPyramidal(const vpImage &I, vpImage &GI); @@ -977,7 +950,7 @@ class VISP_EXPORT vpImageFilter \param[in] normalize : Flag indicating whether to normalize the filter coefficients or not. In that case \f$\Sigma G_i = 1 \f$. - The function computes the \e (size+1)/2 values of the Gaussian filter cooefficients \f$ G_i \f$ as: + The function computes the \e (size+1)/2 values of the Gaussian filter coefficients \f$ G_i \f$ as: \f[ G_i = \frac{1}{\sigma \sqrt{2 \pi}} \exp{(-i^2 / (2. * \sigma^2))}\f] */ template @@ -1072,8 +1045,7 @@ class VISP_EXPORT vpImageFilter } template - static void getGradX(const vpImage &I, vpImage &dIx, const FilterType *filter, - unsigned int size) + static void getGradX(const vpImage &I, vpImage &dIx, const FilterType *filter, unsigned int size) { dIx.resize(I.getHeight(), I.getWidth()); for (unsigned int i = 0; i < I.getHeight(); i++) { @@ -1101,7 +1073,7 @@ class VISP_EXPORT vpImageFilter */ template static void getGradXGauss2D(const vpImage &I, vpImage &dIx, const FilterType *gaussianKernel, - const FilterType *gaussianDerivativeKernel, unsigned int size) + const FilterType *gaussianDerivativeKernel, unsigned int size) { vpImage GIy; vpImageFilter::filterY(I, GIy, gaussianKernel, size); @@ -1163,7 +1135,7 @@ class VISP_EXPORT vpImageFilter */ template static void getGradYGauss2D(const vpImage &I, vpImage &dIy, const FilterType *gaussianKernel, - const FilterType *gaussianDerivativeKernel, unsigned int size) + const FilterType *gaussianDerivativeKernel, unsigned int size) { vpImage GIx; vpImageFilter::filterX(I, GIx, gaussianKernel, size); @@ -1171,11 +1143,11 @@ class VISP_EXPORT vpImageFilter } /*! - Get Sobel kernel for X-direction. - \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. - \param filter : Pointer to a double array already allocated. - \param size : Kernel size computed as: kernel_size = size*2 + 1 (max size is 20). - \return Scaling factor. + Get Sobel kernel for X-direction. + \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. + \param filter : Pointer to a double array already allocated. + \param size : Kernel size computed as: kernel_size = size*2 + 1 (max size is 20). + \return Scaling factor. */ template inline static FilterType getSobelKernelX(FilterType *filter, unsigned int size) @@ -1192,12 +1164,12 @@ class VISP_EXPORT vpImageFilter } /*! - Get Sobel kernel for Y-direction. - \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. - \param filter : Pointer to a double array already allocated. - \param size : Kernel size computed as: kernel_size = size*2 + 1 (max size is 20). - \return Scaling factor. - */ + Get Sobel kernel for Y-direction. + \tparam FilterType: Either float, to accelerate the computation time, or double, to have greater precision. + \param filter : Pointer to a double array already allocated. + \param size : Kernel size computed as: kernel_size = size*2 + 1 (max size is 20). + \return Scaling factor. + */ template inline static FilterType getSobelKernelY(FilterType *filter, unsigned int size) { @@ -1248,6 +1220,12 @@ class VISP_EXPORT vpImageFilter return 1 / 16.0; } + +#if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) + static double median(const cv::Mat &cv_I); + static double median(const vpImage &Isrc); + static std::vector median(const vpImage &Isrc); +#endif }; #endif diff --git a/modules/core/src/image/vpImageFilter.cpp b/modules/core/src/image/vpImageFilter.cpp index 768e7180c5..22d329f385 100644 --- a/modules/core/src/image/vpImageFilter.cpp +++ b/modules/core/src/image/vpImageFilter.cpp @@ -55,60 +55,59 @@ void vpImageFilter::filter(const vpImage &I, vpImage &Iu bool convolve); /** * \endcond - */ +*/ - /*! - Apply a filter to an image using two separable kernels. For instance, - the Sobel kernel can be decomposed to: - \f[ - \left [ - \begin{matrix} - 1 & 0 & -1 \\ - 2 & 0 & -2 \\ - 1 & 0 & -1 - \end{matrix} - \right ] = - \left [ - \begin{matrix} - 1 \\ - 2 \\ - 1 - \end{matrix} - \right ] \ast - \left [ - \begin{matrix} - 1 && 0 && -1 - \end{matrix} - \right ] - \f] - Thus, the convolution operation can be performed as: - \f[ - G_x = - \left [ - \begin{matrix} - 1 \\ - 2 \\ - 1 - \end{matrix} - \right ] \ast - \left ( - \left [ - \begin{matrix} - 1 && 0 && -1 - \end{matrix} - \right ] \ast I - \right ) - \f] - Using two separable kernels reduce the number of operations and can be - faster for large kernels. - - \param I : Image to filter - \param If : Filtered image. - \param kernelH : Separable kernel (performed first). - \param kernelV : Separable kernel (performed last). - \note Only pixels in the input image fully covered by the kernel are - considered. - */ +/*! + Apply a filter to an image using two separable kernels. For instance, + the Sobel kernel can be decomposed to: + \f[ + \left [ + \begin{matrix} + 1 & 0 & -1 \\ + 2 & 0 & -2 \\ + 1 & 0 & -1 + \end{matrix} + \right ] = + \left [ + \begin{matrix} + 1 \\ + 2 \\ + 1 + \end{matrix} + \right ] \ast + \left [ + \begin{matrix} + 1 & 0 & -1 + \end{matrix} + \right ] + \f] + Thus, the convolution operation can be performed as: + \f[ + G_x = + \left [ + \begin{matrix} + 1 \\ + 2 \\ + 1 + \end{matrix} + \right ] \ast + \left ( + \left [ + \begin{matrix} + 1 & 0 & -1 + \end{matrix} + \right ] \ast I + \right ) + \f] + Using two separable kernels reduce the number of operations and can be + faster for large kernels. + + \param I : Image to filter + \param If : Filtered image. + \param kernelH : Separable kernel (performed first). + \param kernelV : Separable kernel (performed last). + \note Only pixels in the input image fully covered by the kernel are considered. +*/ void vpImageFilter::sepFilter(const vpImage &I, vpImage &If, const vpColVector &kernelH, const vpColVector &kernelV) { @@ -143,9 +142,9 @@ void vpImageFilter::sepFilter(const vpImage &I, vpImage & #if defined(VISP_HAVE_OPENCV) && defined(HAVE_OPENCV_IMGPROC) /** - * \brief Calculates the median value of a single channel + * \brief Calculates the median value of a single channel. * The algorithm is based on based on https://github.com/arnaudgelas/OpenCVExamples/blob/master/cvMat/Statistics/Median/Median.cpp - * \param[in] channel Single channel image in OpenCV format. + * \param[in] channel : Single channel image in OpenCV format. */ double vpImageFilter::median(const cv::Mat &channel) { @@ -171,9 +170,9 @@ double vpImageFilter::median(const cv::Mat &channel) } /** - * \brief Calculates the median value of a single channel + * \brief Calculates the median value of a single channel. * The algorithm is based on based on https://github.com/arnaudgelas/OpenCVExamples/blob/master/cvMat/Statistics/Median/Median.cpp - * \param[in] Isrc Gray-level image in ViSP format. + * \param[in] Isrc : Gray-level image in ViSP format. * \sa \ref vpImageFilter::median() "vpImageFilter::median(const cv::Mat)" */ double vpImageFilter::median(const vpImage &Isrc) @@ -186,7 +185,7 @@ double vpImageFilter::median(const vpImage &Isrc) /** * \brief Calculates the median value of a vpRGBa image. * The result is ordered in RGB format. - * \param[in] Isrc RGB image in ViSP format. Alpha channel is ignored. + * \param[in] Isrc : RGB image in ViSP format. Alpha channel is ignored. * \return std::vector meds such as meds[0] = red-channel-median meds[1] = green-channel-median * and meds[2] = blue-channel-median. * \sa \ref vpImageFilter::median() "vpImageFilter::median(const cv::Mat)" @@ -242,7 +241,7 @@ double computeCannyThreshold(const cv::Mat &cv_I, const cv::Mat *p_cv_blur, doub /** * \brief Compute the upper Canny edge filter threshold. * - * \param[in] I The gray-scale image, in ViSP format. + * \param[in] I : The gray-scale image, in ViSP format. * \return double The upper Canny edge filter threshold. */ double computeCannyThreshold(const vpImage &I, double &lowerThresh) @@ -294,7 +293,7 @@ int main() \param apertureSobel : Size of the mask for the Sobel operator (odd number). */ void vpImageFilter::canny(const vpImage &Isrc, vpImage &Ires, - unsigned int gaussianFilterSize, double thresholdCanny, unsigned int apertureSobel) + unsigned int gaussianFilterSize, double thresholdCanny, unsigned int apertureSobel) { cv::Mat img_cvmat, cv_I_blur, edges_cvmat; vpImageConvert::convert(Isrc, img_cvmat); @@ -441,21 +440,20 @@ void vpImageFilter::gaussianBlur(const vpImage &I, vpImag bool normalize); /** * \endcond - */ +*/ - /*! - Apply a Gaussian blur to RGB color image. - \param I : Input image. - \param GI : Filtered image. - \param size : Filter size. This value should be odd. - \param sigma : Gaussian standard deviation. If it is equal to zero or - negative, it is computed from filter size as sigma = (size-1)/6. - \param normalize : Flag indicating whether to normalize the filter coefficients or not. - - \sa getGaussianKernel() to know which kernel is used. - */ -void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size, double sigma, - bool normalize) +/*! + Apply a Gaussian blur to RGB color image. + \param I : Input image. + \param GI : Filtered image. + \param size : Filter size. This value should be odd. + \param sigma : Gaussian standard deviation. If it is equal to zero or + negative, it is computed from filter size as sigma = (size-1)/6. + \param normalize : Flag indicating whether to normalize the filter coefficients or not. + + \sa getGaussianKernel() to know which kernel is used. +*/ +void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size, double sigma, bool normalize) { double *fg = new double[(size + 1) / 2]; vpImageFilter::getGaussianKernel(fg, size, sigma, normalize); @@ -470,12 +468,10 @@ void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, * \cond DO_NOT_DOCUMENT */ template<> -void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size, float sigma, - bool normalize); +void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size, float sigma, bool normalize); template<> -void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size, double sigma, - bool normalize); +void vpImageFilter::gaussianBlur(const vpImage &I, vpImage &GI, unsigned int size, double sigma, bool normalize); template<> void vpImageFilter::getGaussianKernel(float *filter, unsigned int size, float sigma, bool normalize); @@ -524,40 +520,40 @@ void vpImageFilter::getGradY(const vpImage &I, vpImage void vpImageFilter::getGradXGauss2D(const vpImage &I, vpImage &dIx, const float *gaussianKernel, - const float *gaussianDerivativeKernel, unsigned int size); + const float *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradXGauss2D(const vpImage &I, vpImage &dIx, const double *gaussianKernel, - const double *gaussianDerivativeKernel, unsigned int size); + const double *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradXGauss2D(const vpImage &I, vpImage &dIx, const float *gaussianKernel, - const float *gaussianDerivativeKernel, unsigned int size); + const float *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradXGauss2D(const vpImage &I, vpImage &dIx, const double *gaussianKernel, - const double *gaussianDerivativeKernel, unsigned int size); + const double *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradYGauss2D(const vpImage &I, vpImage &dIy, const float *gaussianKernel, - const float *gaussianDerivativeKernel, unsigned int size); + const float *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradYGauss2D(const vpImage &I, vpImage &dIy, const double *gaussianKernel, - const double *gaussianDerivativeKernel, unsigned int size); + const double *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradYGauss2D(const vpImage &I, vpImage &dIy, const float *gaussianKernel, - const float *gaussianDerivativeKernel, unsigned int size); + const float *gaussianDerivativeKernel, unsigned int size); template<> void vpImageFilter::getGradYGauss2D(const vpImage &I, vpImage &dIy, const double *gaussianKernel, - const double *gaussianDerivativeKernel, unsigned int size); + const double *gaussianDerivativeKernel, unsigned int size); /** * \endcond - */ +*/ - // operation pour pyramide gaussienne +// Operation for Gaussian pyramid void vpImageFilter::getGaussPyramidal(const vpImage &I, vpImage &GI) { vpImage GIx; @@ -581,16 +577,6 @@ void vpImageFilter::getGaussPyramidal(const vpImage &I, vpImage &I, vpImage &GI) { -#if 0 - GI.resize(I.getHeight(), (int)((I.getWidth() + 1.) / 2.)); - for (unsigned int i = 0; i < I.getHeight(); i++) { - GI[i][0] = I[i][0]; - for (unsigned int j = 1; j < ((I.getWidth() + 1.) / 2.) - 1; j++) { - GI[i][j] = vpImageFilter::filterGaussXPyramidal(I, i, 2 * j); - } - GI[i][(int)((I.getWidth() + 1.) / 2.) - 1] = I[i][2 * ((int)((I.getWidth() + 1.) / 2.) - 1)]; - } -#else unsigned int w = I.getWidth() / 2; GI.resize(I.getHeight(), w); @@ -601,23 +587,10 @@ void vpImageFilter::getGaussXPyramidal(const vpImage &I, vpImage< } GI[i][w - 1] = I[i][2 * w - 1]; } - -#endif } + void vpImageFilter::getGaussYPyramidal(const vpImage &I, vpImage &GI) { - -#ifdef ORIG - GI.resize((int)((I.getHeight() + 1.) / 2.), I.getWidth()); - for (unsigned int j = 0; j < I.getWidth(); j++) { - GI[0][j] = I[0][j]; - for (unsigned int i = 1; i < ((I.getHeight() + 1.) / 2.) - 1; i++) { - GI[i][j] = vpImageFilter::filterGaussYPyramidal(I, 2 * i, j); - } - GI[(int)((I.getHeight() + 1.) / 2.) - 1][j] = I[2 * ((int)((I.getHeight() + 1.) / 2.) - 1)][j]; - } - -#else unsigned int h = I.getHeight() / 2; GI.resize(h, I.getWidth()); @@ -628,7 +601,6 @@ void vpImageFilter::getGaussYPyramidal(const vpImage &I, vpImage< } GI[h - 1][j] = I[2 * h - 1][j]; } -#endif } /** @@ -647,4 +619,4 @@ template<> float vpImageFilter::getSobelKernelY(float *filter, unsigned int size); /** * \endcond - */ \ No newline at end of file + */