摘要:

形态学一般指生物学中研究动物和植物结构的一个分支。用数学形态学(也称图像代数)表示以形态为基础对图像进行分析的数学工具。

基本思想是用具有一定形态的结构元素去度量和提取图像中的对应形状以达到对图像分析和识别的目的。

形态学图像处理的基本运算有:

  • 膨胀和腐蚀(膨胀区域填充,腐蚀分割区域)
  • 开运算和闭运算(开运算去除噪点,闭运算填充内部孔洞)
  • 击中与击不中
  • 顶帽变换,黑帽变换

形态学的应用:消除噪声、边界提取、区域填充、连通分量提取、凸壳、细化、粗化等;分割出独立的图像元素,或者图像中相邻的元素;求取图像中明显的极大值区域和极小值区域;求取图像梯度


在讲各种形态学操作之前,先来看看结构元素:

膨胀和腐蚀操作的核心内容是结构元素。(后面的开闭运算等重要的也是结构元素的设计,一个合适的结构元素的设计可以带来很好的处理效果)

OpenCV里面的API介绍:

Mat kernel = getStructuringElement(int shape,Size ksize,Point anchor);
shape //结构元素的定义:形状 (MORPH_RECT \MORPH_CROSS(交叉形) \MORPH_ELLIPSE);
ksize //结构元素大小;
anchor //锚点 默认是Point(-1, -1)意思就是中心像素,也可以自己指定

一,腐蚀和膨胀

腐蚀和膨胀是最基本的形态学操作,腐蚀和膨胀都是针对白色部分(高亮部分)而言的。

  • 膨胀就是使图像中高亮部分扩张,效果图拥有比原图更大的高亮区域(是求局部最大值的操作)
  • 腐蚀是原图中的高亮区域被蚕食,效果图拥有比原图更小的高亮区域(是求局部最小值的操作)

膨胀与腐蚀能实现多种多样的功能,主要如下:

1、消除噪声
2、腐蚀分割(isolate)出独立的图像元素,膨胀在图像中连接(join)相邻的元素。
3、寻找图像中的明显的极大值区域或极小值区域
4、求出图像的梯度

opencv中膨胀/腐蚀API:(两者相同)

void dilate/erode( const Mat& src,   //输入图像(任意通道的)
Mat& dst, //输出图像
const Mat& element, //结构元素
Point anchor=Point(-1,-1), //中心位置锚点
int iterations=1, //操作次数。省略时为默认值1。
int borderType=BORDER_CONSTANT, //边缘填充类型
const Scalar& borderValue //填充值(默认即可)
)

opencv实现:

    Mat src1 = imread("D:/opencv练习图片/腐蚀膨胀.png");
Mat src_erode, src_dilate;
imshow("原图", src1);
Mat kernel = getStructuringElement(MORPH_RECT, Size(60, 60), Point(-1, -1));
erode(src1, src_erode, kernel, Point(-1, -1),2);
dilate(src1, src_dilate, kernel, Point(-1, -1),2);
imshow("腐蚀", src_erode);
imshow("膨胀", src_dilate);

膨胀:                                                                                腐蚀:

1️⃣腐蚀操作的原理就是求局部最小值的操作,并把这个最小值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐减少。

2️⃣膨胀操作的原理就是求局部最大值的操作,并把这个最大值赋值给参考点指定的像素。这样就会使图像中的高亮区域逐渐增长。

二,高阶形态学变换

对于更加高级形态学变换就要用到morphologyEx()函数了,其函数原型如下:

void morphologyEx(
InputArray src, //输入图像
OutputArray dst, //输出图像
int op, //形态学运算类型
InputArray kernel, //结构元素
Point anchor = Point(-1,-1), //锚点
int iterations = 1, //运算次数
int borderType = BORDER_CONSTANT,
)

