diff --git a/modules/core/src/image/vpCannyEdgeDetection.cpp b/modules/core/src/image/vpCannyEdgeDetection.cpp index 84f955f491..884f2f02f5 100644 --- a/modules/core/src/image/vpCannyEdgeDetection.cpp +++ b/modules/core/src/image/vpCannyEdgeDetection.cpp @@ -235,7 +235,8 @@ vpCannyEdgeDetection::performFilteringAndGradientComputation(const vpImage= 45.f && absoluteTheta < 90.f) { + else if (gradientOrientation >= M_PI_4f && gradientOrientation < M_PI_2f) { // Angles between 45 and 90 deg rely on the diagonal and vertical points - thetaMin = 45.f; + thetaMin = M_PI_4f; dColGradAlpha = 1; dColGradBeta = 0; dRowGradAlpha = -1; dRowGradBeta = -1; } - else if (absoluteTheta >= 90.f && absoluteTheta < 135.f) { + else if (gradientOrientation >= M_PI_2f && gradientOrientation < (3.f * M_PI_4f)) { // Angles between 90 and 135 deg rely on the vertical and diagonal points - thetaMin = 90.f; + thetaMin = M_PI_2f; dColGradAlpha = 0; dColGradBeta = -1; dRowGradAlpha = -1; dRowGradBeta = -1; } - else if (absoluteTheta >= 135.f && absoluteTheta < 180.f) { + else if (gradientOrientation >= (3.f * M_PI_4f) && gradientOrientation < M_PIf) { // Angles between 135 and 180 deg rely on the vertical and diagonal points - thetaMin = 135.f; + thetaMin = 3.f * M_PI_4f; dColGradAlpha = -1; dColGradBeta = -1; dRowGradAlpha = -1; dRowGradBeta = 0; } - beta = (absoluteTheta - thetaMin) / 45.f; + beta = (gradientOrientation - thetaMin) / M_PI_4f; alpha = 1.f - beta; } @@ -314,28 +315,35 @@ getManhattanGradient(const vpImage &dIx, const vpImage &dIy, const } /** - * @brief Get the absolute value of the gradient orientation. + * @brief Get the gradient orientation, expressed in radians, between 0 and M_PIf radians. + * If the gradient orientation is negative, we add M_PI radians in + * order to keep the same orientation but in the positive direction. * * @param dIx : Gradient along the horizontal axis. * @param dIy : Gradient along the vertical axis. * @param row : Index along the vertical axis. * @param col : Index along the horizontal axis. - * @return float The absolute value of the gradient orientation, expressed in degrees. + * @return float The positive value of the gradient orientation, expressed in radians. */ float -getAbsoluteTheta(const vpImage &dIx, const vpImage &dIy, const int &row, const int &col) +getGradientOrientation(const vpImage &dIx, const vpImage &dIy, const int &row, const int &col) { - float absoluteTheta = 0.f; + float gradientOrientation = 0.f; float dx = dIx[row][col]; float dy = dIy[row][col]; if (std::abs(dx) < std::numeric_limits::epsilon()) { - absoluteTheta = 90.f; + gradientOrientation = M_PI_2f; } else { - absoluteTheta = static_cast(vpMath::deg(std::abs(std::atan2(dy, dx)))); + // -dy because the y-axis of the image is oriented towards the bottom of the screen + // while we later work with a y-axis oriented towards the top when getting the theta quadrant. + gradientOrientation = static_cast(std::atan2(-dy , dx)); + if(gradientOrientation < 0.f) { + gradientOrientation += M_PIf; // + M_PI in order to be between 0 and M_PIf + } } - return absoluteTheta; + return gradientOrientation; } void @@ -358,9 +366,9 @@ vpCannyEdgeDetection::performEdgeThinning(const float &lowerThreshold) // depending on the gradient orientation int dRowAlphaPlus = 0, dRowBetaPlus = 0; int dColAphaPlus = 0, dColBetaPlus = 0; - float absTheta = getAbsoluteTheta(m_dIx, m_dIy, row, col); + float gradientOrientation = getGradientOrientation(m_dIx, m_dIy, row, col); float alpha = 0.f, beta = 0.f; - getInterpolationWeightsAndOffsets(absTheta, alpha, beta, dRowAlphaPlus, dRowBetaPlus, dColAphaPlus, dColBetaPlus); + getInterpolationWeightsAndOffsets(gradientOrientation, alpha, beta, dRowAlphaPlus, dRowBetaPlus, dColAphaPlus, dColBetaPlus); int dRowAlphaMinus = -dRowAlphaPlus, dRowBetaMinus = -dRowBetaPlus; int dColAphaMinus = -dColAphaPlus, dColBetaMinus = -dColBetaPlus; float gradAlphaPlus = getManhattanGradient(m_dIx, m_dIy, row + dRowAlphaPlus, col + dColAphaPlus); diff --git a/modules/core/src/image/vpImageFilter.cpp b/modules/core/src/image/vpImageFilter.cpp index 20f55874a9..629ee1e063 100644 --- a/modules/core/src/image/vpImageFilter.cpp +++ b/modules/core/src/image/vpImageFilter.cpp @@ -684,7 +684,7 @@ float vpImageFilter::computeCannyThreshold(const cv::Mat &cv_I, const cv::Mat *p const float range[] = { 0.f, 256.f }; // The upper boundary is exclusive const float *ranges[] = { range }; int channels[] = { 0 }; - bool dims = 1; // The number of dimensions of the histogram + int dims = 1; // The number of dimensions of the histogram int histSize[] = { bins }; bool uniform = true; bool accumulate = false; // Clear the histogram at the beginning of calcHist if false, does not clear it otherwise @@ -741,14 +741,14 @@ void vpImageFilter::computePartialDerivatives(const cv::Mat &cv_I, if (normalize) { scale = 1. / 8.; if (apertureGradient > 3) { - scale *= std::pow(1./16., ((apertureGradient -1.)/2.) - 1.); + scale *= std::pow(1./2., (apertureGradient * 2. - 3.)); // 1 / 2^(2 x ksize - dx - dy -2) with ksize =apertureGradient and dx xor dy = 1 } } if (computeDx) { - cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, 1, 0, scale); + cv::Sobel(img_blur, cv_dIx, CV_16S, 1, 0, apertureGradient, scale, 0., cv::BORDER_REPLICATE); } if (computeDy) { - cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, 1, 0, scale); + cv::Sobel(img_blur, cv_dIy, CV_16S, 0, 1, apertureGradient, scale, 0., cv::BORDER_REPLICATE); } } else if (filteringType == vpImageFilter::CANNY_GBLUR_SCHARR_FILTERING) {