一、学习目标
- 理解什么是开运算、闭运算、形态学梯度、顶帽和黑帽
- 学会使用OpenCV实现上述的图像形态学操作
- 使用综合性的例子进行实验
二、各种操作简介
1、开运算
开运算:先腐蚀后膨胀,表达公式为:
dst = open(src, element) = dilate(erode(src, element), element)
开运算可以用来消除图像中的细小对象(前提是黑色为类背景,类白色为前景),在纤细点处分离物体和平滑较大物体的边界而又不明显改变其面积和形状。
例如,看看下面的例子。左边的图像是原始图像,右边的图像是应用开运算变换后的结果。我们可以看到白色小点消失了。

OpenCV中,使用函数cv::morphologyEx实现开运算,其函数原型为:
void cv::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() )
- 参数 src: 源图像。信道的数量可以是任意的。深度应该是CV_8U、CV_16U、CV_16S、CV_32F或CV_64F之一
- 参数 dst: 大小和类型与源图像相同的输出图像
- 参数 op: 指定形态学操作的类型,请参见MorphTypes,实现开操作时指定为MORPH_OPEN
- 参数 kernel: 结构元素。它可以使用getStructuringElement创建
- 参数 anchor: 锚定在内核中的位置。负值表示锚点在内核中心
- 参数 iterations: 开运算(其它运算也是如此)迭代的次数
- 参数 borderType: 图像边界处像素填充方法,见BorderTypes不支持BORDER_WRAP
- 参数 borderValue: 指定图像边界像素填充方法为常量时的配套函数
函数cv::morphologyEx可以使用腐蚀和膨胀作为基本操作来执行高级形态学操作。任何操作都可以就地完成。对于多通道图像,每个通道都是独立处理的。通过指定不同的op实现不同的形态学操作,op的取值见下表:
| 参数取值 | 取值说明 |
|---|---|
| MORPH_OPEN | 开运算,dst=open(src,element)=dilate(erode(src,element)) |
| MORPH_CLOSE | 闭运算,dst=close(src,element)=erode(dilate(src,element)) |
| MORPH_GRADIENT | 形态学梯度,dst=morph_grad(src,element)=dilate(src,element)−erode(src,element) |
| MORPH_TOPHAT | 顶帽,dst=tophat(src,element)=src−open(src,element) |
| MORPH_BLACKHAT | 黑帽,dst=blackhat(src,element)=close(src,element)−src |
| MORPH_HITMISS | “hit or miss”,只支持CV_8UC1二进制图像 |
可见,对于形态学操作的其它操作,也只需要改变op的值即可,所以后面的相关操作就只是简单地介绍原理,相应的函数API不再赘述。
注意: 迭代次数是应用腐蚀或膨胀操作的次数。例如,具有2次迭代的开运算(MORPH_OPEN)等效于依次应用:腐蚀->腐蚀->膨胀->膨胀(而不是腐蚀->膨胀->腐蚀->膨胀)。
使用实例:
先上传一张实验用图供大家下载:

实验代码:
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc,char **argv)
{
char fileName[] = "O:\\CSDN\\MORPH.png";
Mat src = imread(fileName, IMREAD_COLOR);
if (src.empty())
{
cout << "couldn't open image: " << fileName << ",please check out!\n";
system("pause");
return EXIT_FAILURE;
}
// 定义结构元素,可以自行尝试不同的SIZE,去除小物体(噪声)的效果不同
Mat kernel = getStructuringElement(MORPH_RECT, Size(5, 5), Point(-1, -1));
Mat dst;
// 执行开运算
morphologyEx(src, dst, MORPH_OPEN, kernel);
namedWindow("Original", WINDOW_AUTOSIZE);
moveWindow("Original", 200, 200);
namedWindow("MORPH_OPEN", WINDOW_AUTOSIZE);
moveWindow("MORPH_OPEN", src.cols + 200, 200);
imshow("Original", src);
imshow("MORPH_OPEN", dst);


7950

被折叠的 条评论
为什么被折叠?



