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

测试代码test_dilate.cpp:

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

dilate 函数的实现(源码)相关推荐

  1. python判断素数的函数_Python素数prime函数练习_Python源码实操

    Python素数prime函数练习_Python源码实操 素数prime函数练习 1) 写一个函数isprime(x) 判断x是否为素数,如果是素数,返回True,否则返回False def ispr ...

  2. python中split函数源代码_Pandas.split()函数用法及源码

    Pandas.split()函数用法及源码 发布时间:2018-05-08 10:44, 浏览次数:1092 , 标签: Pandas split Python数据分析博文汇总 * Pandas重复值 ...

  3. Vue源码流程图(函数名与源码对应)

    这里写目录标题 概览 1. 变化侦查 1.1 Observer流程图 2. vdom虚拟DOM 2.1 创建节点createElm 2.2 更新节点patchVnode 2.3 更新子节点 updat ...

  4. 【逐函数讲解ORB_SLAM2源码】4.计算umax

    视频讲解 逐函数讲解ORB_SLAM2源码|4.计算umax 原理讲解 /*** 1. 加载 Euroc 数据集 QQ交流群 925533821 * 2. 加载 Euroc 数据集参数 对图像进行去畸 ...

  5. linux内核第一个函数,通过内核源码看函数调用之前世今生 - 极光 - CSDN博客

    通过内核源码看函数调用之前世今生 作者:杨小华 栈(Stack):一个有序的积累或堆积 韦氏词典 对每一位孜孜不倦的程序员来说,栈已深深的烙在其脑海中,甚至已经发生变异.栈可以用来传递函数参数.存储局 ...

  6. vue函数如何调用其他函数?_从源码中学Vue(一)生命周期中的钩子函数的那点事儿...

    欢迎来到我的<从源码中学Vue>专题系列文章,更多精彩内容持续更新中,欢迎关注 :) Vue作为当下前端最流行的框架之一,在国内占绝对的优势.所以接下来我们一起来学习它吧! 我不会像其它人 ...

  7. usestate中的回调函数_React Hooks 源码解析(3):useState

    React 源码版本: v16.11.0 源码注释笔记: airingursb/react​github.com 在写本文之前,事先阅读了网上了一些文章,关于 Hooks 的源码解析要么过于浅显.要么 ...

  8. C++演示std :: sort(),std :: reverse()的函数(附完整源码)

    @[TOC](C++演示std :: sort(),std :: reverse()的函数) C++演示std :: sort(),std :: reverse()的函数完整源码(定义,实现,main ...

  9. c++获得总和S所需的最小硬币数量的函数(附完整源码)

    C++获得总和S所需的最小硬币数量的函数 获得总和S所需的最小硬币数量的函数算法的完整源码(定义,实现,main函数测试) 获得总和S所需的最小硬币数量的函数算法的完整源码(定义,实现,main函数测 ...

  10. 如何理解android的函数,通过Android源码理解回调函数

    概述 我们先看一下维基百科对回调函数的定义: 在计算机程序设计中,回调函数,或简称回调(Callback 即call then back 被主函数调用运算后会返回主函数),是指通过函数参数传递到其它代 ...

最新文章

  1. bom表_MicroProfile 2.2 BOM导入支持
  2. 招聘面试的套路和原则
  3. javascript--弹出对话框 四种对话框 获得用户输入值 .
  4. java queue源码_java源码解读--queue
  5. 使用React,Redux和Router进行真正的集成测试
  6. 解决exe文件在别人电脑上运行缺失文件情况
  7. Linux日常运维管理技巧(二)Linux防火墙:你可以ping别人,别人ping不了你、转发、代理
  8. CS229——线性回归
  9. 刷程序对车危害_刷ecu对车有影响吗?会伤车吗?
  10. 微信小程序picker空白
  11. Java飞机大战超全版(plus版)
  12. Tomcat8的下载、安装、配置
  13. 无人驾驶入门1:无人驾驶概览
  14. 计算机一级IF函数应用,计算机一级if函数怎么用
  15. 【深度学习】2.1深度学习的实用层面
  16. 使用LIME解释CNN
  17. 6月13日云栖精选夜读:数梦工场完成A轮7.5亿融资 三个维度构建“新型互联网”
  18. 关于C语言二级指针正确使用总结
  19. Java架构师必备知识体系
  20. 动态面板:拖动滑块解锁(1)

热门文章

  1. Java怎么打开ppt_Java 加密PPT(设置打开密码、编辑权限密码)
  2. 编程题刷题笔记(包括leetcode和各种公司笔试题)
  3. 用VC实现洪水攻击程序
  4. 计算机电源用什么端子,常见的端子连接线有哪些?
  5. web端 刷卡器_新品推荐:WEB端免开发IC卡读卡器
  6. 自从学了Python,全网资源随心下!
  7. 一篇dbus移植的点点滴滴
  8. 建行技术岗计算机知识,建设银行广州分行信息技术岗招聘笔试经验
  9. EXCEL如何分组排序,如何标记序,如何取指定的第n笔?
  10. 利用python实现果蝇优化算法