diff --git a/modules/imgproc/include/opencv2/imgproc.hpp b/modules/imgproc/include/opencv2/imgproc.hpp index 059d26a41c..d43123972f 100644 --- a/modules/imgproc/include/opencv2/imgproc.hpp +++ b/modules/imgproc/include/opencv2/imgproc.hpp @@ -235,8 +235,9 @@ enum MorphShapes { MORPH_RECT = 0, //!< a rectangular structuring element: \f[E_{ij}=1\f] MORPH_CROSS = 1, //!< a cross-shaped structuring element: //!< \f[E_{ij} = \begin{cases} 1 & \texttt{if } {i=\texttt{anchor.y } {or } {j=\texttt{anchor.x}}} \\0 & \texttt{otherwise} \end{cases}\f] - MORPH_ELLIPSE = 2 //!< an elliptic structuring element, that is, a filled ellipse inscribed + MORPH_ELLIPSE = 2, //!< an elliptic structuring element, that is, a filled ellipse inscribed //!< into the rectangle Rect(0, 0, esize.width, esize.height) + MORPH_DIAMOND = 3 //!< a diamond structuring element defined by Manhattan distance }; //! @} imgproc_filter diff --git a/modules/imgproc/include/opencv2/imgproc/types_c.h b/modules/imgproc/include/opencv2/imgproc/types_c.h index df11850738..14a0ec796b 100644 --- a/modules/imgproc/include/opencv2/imgproc/types_c.h +++ b/modules/imgproc/include/opencv2/imgproc/types_c.h @@ -389,6 +389,7 @@ enum MorphShapes_c CV_SHAPE_RECT =0, CV_SHAPE_CROSS =1, CV_SHAPE_ELLIPSE =2, + CV_SHAPE_DIAMOND =3, CV_SHAPE_CUSTOM =100 //!< custom structuring element }; diff --git a/modules/imgproc/src/morph.dispatch.cpp b/modules/imgproc/src/morph.dispatch.cpp index 0cb50ec368..714050ccf1 100644 --- a/modules/imgproc/src/morph.dispatch.cpp +++ b/modules/imgproc/src/morph.dispatch.cpp @@ -138,7 +138,7 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor) int r = 0, c = 0; double inv_r2 = 0; - CV_Assert( shape == MORPH_RECT || shape == MORPH_CROSS || shape == MORPH_ELLIPSE ); + CV_Assert( shape == MORPH_RECT || shape == MORPH_CROSS || shape == MORPH_ELLIPSE || shape == MORPH_DIAMOND ); anchor = normalizeAnchor(anchor, ksize); @@ -151,6 +151,11 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor) c = ksize.width/2; inv_r2 = r ? 1./((double)r*r) : 0; } + else if( shape == MORPH_DIAMOND ) + { + r = ksize.height/2; + c = ksize.width/2; + } Mat elem(ksize, CV_8U); @@ -163,6 +168,16 @@ Mat getStructuringElement(int shape, Size ksize, Point anchor) j2 = ksize.width; else if( shape == MORPH_CROSS ) j1 = anchor.x, j2 = j1 + 1; + else if( shape == MORPH_DIAMOND ) + { + int dy = std::abs(i - r); + if( dy <= r ) + { + int dx = r - dy; + j1 = std::max( c - dx, 0 ); + j2 = std::min( c + dx + 1, ksize.width ); + } + } else { int dy = i - r; diff --git a/modules/imgproc/test/test_structuring_element.cpp b/modules/imgproc/test/test_structuring_element.cpp new file mode 100644 index 0000000000..7ca500e10a --- /dev/null +++ b/modules/imgproc/test/test_structuring_element.cpp @@ -0,0 +1,17 @@ +#include "test_precomp.hpp" + +namespace opencv_test { namespace { + +TEST(MorphShapes, getStructuringElementDiamond) +{ + cv::Mat element = cv::getStructuringElement(cv::MORPH_DIAMOND, cv::Size(5,5)); + cv::Mat expected = (cv::Mat_(5,5) << + 0,0,1,0,0, + 0,1,1,1,0, + 1,1,1,1,1, + 0,1,1,1,0, + 0,0,1,0,0); + EXPECT_EQ(0, cvtest::norm(element, expected, cv::NORM_INF)); +} + +}} // namespace