OpenCV C++ 图像形态学处理实战:腐蚀、膨胀及七种高级运算详解
数字图像处理中,形态学操作是基于形状的分析工具。本文基于 OpenCV 和 C++,详解图像腐蚀、膨胀的原理与代码实现,并介绍利用 morphologyEx 进行开运算、闭运算、顶帽变换、黑帽变换及形态学梯度的实用技巧,提供从基础到进阶的完整解决方案。
结果或目标:掌握形态学核心操作
形态学处理主要用于提取图像中对分割和描述有意义的区域分量,如边界、轮廓、凸包等。其核心在于使用结构元素(Kernel)与输入图像进行卷积操作。我们将依次实现腐蚀、膨胀及其组合运算,并通过自定义函数理解底层逻辑,最后统一通过标准库函数完成复杂变换。
准备条件
在进行形态学操作前,建议先将图像转换为二值图像(黑白图像),因为形态学操作在二值图像上的视觉效果最为明显且稳定。需要包含 #include <opencv2/opencv.hpp> 命名空间为 cv。常用的结构元素可通过 cv::getStructuringElement 获取,支持矩形(MORPH_RECT)、十字形(MORPH_CROSS)和椭圆形(MORPH_ELLIPSE)。
真实操作顺序
第1步:图像腐蚀(Erosion)
目的:收缩或细化前景物体,常用于去除白色噪声点或断开连接。
原理:用结构元素扫描图像,当结构元素覆盖区域内所有像素均为前景色(白色/高值)时,锚点对应像素保留前景;否则变为背景色(黑色/低值)。简而言之,取局部最小值。
使用内置 erode 函数
入口:直接调用 cv::erode。
// 构造 3x3 矩形结构元素
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
// 执行腐蚀,迭代3次以增强效果
Mat image_erosion;
erode(image_bw, image_erosion, element, Point(-1, -1), 3);
imshow("image_erosion", image_erosion);
参数说明:src 为输入图,dst 为输出图,kernel 为结构元素,iterations 为迭代次数(越大腐蚀越严重),anchor 默认中心 Point(-1,-1)。
自定义腐蚀实现
通过遍历局部窗口寻找最小值模拟该过程:
void erode_my(Mat &src, Mat &dst, int size) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
uchar minV = 255;
// 遍历邻域寻找最小像素值
for (int yi = i - size / 2; yi <= i + size / 2; ++yi) {
for (int xi = j - size / 2; xi <= j + size / 2; ++xi) {
if (xi < 0 || xi >= src.cols || yi < 0 || yi >= src.rows) continue;
minV = min(minV, src.at<uchar>(yi, xi));
}
}
dst.at<uchar>(i, j) = minV;
}
}
}
当结构尺寸扩大至 9x9 时,自定义函数效果与内置函数基本一致。展示对比:
第2步:图像膨胀(Dilation)
目的:扩张前景物体边缘,填充孔洞或连接邻近物体。
原理:若结构元素覆盖区域内存在任意前景像素,则锚点对应变为前景。简而言之,取局部最大值。膨胀与腐蚀互为对偶运算。
使用内置 dilate 函数
Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
Mat image_dilate;
// 执行膨胀,迭代9次显著扩大主体
;dilate(image_bw, image_dilate, element, Point(-1, -1), 9);
imshow("image_dilate", image_dilate);
自定义膨胀实现
void dilate_my(Mat& src, Mat& dst, int size) {
for (int i = 0; i < src.rows; ++i) {
for (int j = 0; j < src.cols; ++j) {
uchar maxV = 0;
// 遍历邻域寻找最大像素值
for (int yi = i - size / 2; yi <= i + size / 2; ++yi) {
for (int xi = j - size / 2; xi <= j + size / 2; ++xi) {
if (xi < 0 || xi >= src.cols || yi < 0 || yi >= src.rows) continue;
maxV = max(maxV, src.at<uchar>(yi, xi));
}
}
dst.at<uchar>(i, j) = maxV;
}
}
}
同样在 9x9 尺寸下,自定义膨胀效果与内置函数吻合:
第3步:开运算与闭运算
开运算(Opening):先腐蚀后膨胀。作用是平滑轮廓、断开狭窄连接、消除细小噪声(假设前景为白)。
原图与开运算效果:
可通过两次调用的方式实现,也可直接使用形态学通用函数:
Mat open_image;
Mat kernel = getStructuringElement(MORPH_RECT, Size(3, 3));
morphologyEx(image_bw, open_image, MORPH_OPEN, kernel); // 方法二:推荐
闭运算(Closing):先膨胀后腐蚀。作用是填充前景物体内的小孔、连接邻近物体。
Mat close_image;
morphologyEx(image_bw, close_image, MORPH_CLOSE, kernel); // 方法二:推荐
第4步:高级形态学变换
以下操作均可通过 cv::morphologyEx 一次性完成,定义明确且效率更高。
1. 顶帽变换(Top Hat)
原理:原始图像 - 开运算结果。用于分离比周围亮一些的区域,常用来提取噪声或背景不均匀时的文字前景。
手动实现逻辑如下:
// 方法一:内置标志位
morphologyEx(image_bw, top_hat, MORPH_TOPHAT, kernel);
// 方法二:显式减法
subtract(image_bw, open_image, top_hat_manual);
// 或使用绝对差值检测差异
absdiff(image_bw, open_image, top_hat_diff);
2. 黑帽变换(Black Hat)
原理:闭运算结果 - 原始图像。用于提取前景内部的小孔或深色斑点。
// 方法一:内置标志位
morphologyEx(image_bw, black_hat, MORPH_BLACKHAT, kernel);
// 方法二:闭运算减原图
subtract(close_image, image_bw, black_hat_manual);
// 注意顺序:闭-原
3. 形态学梯度(Morphological Gradient)
原理:膨胀图 - 腐蚀图。能够勾勒出物体的轮廓边界,适合二值图像的边界提取。
// 方法一:内置标志位
morphologyEx(image_bw, gradient, MORPH_GRADIENT, kernel);
// 方法二:膨胀减腐蚀
absdiff(dilated_img, eroded_img, gradient_manual);
morphologyEx 函数参数详解
该函数是形态学操作的统一入口,原型如下:
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
);
op关键枚举值:
MORPH_ERODE (0):腐蚀MORPH_DILATE (1):膨胀MORPH_OPEN (2):开运算MORPH_CLOSE (3):闭运算MORPH_GRADIENT (4):梯度MORPH_TOPHAT (5):顶帽MORPH_BLACKHAT (6):黑帽MORPH_HITMISS (7):击中-击不中
borderType边框处理方式:
BORDER_CONSTANT:固定值填充(默认)BORDER_REPLICATE:边缘复制BORDER_REFLECT:镜像反射
完成判断
运行上述代码后,观察窗口显示的结果:
- 腐蚀后的物体应当变小,孤立噪点消失;
- 膨胀后的物体变大,断裂处连接;
- 开运算去除了毛刺但保持了物体大致面积;
- 闭运算填平了内部空洞;
- 顶帽和黑帽分别突出了亮背景和暗背景下的微小特征;
- 梯度清晰展示了物体边缘。
简要总结
形态学处理是计算机视觉预处理的关键环节。对于简单的腐蚀和膨胀,可直接使用 erode 和 dilate;而对于组合逻辑复杂的开闭运算及顶帽、黑帽等操作,推荐使用 morphologyEx 以提高代码可读性和执行效率。理解结构元素的大小与形状对最终图像处理结果的直接影响,有助于在实际项目中调整参数以达到最佳效果。
以上就是 OpenCV C++ 图像形态学处理(含腐蚀、膨胀、开闭运算及高级变换)的详细内容,更多关于 OpenCV 数字图像处理基于 C++ 的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









