赞
踩
个人博客:http://www.chenjianqu.com/
原文链接:http://www.chenjianqu.com/show-10.html
数学形态学(Mathematical morphology) 是一门建立在格论和拓扑学基础之上的图像分析学科,是数学形态学图像处理的基本理论。其基本的运算包括:腐蚀和膨胀、开运算和闭运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换等。
数学形态学操作可以分为二值形态学和灰度形态学,灰度形态学由二值形态学扩展而来。数学形态学有2个基本的运算,即腐蚀和膨胀,而腐蚀和膨胀通过结合又形成了开运算和闭运算。 开运算就是先腐蚀再膨胀,闭运算就是先膨胀再腐蚀。本文介绍二值形态学变换。
二值形态学变换就是对二值图像进行数学形态学操作。常用操作有腐蚀、膨胀、开运算、闭运算等。腐蚀和膨胀是对白色部分(高亮部分)而言的,不是黑色部分。 膨胀就是图像中的高亮部分进行膨胀,“邻域扩张”,效果图拥有比原图更大的高亮区域。腐蚀就是原图中高亮部分被腐蚀,“邻域被蚕食”,效果图拥有比原图更小的高亮区域。
腐蚀操作会收缩(细化)图像中物体的轮廓,可以用来断开(分离)物体间的连接,消除离散点,代价是导致物体的面积比原来的面积要小。。
腐蚀的数学表达式为:
该式子表示用结构B腐蚀A,需要在B中定义一个参考点。B像在A上面移动(如图像卷积操作一般)。
1. 用结构元素,扫描图像的每一个像素
2. 用结构元素与其覆盖的二值图像做“与”操作
3. 如果都为1,结果图像的该像素为1。否则为0
也就是查找被处理图像中能不能找到和结构元素相同的矩阵。如果存在那么中心点所对应的点就为1,否则为0.下图为腐蚀操作的示意图:
代码实现:
- Mat ErosionTransform(Mat &src,int kernelSize)
- {
- Mat dst(src.rows, src.cols, src.type(), Scalar(0));
- Mat kernel = Mat::ones(kernelSize, kernelSize, CV_8UC1);
- if (src.channels() == 1) {
- int rowsSub = int(kernel.rows / 2);
- int colsSub = int(kernel.cols / 2);
- for (int i = rowsSub; i < src.rows-rowsSub; i++) {
- for (int j = colsSub; j < src.cols-colsSub; j++)
- {
- int flag = 0;
- for (int ki = 0; ki < kernel.rows; ki++)
- {
- for (int kj = 0; kj < kernel.cols; kj++)
- {
- int i_ = i+ki - rowsSub;
- int j_ = j+kj - colsSub;
- if (src.at<uchar>(i_, j_) == 0 && kernel.at<uchar>(ki, kj) >0)
- flag = 1;
- }
- }
- if(!flag)
- dst.at<uchar>(i, j) = 255;
- else
- dst.at<uchar>(i, j) = 0;
- }
- }
- }
- return dst;
- }
说明:
当输入的核是一个3x3的全1矩阵时,运行效果图如下:
膨胀操作会扩大(粗化)图像中物体的轮廓,可以用来弥补(填充)物体间的孔洞,强化离散点,代价是导致物体的面积比原来的面积要大。
膨胀的公式如下:
膨胀是和腐蚀运算相反的操作,膨胀的步骤如下:
1. 用结构元素,扫描图像的每一个像素
2. 用结构元素与其覆盖的二值图像做“与”操作
3. 如果都为0,结果图像的该像素为0。否则为1
也就是在结构元素覆盖范围下,只要有一个像素符和结构元素像素相同,那么中心点对应点就为1,否则为0.
代码实现如下:
- Mat DialateTransform(Mat &src, int kernelSize)
- {
- Mat dst(src.rows, src.cols, src.type(), Scalar(0));
- Mat kernel = Mat::ones(kernelSize, kernelSize, CV_8UC1);
- if (src.channels() == 1) {
- int rowsSub = int(kernel.rows / 2);
- int colsSub = int(kernel.cols / 2);
- for (int i = rowsSub; i < src.rows - rowsSub; i++) {
- for (int j = colsSub; j < src.cols - colsSub; j++)
- {
- int flag = 0;
- for (int ki = 0; ki < kernel.rows; ki++)
- {
- for (int kj = 0; kj < kernel.cols; kj++)
- {
- int i_ = i + ki - rowsSub;
- int j_ = j + kj - colsSub;
- if (src.at<uchar>(i_, j_) >0 && kernel.at<uchar>(ki, kj) >0)
- flag = 1;
- }
- }
- if (!flag)
- dst.at<uchar>(i, j) =0;
- else
- dst.at<uchar>(i, j) = 255;
- }
- }
- }
- return dst;
- }
当kernelSize=3时,运行效果图如下:
闭运算是使用同一结构元对图像进行先膨胀后腐蚀的操作,可以用来弥合较窄的间断和细长的沟壑,消除物体间小的孔洞,填补轮廓线中的断裂。
闭运算=先进行膨胀运算,在进行腐蚀运算,其运行示意图如下,
代码实现:
- Mat ClosingTransform(Mat &src, int kernelSize)
- {
- Mat dialateImg = DialateTransform(src, kernelSize);
- return ErosionTransform(dialateImg, kernelSize);
- }
开运算是使用同一结构元对图像进行先腐蚀后膨胀的操作,可以用来平滑物体的轮廓,断开物体间较窄的连接,消除物体边沿尖锐的突出部分。
开运算 = 先腐蚀运算,再膨胀运算.示意图如下:
代码实现:
- Mat OpeningTransform(Mat &src, int kernelSize)
- {
- Mat erosionImg = ErosionTransform(src, kernelSize);
- return DialateTransform(erosionImg, kernelSize);
- }
-
- kernelSize=5
参考文献
[1] 百度百科.数学形态学.https://baike.baidu.com/item/%E6%95%B0%E5%AD%A6%E5%BD%A2%E6%80%81%E5%AD%A6/2594174.
[2]CSDN博客:chaolei_9527. 数学形态学运算——腐蚀、膨胀、开运算、闭运算.https://blog.csdn.net/chaolei3/article/details/79618602.2018-03-20
[3]CSDN博客:青雲-吾道乐途. 膨胀与腐蚀的彻底击破.https://blog.csdn.net/qq_37059483/article/details/77878829.2017-09-07
[4]CSDN博客:HanShanBuLeng. 形态学应用——图像开运算与闭运算.https://blog.csdn.net/hanshanbuleng/article/details/80657148.2018-06-11
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。