一、引言

形态学滤波器可以用于检测图像的不同特征,这一节,我们介绍利用形态学检测灰度级图像的边缘和角点。

二、原理介绍

形态学还是将图像的灰度级看成地理里面的“等高线”,亮的地方看成山峰,暗的地方看成低谷,中间部分就是峭壁。形态学中的腐蚀(eroded),会把山谷扩展,峭壁减少;相反的,膨胀(dilated)会把山谷减少,峭壁扩展。在两种情况下,中间(大块的山峰和低谷)不会改变太多。

利用形态学进行边界检测原理很简单,就是将一幅图片分别经过腐蚀和膨胀处理,然后图像相减,在进行门限处理,消除小的噪声。(当然也可以利用腐蚀或者膨胀后的图像和源图像相比,得到的边界会相对细些)当结构元素越大,得到的边界越粗。

利用形态学进行角点检测比较麻烦。角点检测分别使用十字角,菱形,X形,方形四种结构元素进行腐蚀和膨胀。(1)我们以方形图像为源图像介绍,第一步对图像进行结构元为十字角的膨胀,然后在进行结构元为菱形的腐蚀;第二步对源图像进行结构元为X形的膨胀,在进行结构元为方形的腐蚀。第一步的作用是检测直角角点,第二步的作用是检测斜45°的角点。

       

图1 源图像,图2 Dilate with a cross ,图3 Erode with a diamond,图4 Dilate with a X,图5 Erode with a square ,图6 Corner Image,图7 Corners on Image

(2)选取等腰三角形和等边三角形作为源图像进行处理,可以看出与四个机构元处理的结果

      

图1 源图像,图2 Dilate with a cross ,图3 Erode with a diamond,图4 Dilate with a X,图5 Erode with a square ,图6 Corner Image,图7 Corners on Image

三、opencv函数介绍

头文件:#include <opencv2/imgproc/imgproc.hpp>

函数定义:

//! erodes the image (applies the local minimum operator)
CV_EXPORTS_W void erode( InputArray src, OutputArray dst, InputArray kernel,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue() );//! dilates the image (applies the local maximum operator)
CV_EXPORTS_W void dilate( InputArray src, OutputArray dst, InputArray kernel,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue() );//! applies an advanced morphological operation to the image
CV_EXPORTS_W void morphologyEx( InputArray src, OutputArray dst,int op, InputArray kernel,Point anchor=Point(-1,-1), int iterations=1,int borderType=BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue() );

函数参数:

erode(腐蚀函数): InputArray src,  原图像
                                        OutputArray dst,  结果输出图像
                                        InputArray kernel,  结构元素
                                        Point anchor=Point(-1,-1),  结构元素的原点 
                                       int iterations=1,  迭代次数

dilate(膨胀函数):InputArray src,  原图像
                                         OutputArray dst,  结果输出图像
                                         InputArray kernel,  结构元素
                                         Point anchor=Point(-1,-1),  结构元素的原点 
                                         int iterations=1,  迭代次数

morphologyEx :      InputArray src,  原图像
                                       OutputArray dst,  结果输出图像
                                        int op,cv::MORPH_OPEN(打开) cv::MORPH_CLOSE(关闭) cv::MORPH_GRADIENT(梯度)
                                        InputArray kernel,  结构元素
                                       Point anchor=Point(-1,-1),  结构元素的原点 
                                       int iterations=1,  迭代次数

四、例程

程序:

morphoFeatures.h

