OpenCV入门(17):图像处理之形态学操作
图像形态学操作是图像处理中的一种重要技术,主要用于处理二值图像(即黑白图像)。
OpenCV 中的图像形态学操作是图像处理中的重要工具,通过腐蚀、膨胀、开运算、闭运算和形态学梯度等操作,可以实现对图像的噪声去除、对象分离、边缘检测等效果。掌握这些操作有助于更好地处理和分析图像数据。
以下是 OpenCV 中常用的形态学操作及其函数:
| 操作 | 函数 | 说明 | 应用场景 |
|---|---|---|---|
| 腐蚀 | cv::erode() |
用结构元素扫描图像,如果结构元素覆盖的区域全是前景,则保留中心像素。 | 去除噪声、分离物体。 |
| 膨胀 | cv::dilate() |
用结构元素扫描图像,如果结构元素覆盖的区域存在前景,则保留中心像素。 | 连接断裂的物体、填充空洞。 |
| 开运算 | cv::morphologyEx() |
先腐蚀后膨胀。 | 去除小物体、平滑物体边界。 |
| 闭运算 | cv::morphologyEx() |
先膨胀后腐蚀。 | 填充小孔洞、连接邻近物体。 |
| 形态学梯度 | cv::morphologyEx() |
膨胀图减去腐蚀图。 | 提取物体边缘。 |
| 顶帽运算 | cv::morphologyEx() |
原图减去开运算结果。 | 提取比背景亮的细小物体。 |
| 黑帽运算 | cv::morphologyEx() |
闭运算结果减去原图。 | 提取比背景暗的细小物体。 |
一、腐蚀(erode)
腐蚀操作是一种缩小图像中前景对象的过程。腐蚀操作通过将结构元素与图像进行卷积,只有当结构元素完全覆盖图像中的前景像素时,中心像素才会被保留,否则会被腐蚀掉。
1.1 API
erode( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
src:表示需要处理的原始图像dst:表示处理后的输出图像kernel:结构元素anchor:锚点,默认中心像素;iterations:迭代处理的次数;
1.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_erosion; // 定义输入图像,灰度图像,腐蚀图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 腐蚀
Mat se = getStructuringElement(MORPH_RECT, Size(5, 5)); // 构造矩形结构元素
erode(image_gray, image_erosion, se, Point(-1, -1), 1); // 执行腐蚀操作
imshow("image_erosion", image_erosion);
waitKey(0);
return 0;
}
腐蚀操作是使用最小像素值用来替换锚点的像素,可以看到通过取最小值,使得图像中形状变细,效果图如下所示:

二、膨胀(dilate)
膨胀操作与腐蚀相反,它是一种扩大图像中前景对象的过程。膨胀操作通过将结构元素与图像进行卷积,只要结构元素与图像中的前景像素有重叠,中心像素就会被保留。
2.1 API
dilate( InputArray src, OutputArray dst, InputArray kernel,
Point anchor = Point(-1,-1), int iterations = 1,
int borderType = BORDER_CONSTANT,
const Scalar& borderValue = morphologyDefaultBorderValue() );
src:表示需要处理的原始图像dst:表示处理后的输出图像kernel:结构元素anchor:锚点,默认中心像素;iterations:迭代处理的次数;
2.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_dilate; // 定义输入图像,灰度图像,膨胀图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 膨胀
Mat se = getStructuringElement(0, Size(5, 5)); // 构造矩形结构元素
dilate(image_gray, image_dilate, se, Point(-1, -1), 1); // 执行膨胀操作
imshow("image_dilate", image_dilate);
waitKey(0);
return 0;
}
膨胀操作是使用最小像素值用来替换锚点的像素,可以看到通过取最大值,使得图像形状变粗,效果图如下所示:

三、开运算(open)
开运算是先腐蚀后膨胀的组合操作。开运算主要用于去除图像中的小噪声或分离连接的对象。
开操作的作用:
- 常用于图像中的噪声消除
- 通过对小对象放在背景中来从图像的前景中移除;
3.1 API
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() );
src:源图像。dst:与源图像大小和类型相同的目标图像。op:形态学操作类型,开运算使用MORPH_OPEN。kernel:结构元素。 它可以使用getStructuringElement创建。anchor:与内核锚定位置。 负值表示锚点位于内核中心。iterations:应用腐蚀和膨胀的次数。borderType:像素外推法。borderValue:边界值在恒定边界的情况下。 默认值具有特殊含义。
3.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_morphologyEx; // 定义输入图像,灰度图像,开运算图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 开运算
Mat se = getStructuringElement(0, Size(5, 5)); // 构造矩形结构元素
morphologyEx(image, image_morphologyEx, MORPH_OPEN, se, Point(-1, -1), 1); // 执行开运算
imshow("image_morphologyEx", image_morphologyEx);
waitKey(0);
return 0;
}
开运算可以去除图像中的小噪声,同时保留图像中的主要前景对象。效果图如下所示:

