几种基于膨胀和腐蚀的更高级运算,morphologyEx()函数

既然是基于膨胀和腐蚀的运算,那么再让我们详细了解一下膨胀和腐蚀到底对图像做了什么?

第一种情况,对于二值图像来说
腐蚀:核与其覆盖的图像部分做“与”操作,如果全为1,则该像素点为1,否则为0;也就是0容易得到,图像更多的地方变黑了,白色部分被腐蚀了
膨胀:核与其覆盖的图像部分做“与”操作,如果全为0,则该像素点为0,否则为1;也就是1容易得到,图像更多的地方变白了,白色部分膨胀了
第二种情况,对于一个灰度图像来说:
腐蚀:某一点的像素值,就是核与图像该部分像素值差的最小值。所以像素值变低比较容易,亮色部分被腐蚀。
膨胀:某一点的像素值,就是核与图像该部分像素值和的最大值。所以像素值变高比较容易,亮色部分膨胀。

1.开运算
先腐蚀后膨胀
作用:放大裂缝和低密度区域,消除小物体,在平滑较大物体的边界时,不改变其面积
2.闭运算
先膨胀后腐蚀
作用:排除小型黑洞,突触了比原图轮廓区域更暗的区域
3.形态学梯度
形态学梯度=膨胀图-腐蚀图
作用:保留图像边缘
4.顶帽(礼帽)
顶帽=原图-开运算
分离邻近点亮一些的斑块,进行背景提取
5.黑帽
黑帽=闭运算-原图
用来分离比邻近点暗一些的斑块
6.更加高级的形态学运算函数——morphologyEx()

下面这个程序:用键盘按键123改变核的形状,用进度条同时改变类型及Size大小,正负代表类型,绝对值代表Size

#include
#include 
#include 
#include 
#include 
#include 
#include  "vector"

using namespace std;
using namespace cv;
//目的:写一个腐蚀/膨胀,顶帽/黑帽,开/闭运算的程序,用控制条控制运算方式及核Size,用键盘控制核类型

Mat g_src,g_dst;
int g_nOpenCloseNum=0;
int g_nErodeDilateNum=0;
int g_nTopBlackNum=0;
int g_nMaxNum=10;

static void on_nOpenCloseSlide(int,void);
static void on_nErodeDilateSlide(int,void);
static void on_nTopBlackSlide(int,void*);

int g_nShapeNum=MORPH_RECT;

int main()
{
g_src=imread(“cui.jpg”); //这里前面错误的写为Mat g_src=imread(“cui.jpg”)相当于把g_src变成了局部变量
namedWindow(“腐蚀/膨胀”);
namedWindow(“顶帽/黑帽”);
namedWindow(“开/闭”);

createTrackbar("Size-10","开/闭",&g_nOpenCloseNum,g_nMaxNum*2+1,on_nOpenCloseSlide);
createTrackbar("Size-110","腐蚀/膨胀",&g_nErodeDilateNum,g_nMaxNum*2+1,on_nErodeDilateSlide);
createTrackbar("Size-120","顶帽/黑帽",&g_nTopBlackNum,g_nMaxNum*2+1,on_nTopBlackSlide);

while(1)
{
int c;
//cin>>c;
//执行回调函数
cout<<"循环1次"<0)
	morphologyEx(g_src,g_dst,MORPH_OPEN,element);
else
	morphologyEx(g_src,g_dst,MORPH_CLOSE,element);
imshow("开/闭",g_dst);

}
static void on_nErodeDilateSlide(int,void*)
{
cout<<“已经调用回调函数二:on_nErodeDilateSlide”<0)
erode(g_src,g_dst,element);
else
dilate(g_src,g_dst,element);

imshow("腐蚀/膨胀",g_dst);

}
static void on_nTopBlackSlide(int,void*)
{
cout<<“已经调用回调函数三:on_nTopBlackSlide”<0)
morphologyEx(g_src,g_dst,MORPH_TOPHAT,element);
else
morphologyEx(g_src,g_dst,MORPH_BLACKHAT,element);
imshow(“顶帽/黑帽”,g_dst);
}

程序问题:1.createTrackbar不执行回调函数为什么也可以运行呢?

经试验,不写回调函数的语句,确实没有调用回调函数,但是为什么之前的例子没关系呢?

确实,不写回调函数可以,但是回调函数承担着给函数赋初值的作用,如果不写回调函数,第一,刚打开图片时是没有画面的,必须点击一下进度条才有画面。

第二,如果在循环开始不赋初值的话,当改变核形状的时候,图片不会自己转变,而是要点一下进度条才有变化。

所以,赋初值,也就是写回调函数,还是很有必要的。

2.waitkey()如何获取获取按键

waitkey灵活运用注意如下几点

当参数delay中为负,则无穷等待

否则等待delay ms.

返回值是按键值 否则返回-1

当参数为空,则一直等待按键当前线程等待

waitkey只对显示图像窗口有效,对控制台无效

3.程序中出现一个错误,那就是只有开闭运算会随着进度条的调整,图像发生变化,其他两种运算不会变化。这里有一个细节,第一下拖动进度条会变化,后面就不动了。还有一个细节,每次显示图片,开闭运算的图片总是第一个显示出来。

猜想原因是:

(1).和三个函数调用的顺序有关,经改变,情况依旧,所以排除该种可能。

(2).另外两个函数的书写有问题,经检查,没问题。

(3).偏差与element没有设置为局部变量,所以函数之间互相影响,这一点是错误,已经更正了。

错误原因找到了 offset的定义出了问题,每一个函数的offset定义不同,但是我因为是复制的,所以都一样了,所以第一个图变了,其他的offset就确定了,导致了错误。

4.3通道RGB图片可以吗?答案是可以。


你可能感兴趣的:(几种基于膨胀和腐蚀的更高级运算,morphologyEx()函数)