对于输入参数op(形态学运算类型)有以下几种参数可以设置:

  • MORPH_ERODE(腐蚀)
  • MORPH_DILATE(膨胀)
  • MORPH_OPEN(开运算)
  • MORPH_CLOSE(闭运算)
  • MORPH_GRADIENT(形态学梯度,即膨胀图减腐蚀图)
  • MORPH_TOPHAT(顶帽运算)
  • MORPH_BLACKHAT(底帽运算)
  • MORPH_HITMISS(击中与击不中)

开运算和顶帽运算

开运算就是先腐蚀膨胀。作用:用来消除图像中细小对象,在纤细点处分离物体和平滑较大物体的边界而有不明显改变其面积和形状。

顶帽运算就是图与原图的开运算的差值图像。作用:由于开运算可以消除较暗背景下的较亮区域,那么用原图减开运算后的结果就可以得到原图中灰度较亮的区域(即得到开运算消除的区域)

opencv实现:

    Mat src1 = imread("D:/opencv练习图片/开运算.png");
Mat src_open, src_tophat;
imshow("原图", src1);
Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1));
morphologyEx(src1, src_open, MORPH_OPEN, kernel,Point(-1, -1));//开运算
morphologyEx(src1, src_tophat, MORPH_TOPHAT, kernel, Point(-1, -1));//顶帽运算
imshow("开运算", src_open);
imshow("顶帽运算", src_tophat);

开运算:                                                                      顶帽运算:(可以用来观察开运算的效果)

 闭运算和底帽运算

闭运算就是先膨胀后腐蚀。作用:用来填充目标内部的细小孔洞(fill hole),将断开的邻近目标连接,在不明显改变物体面积和形状的情况下平滑其边界。

底帽运算就是图与原图的闭运算的差值图像。作用:闭运算是去噪点的过程,所以黑帽操作实质上保留的是噪点的部分。

opencv实现:

    Mat src1 = imread("D:/opencv练习图片/闭运算.png");
Mat src_close, src_blackhat;
imshow("原图", src1);
Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1));
morphologyEx(src1, src_close, MORPH_CLOSE, kernel,Point(-1, -1));//闭运算
morphologyEx(src1, src_blackhat, MORPH_BLACKHAT, kernel, Point(-1, -1));//底帽运算
imshow("闭运算", src_close);
imshow("底帽运算", src_blackhat);

闭运算:                                                                    底帽运算:

 形态学梯度(求二值图边缘)

图像形态学的梯度跟我们前面介绍的图像卷积计算出来的梯度有本质不同,形态学梯度可以帮助我们获得连通组件的边缘与轮廓,实现图像轮廓或者边缘提取。

根据使用的形态学操作不同,形态学梯度又分为:

  • 基本梯度(图像膨胀与腐蚀操作之间的差值)
  • 内梯度(输入图像与腐蚀之间的差值)
  • 外梯度(膨胀与输入图像之间的差值)

opencv实现:

    Mat src1 = imread("D:/opencv练习图片/腐蚀膨胀.png");
Mat src_giad1, src_exter,src_inter,src_dilate,src_erode;
imshow("原图", src1);
Mat kernel = getStructuringElement(MORPH_RECT, Size(7, 7), Point(-1, -1));
//基本梯度
morphologyEx(src1, src_giad1, MORPH_GRADIENT, kernel,Point(-1, -1));
imshow("基本梯度", src_giad1);
//外梯度
morphologyEx(src1, src_dilate, MORPH_DILATE, kernel, Point(-1, -1));
subtract(src_dilate, src1, src_exter);//求差值
imshow("外梯度", src_exter);
//内梯度
morphologyEx(src1, src_erode, MORPH_ERODE, kernel, Point(-1, -1));
subtract(src1, src_erode, src_inter);
imshow("内梯度", src_inter);

外梯度:                                                                      内梯度:

内外梯度区别不是很大。。。

击中与击不中

