dilate 函数的实现(源码)

来源:互联网 发布:centos升级python2.7 编辑:程序博客网 时间:2024/06/06 12:49

          文章从自己的QQ(632846506)7年前的日志中移过来的。

       数学形态学可以作为图像的一种滤波算法--形态学滤波。滤波中用到的滤波器(kernal)即为结构元素。结构元素往往是由一个特殊的形状构成,如线条、矩形、圆等。

OpenCV中的dilate函数支持多通道,各个通道膨胀处理过程独立。膨胀针对白色部分(高亮部分)。膨胀即是求局部最大值的操作,图像A与核B作卷积运算,计算核B覆盖区域的像素点的最大值,并把这个值赋值给锚点(anchor point)指定的像素。

Dilation:

(1)、This operations consists of convoluting an image A with some kernel(B), which can have any shape or size, usually a square or circle.

(2)、The kernel B has a defined anchor point, usually being the center of the kernel.

(3)、As the kernel B is scanned over the image, we compute the maximal pixel value overlapped by B and replace the image pixel in the anchor point position with that maximal value. As you can deduce, this maximizing operation causes bright regions within an image to “grow” (therefore the name dilation).


目前fbc_cv库中支持uchar和float两种数据类型,经测试,与OpenCV3.1结果完全一致。

实现代码dilate.cpp:

