OPenCV高级编程——OPenCV形态学之腐蚀、膨胀、开运算、闭运算、形态学梯度等详解
图像形态学是一种基于数学形态学的理论和技术,广泛应用于数字图像处理、计算机视觉和模式识别等领域。它主要通过对图像中的形状和结构元素(也称为内核或模板)进行操作,来实现图像的增强、去噪、特征提取等目的。本文将详细介绍OpenCV中C++语言支持的几种基本形态学操作,包括腐蚀、膨胀、开运算、闭运算、形态学梯度等。
目录
引言
图像形态学是一种基于数学形态学的理论和技术,广泛应用于数字图像处理、计算机视觉和模式识别等领域。它主要通过对图像中的形状和结构元素(也称为内核或模板)进行操作,来实现图像的增强、去噪、特征提取等目的。本文将详细介绍OpenCV中C++语言支持的几种基本形态学操作,包括腐蚀、膨胀、开运算、闭运算、形态学梯度等。
形态学基础
结构元素(Structuring Element)
结构元素是一种小的图像模板,用于定义形态学操作的特征和行为。它通常是一个小的二值图像,用于描述待处理图像中的局部结构。常见的结构元素包括方形、圆形、十字形等。在OpenCV中,可以使用cv::getStructuringElement
函数来生成这些结构元素。
函数原型
在 C++ 中,getStructuringElement
函数的原型如下:
Mat cv::getStructuringElement(int shape, Size ksize, Point anchor=Point(-1,-1))
参数说明
- shape:结构元素的形状。OpenCV 提供了几种预定义的形状,如矩形(
MORPH_RECT
)、交叉形(MORPH_CROSS
)、椭圆形(MORPH_ELLIPSE
)等。 - ksize:结构元素的大小,使用
Size
类型表示,即宽度和高度。 - anchor:结构元素的锚点位置,即中心点。如果设置为
Point(-1,-1)
,则表示锚点位于结构元素的中心。
返回值
函数返回一个 Mat
对象,该对象是一个二值图像,表示了结构元素。
基本形态学操作
腐蚀(Erosion)
腐蚀是一种通过结构元素对图像进行局部最小值滤波的形态学操作,它会使图像中的边界部分逐渐缩小。腐蚀操作常用于去除图像中的噪声、细化边缘、分离紧密相连的物体等。
函数声明:
void cv::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
:腐蚀操作的迭代次数。borderType
:边界填充类型。borderValue
:当borderType
为BORDER_CONSTANT
时,用于填充图像边缘的值。
代码示例:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// 加载图像
Mat src = imread("C:/Users/Administrator/Desktop/777.jpg");
if (src.empty()) {
cout << "Could not open or find the image!" << endl;
return -1;
}
// 显示原始图像
namedWindow("Original Image", WINDOW_AUTOSIZE);
imshow("Original Image", src);
// 创建腐蚀操作所需的结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); // 使用3x3的矩形结构元素
// 创建一个与原始图像相同大小和类型的Mat对象用于存储腐蚀后的图像
Mat eroded;
// 应用腐蚀操作
erode(src, eroded, element);
// 显示腐蚀后的图像
namedWindow("Eroded Image", WINDOW_AUTOSIZE);
imshow("Eroded Image", eroded);
// 等待任意键盘按键后退出
waitKey(0);
return 0;
}
膨胀(Dilation)
膨胀是腐蚀的相反操作,它通过结构元素对图像进行局部最大值滤波,使图像中的边界部分逐渐扩张。膨胀操作常用于填充图像中的空洞、连接物体等。
函数声明(与腐蚀类似,但操作原理相反):
void cv::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
:膨胀操作的迭代次数。borderType
:边界填充类型。borderValue
:当borderType
为BORDER_CONSTANT
时,用于填充图像边缘的值。
代码示例:
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main() {
// 加载图像
Mat src = imread("C:/Users/Administrator/Desktop/777.jpg");
if (src.empty()) {
cout << "Could not open or find the image!" << endl;
return -1;
}
// 显示原始图像
namedWindow("Original Image", WINDOW_AUTOSIZE);
imshow("Original Image", src);
// 创建膨胀操作所需的结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3)); // 使用3x3的矩形结构元素
// 创建一个与原始图像相同大小和类型的Mat对象用于存储膨胀后的图像
Mat dilated;
// 应用膨胀操作
dilate(src, dilated, element);
// 显示膨胀后的图像
namedWindow("Dilated Image", WINDOW_AUTOSIZE);
imshow("Dilated Image", dilated);
// 等待任意键盘按键后退出
waitKey(0);
return 0;
}
开运算(Opening)
开运算是先进行腐蚀操作,再进行膨胀操作的组合操作。它常用于去除小的噪声,并保留图像中的主要结构。
示例代码:
Mat structureElement = getStructuringElement(MORPH_RECT, Size(5,5), Point(-1,-1));
morphologyEx(src, dst, MORPH_OPEN, structureElement);
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
// 读取图像
Mat src = imread("C:/Users/Administrator/Desktop/777.jpg", IMREAD_GRAYSCALE); // 假设我们处理的是灰度图像
if (src.empty()) {
std::cerr << "Could not read the image." << std::endl;
return 1;
}
// 创建输出图像
Mat dst;
// 定义结构元素
// 这里我们使用一个3x3的矩形结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
// 应用开运算
morphologyEx(src, dst, MORPH_OPEN, element);
// 显示原始图像和处理后的图像
imshow("Original Image", src);
imshow("Opening Result", dst);
// 等待按键操作
waitKey(0);
return 0;
}
闭运算(Closing)
闭运算是先进行膨胀操作,再进行腐蚀操作的组合操作。它常用于填充小的空洞,并连接图像中的断裂结构。
示例代码:
Mat structureElement = getStructuringElement(MORPH_RECT, Size(5,5), Point(-1,-1));
morphologyEx(src, dst, MORPH_CLOSE, structureElement);
#include <opencv2/opencv.hpp>
using namespace cv;
int main() {
// 读取图像
Mat src = imread("C:/Users/Administrator/Desktop/777.jpg", IMREAD_GRAYSCALE); // 假设我们处理的是灰度图像
if (src.empty()) {
std::cerr << "Could not read the image." << std::endl;
return 1;
}
// 创建输出图像
Mat dst;
// 定义结构元素
// 这里我们使用一个3x3的矩形结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
// 应用开运算
morphologyEx(src, dst, MORPH_CLOSE, element);
// 显示原始图像和处理后的图像
imshow("Original Image", src);
imshow("Closing Result", dst);
// 等待按键操作
waitKey(0);
return 0;
}
高级形态学操作
形态学梯度(Morphological Gradient)
形态学梯度是膨胀和腐蚀之间的差异,它常用于检测图像中的边缘和轮廓。
示例代码(使用morphologyEx
函数):
Mat structureElement = getStructuringElement(MORPH_RECT, Size(3,3), Point(-1,-1));
morphologyEx(src, gradient, MORPH_GRADIENT, structureElement);
顶帽(Top Hat)
顶帽是原图与开运算结果之间的差值,常用于从图像中提取更精细的细节。
示例代码:
morphologyEx(src, tophat, MORPH_TOPHAT, structureElement);
黑帽(Black Hat)
黑帽是闭运算与原图之间的差值,同样用于从图像中提取更精细的细节,但通常用于分离比邻近点暗的斑块。
示例代码:
morphologyEx(src, blackhat, MORPH_BLACKHAT, structureElement);
结论
OpenCV提供的形态学操作功能强大且灵活,能够处理各种复杂的图像处理任务。通过合理使用腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽和黑帽等操作,我们可以有效地对图像进行去噪、增强、特征提取等处理。
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)