形态学的击中击不中操作, 击中击不中也是基础形态学操作组合,它可以实现对象的细化跟剪枝操作,根据结构元素不同,可以提取二值图像中的一些特殊区域,得到我们想要的结果。并且击中击不中操作在二值图像的模式匹配跟发现上也非常有用

Hit-miss算法步骤(两次腐蚀,求交集):

击中击不中变换是形态学中用来检测特定形状所处位置的一个基本工具。它的原理就是使用腐蚀;如果要在一幅图像A上找到B形状的目标,我们要做的是:

  • 首先,建立一个比B大的结构元素B1;使用B1对图像A进行腐蚀,得到图像假设为A_B1;
  • 其次,用B减去B1,从而得到结构元素B2(B2-B);使用B2对图像A的补集进行腐蚀,得到图像假设为A_B2;
  • 然后,A_B1与A_B2取交集;得到的结果就是B的位置。

opencv实战(利用击中与击不中,提取网绳的结点位置):

Mat src = imread("D:/opencv练习图片/击中与击不中.png");
imshow("原图", src);
// 二值图像
Mat gray, binary, hitImg;
cvtColor(src, gray, COLOR_BGR2GRAY);
//高斯滤波
Mat gauss;
GaussianBlur(gray, gauss, Size(5, 5), 0, 0);
//二值化
threshold(gauss, binary, 0, 255, THRESH_BINARY_INV | THRESH_OTSU);
imshow("binary", binary);
// 定义结构元素
Mat se = getStructuringElement(MORPH_CROSS, Size(11, 11), Point(-1, -1));
// 击中击不中
morphologyEx(binary, hitImg, MORPH_HITMISS, se);
imshow("击中击不中", hitImg);
//膨胀一下
Mat openImg;
Mat kern2 = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(hitImg, openImg, MORPH_OPEN, kern2, Point(-1, -1), 2);
imshow("dilate", openImg);
//寻找轮廓
vector<vector<Point>>contours;
vector<Vec4i>hie;
findContours(openImg, contours, hie, RETR_TREE, CHAIN_APPROX_SIMPLE, Point());
for (size_t i = 0; i < contours.size(); i++)
{
double area = contourArea(contours[i]);
if (area < 20.0)continue;
Rect rect = boundingRect(contours[i]);
rectangle(src, rect, Scalar(0, 0, 255), 1, 8); }
// 显示
imshow("结果", src);

参考链接:(8条消息) Opencv图像识别从零到精通(18)-------击中击不中_小木匠的博客-CSDN博客

OpenCV中一个最容易搞错的形态学操作 - 云+社区 - 腾讯云 (tencent.com)