[cpp] view plain copy
  1. // fbc_cv is free software and uses the same licence as OpenCV  
  2. // Email: fengbingchun@163.com  
  3.   
  4. #ifndef FBC_CV_DILATE_HPP_  
  5. #define FBC_CV_DILATE_HPP_  
  6.   
  7. /* reference: include/opencv2/imgproc.hpp 
  8.               modules/imgproc/src/morph.cpp 
  9. */  
  10.   
  11. #include <typeinfo>  
  12. #include "core/mat.hpp"  
  13. #include "imgproc.hpp"  
  14. #include "filterengine.hpp"  
  15. #include "core/core.hpp"  
  16. #include "morph.hpp"  
  17.   
  18. namespace fbc {  
  19.   
  20. // Dilates an image by using a specific structuring element  
  21. // \f[\texttt{dst} (x,y) =  \max _{(x',y'):  \, \texttt{element} (x',y') \ne0 } \texttt{src} (x+x',y+y')\f]  
  22. // In case of multi - channel images, each channel is processed independently.  
  23. // support type: uchar/float, multi-channels  
  24. template<typename _Tp, int chs>  
  25. int dilate(const Mat_<_Tp, chs>& src, Mat_<_Tp, chs>& dst, Mat_<uchar, 1>& kernel,  
  26.     Point anchor = Point(-1, -1), int iterations = 1, int borderType = BORDER_CONSTANT, const Scalar& borderValue = Scalar::all(DBL_MAX))  
  27. {  
  28.     FBC_Assert(typeid(uchar).name() == typeid(_Tp).name() || typeid(float).name() == typeid(_Tp).name()); // uchar || float  
  29.     if (dst.empty()) {  
  30.         dst = Mat_<_Tp, chs>(src.rows, src.cols);  
  31.     } else {  
  32.         FBC_Assert(src.rows == dst.rows && src.cols == dst.cols);  
  33.     }  
  34.   
  35.     Size ksize = !kernel.empty() ? kernel.size() : Size(3, 3);  
  36.     anchor = normalizeAnchor(anchor, ksize);  
  37.   
  38.     if (iterations == 0 || kernel.rows * kernel.cols == 1) {  
  39.         src.copyTo(dst);  
  40.         return 0;  
  41.     }  
  42.   
  43.     if (kernel.empty()) {  
  44.         kernel = Mat_<uchar, 1>(1 + iterations * 2, 1 + iterations * 2);  
  45.         getStructuringElement(kernel, MORPH_RECT, Size(1 + iterations * 2, 1 + iterations * 2));  
  46.         anchor = Point(iterations, iterations);  
  47.         iterations = 1;  
  48.     } else if (iterations > 1 && countNonZero(kernel) == kernel.rows * kernel.cols) {  
  49.         anchor = Point(anchor.x*iterations, anchor.y*iterations);  
  50.         kernel = Mat_<uchar, 1>(ksize.height + (iterations - 1)*(ksize.height - 1), ksize.width + (iterations - 1)*(ksize.width - 1));  
  51.         getStructuringElement(kernel, MORPH_RECT,  
  52.             Size(ksize.width + (iterations - 1)*(ksize.width - 1), ksize.height + (iterations - 1)*(ksize.height - 1)), anchor);  
  53.         iterations = 1;  
  54.     }  
  55.   
  56.     anchor = normalizeAnchor(anchor, kernel.size());  
  57.   
  58.     Ptr<BaseRowFilter> rowFilter;  
  59.     Ptr<BaseColumnFilter> columnFilter;  
  60.     Ptr<BaseFilter> filter2D;  
  61.   
  62.     if (countNonZero(kernel) == kernel.rows*kernel.cols) {  
  63.         // rectangular structuring element  
  64.         rowFilter = getMorphologyRowFilter<_Tp, chs>(1, kernel.cols, anchor.x);  
  65.         columnFilter = getMorphologyColumnFilter<_Tp, chs>(1, kernel.rows, anchor.y);  
  66.     } else {  
  67.         filter2D = getMorphologyFilter<_Tp, chs>(1, kernel, anchor);  
  68.     }  
  69.   
  70.     Scalar borderValue_ = borderValue;  
  71.     if (borderType == BORDER_CONSTANT && borderValue_ == Scalar::all(DBL_MAX)) {  
  72.         if (sizeof(_Tp) == 1) // CV_8U  
  73.             borderValue_ = Scalar::all(0.);  
  74.         else // CV_32F  
  75.             borderValue_ = Scalar::all(-FLT_MAX);  
  76.     }  
  77.   
  78.     Ptr<FilterEngine<_Tp, _Tp, _Tp, chs, chs, chs>> f = makePtr<FilterEngine<_Tp, _Tp, _Tp, chs, chs, chs>>(filter2D, rowFilter, columnFilter, borderType, borderType, borderValue_);  
  79.     f->apply(src, dst);  
  80.     for (int i = 1; i < iterations; i++)  
  81.         f->apply(dst, dst);  
  82.   
  83.     return 0;  
  84. }  
  85.   
  86. // namespace fbc  
  87.   
  88. #endif // FBC_CV_DILATE_HPP_  

测试代码test_dilate.cpp:

[cpp] view plain copy
  1. #include "test_dilate.hpp"  
  2. #include <assert.h>  
  3.   
  4. #include <dilate.hpp>  
  5. #include <opencv2/opencv.hpp>  
  6.   
  7. int test_getStructuringElement()  
  8. {  
  9.     for (int elem = 0; elem < 3; elem++) {  
  10.         for (int size = 0; size < 10; size++) {  
  11.             int type;  
  12.             if (elem == 0){ type = fbc::MORPH_RECT; }  
  13.             else if (elem == 1){ type = fbc::MORPH_CROSS; }  
  14.             else if (elem == 2) { type = fbc::MORPH_ELLIPSE; }  
  15.   
  16.             fbc::Mat_<uchar, 1> element(2*size+1, 2*size+1);  
  17.             fbc::getStructuringElement(element, type, fbc::Size(2 * size + 1, 2 * size + 1), fbc::Point(size, size));  
  18.   
  19.             int type_;  
  20.             if (elem == 0){ type_ = cv::MORPH_RECT; }  
  21.             else if (elem == 1){ type_ = cv::MORPH_CROSS; }  
  22.             else if (elem == 2) { type_ = cv::MORPH_ELLIPSE; }  
  23.   
  24.             cv::Mat element_ = cv::getStructuringElement(type_, cv::Size(2 * size + 1, 2 * size + 1), cv::Point(size, size));  
  25.   
  26.             assert(element.rows == element_.rows && element.cols == element.cols && element.step == element_.step);  
  27.             for (int y = 0; y < element.rows; y++) {  
  28.                 const fbc::uchar* p1 = element.ptr(y);  
  29.                 const uchar* p2 = element_.ptr(y);  
  30.   
  31.                 for (int x = 0; x < element.step; x++) {  
  32.                     assert(p1[x] == p2[x]);  
  33.                     if (size == 5)  
  34.                         fprintf(stderr, "%d  ", p1[x]);  
  35.                 }  
  36.                 if (size == 5)  
  37.                     fprintf(stderr, "\n");  
  38.             }  
  39.   
  40.             if (size == 5)  
  41.                 fprintf(stderr, "\n");  
  42.         }  
  43.     }  
  44.   
  45.     return 0;  
  46. }  
  47.   
  48. int test_dilate_uchar()  
  49. {  
  50.     cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1);  
  51.     if (!matSrc.data) {  
  52.         std::cout << "read image fail" << std::endl;  
  53.         return -1;  
  54.     }  
  55.   
  56.     int width = matSrc.cols;  
  57.     int height = matSrc.rows;  
  58.   
  59.     for (int elem = 0; elem < 3; elem++) {  
  60.         for (int size = 0; size < 10; size++) {  
  61.             for (int iterations = 1; iterations < 5; iterations++) {  
  62.                 int type;  
  63.                 if (elem == 0){ type = fbc::MORPH_RECT; }  
  64.                 else if (elem == 1){ type = fbc::MORPH_CROSS; }  
  65.                 else if (elem == 2) { type = fbc::MORPH_ELLIPSE; }  
  66.   
  67.                 fbc::Mat_<uchar, 1> element(2 * size + 1, 2 * size + 1);  
  68.                 fbc::getStructuringElement(element, type, fbc::Size(2 * size + 1, 2 * size + 1), fbc::Point(size, size));  
  69.   
  70.                 int type_;  
  71.                 if (elem == 0){ type_ = cv::MORPH_RECT; }  
  72.                 else if (elem == 1){ type_ = cv::MORPH_CROSS; }  
  73.                 else if (elem == 2) { type_ = cv::MORPH_ELLIPSE; }  
  74.   
  75.                 cv::Mat element_ = cv::getStructuringElement(type_, cv::Size(2 * size + 1, 2 * size + 1), cv::Point(size, size));  
  76.   
  77.                 assert(element.rows == element_.rows && element.cols == element.cols && element.step == element_.step);  
  78.                 for (int y = 0; y < element.rows; y++) {  
  79.                     const fbc::uchar* p1 = element.ptr(y);  
  80.                     const uchar* p2 = element_.ptr(y);  
  81.   
  82.                     for (int x = 0; x < element.step; x++) {  
  83.                         assert(p1[x] == p2[x]);  
  84.                     }  
  85.                 }  
  86.   
  87.                 fbc::Mat3BGR mat1(height, width, matSrc.data);  
  88.                 fbc::Mat3BGR mat2(height, width);  
  89.                 fbc::dilate(mat1, mat2, element, fbc::Point(-1, -1), iterations, 0, fbc::Scalar::all(128));  
  90.   
  91.                 cv::Mat mat1_(height, width, CV_8UC3, matSrc.data);  
  92.                 cv::Mat mat2_;  
  93.                 cv::dilate(mat1_, mat2_, element_, cv::Point(-1, -1), iterations, 0, cv::Scalar::all(128));  
  94.   
  95.                 assert(mat2.rows == mat2_.rows && mat2.cols == mat2_.cols && mat2.step == mat2_.step);  
  96.                 for (int y = 0; y < mat2.rows; y++) {  
  97.                     const fbc::uchar* p1 = mat2.ptr(y);  
  98.                     const uchar* p2 = mat2_.ptr(y);  
  99.   
  100.                     for (int x = 0; x < mat2.step; x++) {  
  101.                         assert(p1[x] == p2[x]);  
  102.                     }  
  103.                 }  
  104.             }  
  105.         }  
  106.     }  
  107.   
  108.     return 0;  
  109. }  
  110.   
  111. int test_dilate_float()  
  112. {  
  113.     cv::Mat matSrc = cv::imread("E:/GitCode/OpenCV_Test/test_images/lena.png", 1);  
  114.     if (!matSrc.data) {  
  115.         std::cout << "read image fail" << std::endl;  
  116.         return -1;  
  117.     }  
  118.     cv::cvtColor(matSrc, matSrc, CV_BGR2GRAY);  
  119.     matSrc.convertTo(matSrc, CV_32FC1);  
  120.   
  121.     int width = matSrc.cols;  
  122.     int height = matSrc.rows;  
  123.   
  124.     for (int elem = 0; elem < 3; elem++) {  
  125.         for (int size = 0; size < 10; size++) {  
  126.             for (int iterations = 1; iterations < 5; iterations++) {  
  127.                 int type;  
  128.                 if (elem == 0){ type = fbc::MORPH_RECT; }  
  129.                 else if (elem == 1){ type = fbc::MORPH_CROSS; }  
  130.                 else if (elem == 2) { type = fbc::MORPH_ELLIPSE; }  
  131.   
  132.                 fbc::Mat_<uchar, 1> element(2 * size + 1, 2 * size + 1);  
  133.                 fbc::getStructuringElement(element, type, fbc::Size(2 * size + 1, 2 * size + 1), fbc::Point(size, size));  
  134.   
  135.                 int type_;  
  136.                 if (elem == 0){ type_ = cv::MORPH_RECT; }  
  137.                 else if (elem == 1){ type_ = cv::MORPH_CROSS; }  
  138.                 else if (elem == 2) { type_ = cv::MORPH_ELLIPSE; }  
  139.   
  140.                 cv::Mat element_ = cv::getStructuringElement(type_, cv::Size(2 * size + 1, 2 * size + 1), cv::Point(size, size));  
  141.   
  142.                 assert(element.rows == element_.rows && element.cols == element.cols && element.step == element_.step);  
  143.                 for (int y = 0; y < element.rows; y++) {  
  144.                     const fbc::uchar* p1 = element.ptr(y);  
  145.                     const uchar* p2 = element_.ptr(y);  
  146.   
  147.                     for (int x = 0; x < element.step; x++) {  
  148.                         assert(p1[x] == p2[x]);  
  149.                     }  
  150.                 }  
  151.   
  152.                 fbc::Mat_<float, 1> mat1(height, width, matSrc.data);  
  153.                 fbc::Mat_<float, 1> mat2(height, width);  
  154.                 fbc::dilate(mat1, mat2, element, fbc::Point(-1, -1), iterations, 0, fbc::Scalar::all(128));  
  155.   
  156.                 cv::Mat mat1_(height, width, CV_32FC1, matSrc.data);  
  157.                 cv::Mat mat2_;  
  158.                 cv::dilate(mat1_, mat2_, element_, cv::Point(-1, -1), iterations, 0, cv::Scalar::all(128));  
  159.   
  160.                 assert(mat2.rows == mat2_.rows && mat2.cols == mat2_.cols && mat2.step == mat2_.step);  
  161.                 for (int y = 0; y < mat2.rows; y++) {  
  162.                     const fbc::uchar* p1 = mat2.ptr(y);  
  163.                     const uchar* p2 = mat2_.ptr(y);  
  164.   
  165.                     for (int x = 0; x < mat2.step; x++) {  
  166.                         assert(p1[x] == p2[x]);  
  167.                     }  
  168.                 }  
  169.             }  
  170.         }  
  171.     }  
  172.   
  173.     return 0;  
  174. }  
         有兴趣的朋友也可以直接从opencv中查找