#if !defined MORPHOF
#define MORPHOF#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>class MorphoFeatures {private:// threshold to produce binary imageint threshold;// structuring elements used in corner detectioncv::Mat cross;cv::Mat diamond;cv::Mat square;cv::Mat x;void applyThreshold(cv::Mat& result) {// Apply threshold on resultif (threshold>0)cv::threshold(result, result, threshold, 255, cv::THRESH_BINARY_INV);}public:MorphoFeatures() : threshold(-1), cross(5,5,CV_8U,cv::Scalar(0)), diamond(5,5,CV_8U,cv::Scalar(1)), square(5,5,CV_8U,cv::Scalar(1)),x(5,5,CV_8U,cv::Scalar(0)){// Creating the cross-shaped structuring elementfor (int i=0; i<5; i++) {cross.at<uchar>(2,i)= 1;cross.at<uchar>(i,2)= 1;                                   }// Creating the diamond-shaped structuring elementdiamond.at<uchar>(0,0)= 0;diamond.at<uchar>(0,1)= 0;diamond.at<uchar>(1,0)= 0;diamond.at<uchar>(4,4)= 0;diamond.at<uchar>(3,4)= 0;diamond.at<uchar>(4,3)= 0;diamond.at<uchar>(4,0)= 0;diamond.at<uchar>(4,1)= 0;diamond.at<uchar>(3,0)= 0;diamond.at<uchar>(0,4)= 0;diamond.at<uchar>(0,3)= 0;diamond.at<uchar>(1,4)= 0;// Creating the x-shaped structuring elementfor (int i=0; i<5; i++) {x.at<uchar>(i,i)= 1;x.at<uchar>(4-i,i)= 1;                                  }}void setThreshold(int t) {threshold= t;}int getThreshold() const {return threshold;}cv::Mat getEdges(const cv::Mat &image) {// Get the gradient imagecv::Mat result;cv::morphologyEx(image,result,cv::MORPH_GRADIENT,cv::Mat());// Apply threshold to obtain a binary imageapplyThreshold(result);return result;}cv::Mat getCorners(const cv::Mat &image) {cv::Mat result;// Dilate with a cross cv::dilate(image,result,cross);// Erode with a diamondcv::erode(result,result,diamond);cv::Mat result2;// Dilate with a X   cv::dilate(image,result2,x);// Erode with a squarecv::erode(result2,result2,square);// Corners are obtained by differencing// the two closed imagescv::absdiff(result2,result,result);// Apply threshold to obtain a binary imageapplyThreshold(result);return result;}void drawOnImage(const cv::Mat& binary, cv::Mat& image) {// cv::Mat_<uchar>::const_iterator it= binary.begin<uchar>();//  cv::Mat_<uchar>::const_iterator itend= binary.end<uchar>();cv::Mat_<uchar>::const_iterator it= binary.begin<uchar>();cv::Mat_<uchar>::const_iterator itend= binary.end<uchar>();// for each pixel  for (int i=0; it!= itend; ++it,++i) {if (!*it)cv::circle(image,cv::Point(i%image.step,i/image.step),5,cv::Scalar(255,0,0));}}
};#endif

main.cpp

#include <opencv2/core/core.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include "morphoFeatures.h"int main()
{// Read input imagecv::Mat image= cv::imread("../building.jpg",0);if (!image.data)return 0; // Display the imagecv::namedWindow("Image");cv::imshow("Image",image);// Create the morphological features instanceMorphoFeatures morpho;morpho.setThreshold(40);// Get the edgescv::Mat edges;edges= morpho.getEdges(image);// Display the edge imagecv::namedWindow("Edge Image");cv::imshow("Edge Image",edges);// Get the cornersmorpho.setThreshold(-1);cv::Mat corners;corners= morpho.getCorners(image);cv::morphologyEx(corners,corners,cv::MORPH_TOPHAT,cv::Mat());cv::threshold(corners, corners, 40, 255, cv::THRESH_BINARY_INV);// Display the corner imagecv::namedWindow("Corner Image");cv::imshow("Corner Image",corners);// Display the corner on the imagemorpho.drawOnImage(corners,image);cv::namedWindow("Corners on Image");cv::imshow("Corners on Image",image);cv::waitKey();return 0;
}

源图像 building.jpg

Edge Image.jpg

Corner Image.jpg

Corners on Image.jpg

参考资料:opencv cookbook 2 chapter 5

参考资料下载:http://download.csdn.net/detail/skeeee/5311512

程序下载:http://download.csdn.net/detail/skeeee/5584643