opencv——形态学深究(分析和应用)的更多相关文章

  1. [OpenCV-Python] OpenCV 中视频分析 部分 VI

    部分 VI视频分析 OpenCV-Python 中文教程(搬运)目录 39 Meanshift 和 和 Camshift 目标 • 本节我们要学习使用 Meanshift 和 Camshift 算法在 ...

  2. OpenCV源码分析:RGB到其他色彩空间的转换

    1.流程调用图 2.部分代码分析 //模板函数进行颜色空间的转换 template <typename Cvt> void CvtColorLoop(const Mat& src, ...

  3. opencv face-detection 代码分析 (1)人脸识别后的数据

    2014,3,16   老师的工作建议如下:   1. 与四民沟通下,把openCV这边的源代码和调用接口发给四民同时抄送给我. 2. 根据openCV的实时检测结果,实现对屏幕的调整(下周一前基本实 ...

  4. OPENCV形态学算法-2

    一.漫水填充算法 该算法通过一个指定的种子点,来分析整张图片上的像素,并设置像素差异阈值,在阈值类的点,最后变成相同的颜色.该方法通过上下限和连通方式来达到不同的连通效果. 该方法常用与标记和分离图像 ...

  5. OPENCV形态学操作1

    形态学操作是指基于形状的一系列图像处理操作,包括膨胀,腐蚀,二值化,开运算,闭运算,顶帽算法,黑帽算法,形态学梯度等,最基本的形态学操作就是膨胀和腐蚀. 一.膨胀 首先需要明确一个概念,膨胀和腐蚀都是 ...

  6. opencv 形态学操作应用-提取水平与垂直线

    adaptiveThreshold(~gray_src, binImg, , ADAPTIVE_THRESH_MEAN_C, THRESH_BINARY, , -); #include <ope ...

  7. opencv::形态学操作

    形态学操作 开操作- open 闭操作- close 形态学梯度- Morphological Gradient 顶帽 – top hat 黑帽 – black hat 开操作- open 先腐蚀后膨 ...

  8. 基于OpenCV.Net连通域分析进行文本块分割

    上一次通过投影的方式进行了文本块分割,(见 https://www.cnblogs.com/BoyTNT/p/11812323.html )但这种方法有很大的局限性,要求分行清晰.不能有字符跨多行.不 ...

  9. OpenCV常用函数分析

    1. 聚类:将拥有最相似属性的数据归为一类. K-means聚类: python调用格式:compacness, labels, centers = cv2.kmeans(data, K, crite ...

随机推荐

  1. 计算机体系结构——CH3存储系统

    计算机体系结构--CH3存储系统 右键点击查看图像,查看清晰图像 X-mind 计算机体系结构--CH3存储系统 存储系统原理 主要性能 速度 容量 价格 两种存储系统 Cache与主存储器 虚拟存储 ...

  2. vue-cli2 项目中使用node-sass

    公司的项目,换了个电脑要重新安装一下依赖,但是直接npm install的时候报错了,提示node-sass未安装成功. 然后直接npn install node-sass --save 的时候还是下 ...

  3. 透视HTTP协议,带你拨开纷繁复杂的表象

    一个HTTP,打趴80%面试者! HTTP是一个在计算机世界里专门在两点之间传输文字.图片.音频.视频等超文本数据的约定和规范.如果你不懂HTTP协议,那就相当于是个只有半桶水的程序员. 在这个专栏中 ...

  4. 字符串函数的实现(三)之strcat

    C语言中的字符串函数有如下这些 获取字符串长度 strlen 长度不受限制的字符串函数 strcpy strcat strcmp 长度受限制的字符串函数 strncpy strncat strncmp ...

  5. Github仓库master分支到main分支迁移指南

    1 概述 2020年10月1日后,Github会将所有新建的仓库的默认分支从master修改为main,这就导致了一些旧仓库主分支是master,新仓库主分支是main的问题,这在有时候会带来一些麻烦 ...

  6. 《鸟哥的Linux私房菜》部分章节学习笔记整理

    简介 此笔记为<鸟哥的Linux私房菜·基础学习篇>中部分章节的学习笔记. 目录 0 计算机概论 1 Linux是什么与如何学习 2 主机规划与磁盘分区 3 安装CentOS7.x 4 首 ...

  7. day17.网络编程2+进程

    1 加入链接循环的套接字服务端 1.1 服务端 ''' 2.1 基于文件类型的套接字家族 套接字家族的名字:AF_UNIX unix一切皆文件,基于文件的套接字调用的就是底层的文件系统来取数据,两个套 ...

  8. Mybatis3源码笔记(一)环境搭建

    1. 源码下载 地址:https://github.com/mybatis/mybatis-3.git. 国内访问有时确实有点慢,像我就直接先fork.然后从git上同步到国内的gitte上,然后在i ...

  9. 1.8.8- textarea控件(文本域)

    如果需要大量的信息,就需要用到<textarea>标签,通过testarea控件可以轻松创建多行文本输入框,其基本语法如下: <textarea cols="每行的字数&q ...

  10. system分区解锁

    前言 获取root权限,解锁system 步骤 手机设置 设置--更多设置--开发者选项--USB调试给打开 电脑操作 打开cmd adb devices 执行命令 adb root &&am ...