四、闭运算(close)
闭运算是先膨胀后腐蚀的组合操作。闭运算主要用于填补前景对象中的小孔或连接断裂的对象。
闭操作的作用:
- 能够填充间隙来闭合形状的操作,也可以用来去除噪声;
- 通过把背景中的小对象来放入前景中来移除前景的小孔;
4.1 API
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() );
-
op:形态学操作类型,开运算使用MORPH_CLOSE。 -
该函数和其它参数跟开运算的一样,这里不再赘述。
4.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_morphologyEx; // 定义输入图像,灰度图像,闭运算图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 闭运算
Mat se = getStructuringElement(MORPH_RECT, Size(5, 5)); // 构造矩形结构元素
morphologyEx(image, image_morphologyEx, MORPH_CLOSE, se, Point(-1, -1), 1); // 执行闭运算
imshow("image_morphologyEx", image_morphologyEx);
waitKey(0);
return 0;
}
闭运算可以填补前景对象中的小孔,同时保留图像中的主要前景对象。效果图如下所示:

五、形态学梯度(Morphological Gradient)
形态学梯度是膨胀图像与腐蚀图像的差值,又称基本梯度(其他还包括内部梯度, 方向梯度)。形态学梯度主要用于提取图像中前景对象的边缘。
形态学梯度的作用:
- 通过获取图像的膨胀和腐蚀之间的差异,绘制围绕形状的边界;
5.1 API
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() );
-
op:形态学操作类型,开运算使用MORPH_GRADIENT。 -
该函数和其它参数跟开运算的一样,这里不再赘述。
5.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_morphologyEx; // 定义输入图像,灰度图像,形态学梯度图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 形态学梯度
Mat se = getStructuringElement(MORPH_RECT, Size(5, 5)); // 构造矩形结构元素
morphologyEx(image, image_morphologyEx, MORPH_GRADIENT, se, Point(-1, -1), 1);
imshow("image_morphologyEx", image_morphologyEx);
waitKey(0);
return 0;
}
形态学梯度可以提取图像中前景对象的边缘,常用于边缘检测。效果图如下所示:

六、顶帽(Top hat)
顶帽是原始图像减去图像开运算的结果,用于提取比背景亮的细小物体。
顶帽的作用:
- 从图像中提取更精细的细节或者图像的噪声;
6.1 API
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() );
-
op:形态学操作类型,顶帽使用MORPH_TOPHAT。 -
该函数和其它参数跟开运算的一样,这里不再赘述。
6.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_morphologyEx; // 定义输入图像,灰度图像,顶帽图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 顶帽
Mat se = getStructuringElement(MORPH_RECT, Size(5, 5)); // 构造矩形结构元素
morphologyEx(image, image_morphologyEx, MORPH_TOPHAT, se, Point(-1, -1), 1);
imshow("image_morphologyEx", image_morphologyEx);
waitKey(0);
return 0;
}
效果图如下所示:

七、黑帽(Black hat)
黑帽是图像闭运算操作减去原始图像的结果,用于提取比背景暗的细小物体。。
黑帽的作用:
- 得到图像内部的小孔,或者前景色中的小黑点,即从图像中提取更精细的细节;
7.1 API
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() );
-
op:形态学操作类型,黑帽使用MORPH_GRADIENT。 -
该函数和其它参数跟开运算的一样,这里不再赘述。
7.2 示例代码
#include<iostream>
#include<opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main()
{
Mat image, image_gray, image_morphologyEx; // 定义输入图像,灰度图像,黑帽图像
image = imread("font.jpg"); // 读取图像;
if (image.empty())
{
cout << "读取错误" << endl;
return -1;
}
imshow("image", image);
// 转换为灰度图像
cvtColor(image, image_gray, COLOR_BGR2GRAY);
// 黑帽
Mat se = getStructuringElement(MORPH_RECT, Size(5, 5)); // 构造矩形结构元素
morphologyEx(image, image_morphologyEx, MORPH_BLACKHAT, se, Point(-1, -1), 1);
imshow("image_morphologyEx", image_morphologyEx);
waitKey(0);
return 0;
}
效果图如下所示:


浙公网安备 33010602011771号