利用形态学检测边缘和角点相关推荐

  1. 有关opencv的学习(17)—形态学滤波器检测边缘和角点

    一.图像特征类型可被分为以下三种: 边缘.角点.斑点 其中,角点是个很特殊的存在.他们在图像中可以轻易地定位,同时,他们在人造物体场景,比如门.窗.桌等出随处可见.因为 角点位于两条边缘的交点处,代表 ...

  2. OpenCV 形态学滤波 边缘及角点检测

    形态学滤波可用于检测图像种指定的特征,可检测灰度图种的直线和角点. 目录 1.创建MorphoFeatures类,实现检测图像特征 2.实现过程: 3.验证结果 1.创建MorphoFeatures类 ...

  3. 角点检测--基于梯度的方法(Moravec角点检测、Harris角点检测、Shi-Tomasi角点检测)

    Moravec Detector Moravec角点检测是第一个提出兴趣点(interest points)的Paper.它的主要思想是:以每个像素为中心,有一个固定的滑动窗口.该方法计算并在八个方向 ...

  4. OpenCV + CPP 系列(卅三)图像特征提取(Harris角点检测、Shi-Tomasi角点检测、自定义角点检测)

    文章目录 一.常用图像特征描述 二.Harris角点检测 演示Harris角点检测 三.Shi-Tomasi角点检测 四.自定义角点检测器 一.常用图像特征描述 SIFT.SURF.HOG.Haar. ...

  5. OpenCV —— 角点检测之 Harris 角点检测、Shi-Tomasi 角点检测、FAST 角点检测

    角点检测 Harris 角点检测 实现原理 OpenCV 函数 优化 Shi-Tomasi 角点检测 实现原理 OpenCV 函数 FAST 角点检测 实现原理 OpenCV 函数 优化 在图像处理和 ...

  6. opencv图像处理梯度边缘和角点

    转自:http://blog.sina.com.cn/s/blog_4b9b714a0100c9f7.html 梯度.边缘和角点 Sobel 使用扩展 Sobel 算子计算一阶.二阶.三阶或混合图像差 ...

  7. OpenCV角点检测之Harris角点检测

    本篇文章中,我们一起探讨了OpenCV中Harris角点检测相关的知识点,学习了OpenCV中实现Harris角点检测的cornerHarris函数的使用方法.此博文一共有两个配套的麻雀虽小但五脏俱全 ...

  8. OpenCV之feature2d 模块. 2D特征框架(1)Harris 角点检测子 Shi-Tomasi角点检测子 定制化创建角点检测子 亚像素级的角点检测 特征点检测

    Harris 角点检测子 目标 本教程中我们将涉及: 有哪些特征?它们有什么用? 使用函数 cornerHarris 通过 Harris-Stephens方法检测角点. 理论 有哪些特征? 在计算机视 ...

  9. 结构张量用于区分平坦、边缘、角点区域

    1.结构张量原理 此处所说的张量不是相对论或黎曼几何里的张量,黎曼几何的张量好多论文都叫张量场了.也不是数学界还没研究明白的对矩阵进行扩展的高阶张量,主要是张量分解.这里的结构张量就是一个矩阵,一个对 ...

最新文章

  1. 微软拟对Office 2007增添新功能 增强安全性
  2. DL框架之PyTorch:深度学习框架PyTorch的简介、安装、使用方法之详细攻略
  3. NYOJ 括号配对问题
  4. 人的一生能交多少朋友?
  5. 用python画树_Python+Turtle动态绘制一棵树实例分享
  6. 工厂模式理解_工厂模式
  7. opencore0.6.3_Ubuntu 18.04 源码编译安装 PHP 7.3
  8. 监督式学习、 非监督式学习、强化学习
  9. JS语法apply()与call()的区别
  10. Qt使用MSVC编译器关闭“C4100:未引用的形参”警告的方法
  11. TrueCrypt使用方法及详细教程介绍
  12. ESP8266 教程1 — ESP8266硬件平台介绍
  13. excel打不开html格式的文件,excel文件打不开提示格式无效怎么解决【图文】
  14. 2021-11-07算法的本质是什么?
  15. Android面试题精选——再聊Android-Handler机制-2,android物联网开发李天祥源代码
  16. 转:Flutter做出剑气效果
  17. php 搜索关键字,PHP获取搜索关键字有关问题_PHP教程
  18. 给力!低代码开发平台广州流辰信息科技助您增辉创价值!
  19. 【MT7620】MT7620 WiFi驱动增加无线终端连接实时协商速率功能
  20. Unity3D鼠标、WASD空格键盘控制摄像机及esc键退出C#脚本

热门文章

  1. 获取拼音并生成随机编号
  2. 2D游戏中常见的碰撞检测算法思路(附详细思路及部分源码)
  3. Wix 软件打包(一)
  4. Android基础知识巩固系列 Android之四大组件——ContentProvider(内容提供者)
  5. 从零学Java(16)之赋值运算符
  6. 腾讯Bugly、腾讯移动分析和OneApm功能对比
  7. Mybatis延时加载
  8. 直击 COSCon'21 开源年会颁奖现场 感谢一路有你相伴
  9. Halcon 算子 get_contour_global_attrib_xld
  10. 三十.结束语句之break语句