OpenCV(cv::morphologyEx())
cv::morphologyEx()
是 OpenCV 中的一个重要函数,用于执行图像的高级形态学运算。形态学运算基于图像中像素邻域的形状(通常是二进制图像)来处理图像,用于增强图像的特定特征。
1. 函数原型
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_8UC1
(单通道 8 位)或者CV_8UC3
(多通道彩色图像)。
- 输入图像,可以是灰度图像或二值图像。它的类型通常是
-
dst
:- 输出图像,尺寸和类型与输入图像相同。形态学运算结果会存储在这里。
-
op
:- 形态学运算类型,可以是以下几种:
MORPH_ERODE
: 腐蚀运算,最小化局部像素值。MORPH_DILATE
: 膨胀运算,最大化局部像素值。MORPH_OPEN
: 开运算(先腐蚀后膨胀),用于去除小噪声点。MORPH_CLOSE
: 闭运算(先膨胀后腐蚀),用于填补小孔。MORPH_GRADIENT
: 形态学梯度,膨胀和腐蚀之差,突出物体边界。MORPH_TOPHAT
: 顶帽运算,输入图像与其开运算结果之差,提取比周围亮的区域。MORPH_BLACKHAT
: 黑帽运算,闭运算结果与输入图像之差,提取比周围暗的区域。MORPH_HITMISS
: 击中击不中运算,主要用于形态学模式匹配。
- 形态学运算类型,可以是以下几种:
-
kernel
:- 结构元素(核),形态学运算的关键因素。核可以是矩形、椭圆或十字形,指定了像素邻域的形状。常见的核使用函数
cv::getStructuringElement()
生成。核的尺寸和形状直接影响形态学运算的效果。
- 结构元素(核),形态学运算的关键因素。核可以是矩形、椭圆或十字形,指定了像素邻域的形状。常见的核使用函数
-
anchor
:- 核的锚点,决定形态学运算时哪个点与源图像进行对齐。默认值为
(-1, -1)
,表示锚点在核的中心。
- 核的锚点,决定形态学运算时哪个点与源图像进行对齐。默认值为
-
iterations
:- 运算重复的次数,默认值为 1。如果设置为更大的数值,则形态学运算将重复执行多次,这有助于增强效果。
-
borderType
:- 图像边界的处理方式,决定当核处理图像边界时如何扩展边界。常见值包括:
BORDER_CONSTANT
: 边界填充为常数值。BORDER_REPLICATE
: 复制边界像素。
- 图像边界的处理方式,决定当核处理图像边界时如何扩展边界。常见值包括:
-
borderValue
:- 当
borderType
为BORDER_CONSTANT
时,指定的常数边界值。
- 当
2. 示例
2.1 开运算
#include<iostream>
#include<opencv2/opencv.hpp>
#include<ctime>
using namespace std;
using namespace cv;
int main(void)
{
cv::Mat test = cv::Mat::zeros(64, 64, CV_8UC1);
cv::rectangle(test, cv::Rect(30, 30, 5, 5), 255, -1);
cv::rectangle(test, cv::Rect(20, 20, 2, 2), 255, -1);
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
cv::Mat result;
cv::morphologyEx(test, result, MORPH_OPEN,element);
imshow("original", test);
imshow("result", result);
waitKey(0);
system("pause");
return 0;
}
输出:
2.2 闭运算
#include<iostream>
#include<opencv2/opencv.hpp>
#include<ctime>
using namespace std;
using namespace cv;
int main(void)
{
cv::Mat test = cv::Mat::zeros(64, 64, CV_8UC1);
cv::rectangle(test, cv::Rect(30, 30, 8, 8), 255, -1);
cv::rectangle(test, cv::Rect(33, 33, 2, 2), 0, -1);
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
cv::Mat result;
cv::morphologyEx(test, result, MORPH_CLOSE, element);
imshow("original", test);
imshow("result", result);
waitKey(0);
system("pause");
return 0;
}
输出:
2.3 形态学梯度
#include<iostream>
#include<opencv2/opencv.hpp>
#include<ctime>
using namespace std;
using namespace cv;
int main(void)
{
cv::Mat test = cv::Mat::zeros(64, 64, CV_8UC1);
cv::rectangle(test, cv::Rect(30, 30, 8, 8), 255, -1);
cv::rectangle(test, cv::Rect(33, 33, 2, 2), 0, -1);
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
cv::Mat result;
cv::morphologyEx(test, result, MORPH_CLOSE, element);
imshow("original", test);
imshow("result", result);
waitKey(0);
system("pause");
return 0;
}
输出:
2.4 顶帽运算
#include<iostream>
#include<opencv2/opencv.hpp>
#include<ctime>
using namespace std;
using namespace cv;
int main(void)
{
cv::Mat test = cv::Mat::zeros(64, 64, CV_8UC1);
cv::rectangle(test, cv::Rect(30, 30, 8, 8), 255, -1);
cv::rectangle(test, cv::Rect(32, 28, 2, 2), 255, -1);
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
cv::Mat result,open;
cv::morphologyEx(test, open, MORPH_OPEN, element);
cv::morphologyEx(test, result, MORPH_TOPHAT, element);
imshow("original", test);
imshow("open", open);
imshow("result", result);
waitKey(0);
system("pause");
return 0;
}
输出:
2.5 黑帽运算
#include<iostream>
#include<opencv2/opencv.hpp>
#include<ctime>
using namespace std;
using namespace cv;
int main(void)
{
cv::Mat test = cv::Mat::zeros(64, 64, CV_8UC1);
cv::rectangle(test, cv::Rect(30, 30, 8, 8), 255, -1);
cv::rectangle(test, cv::Rect(33, 30, 2, 2), 0, -1);
cv::Mat element = getStructuringElement(MORPH_RECT, Size(3, 3));
cv::Mat result, close;
cv::morphologyEx(test, close, MORPH_CLOSE, element);
cv::morphologyEx(test, result, MORPH_BLACKHAT, element);
imshow("original", test);
imshow("close", close);
imshow("result", result);
waitKey(0);
system("pause");
return 0;
}
输出:
3. 常见的形态学运算
-
腐蚀 (
MORPH_ERODE
):- 腐蚀运算使得图像中的高亮区域变小,黑色区域变大,通常用于去除噪点。
-
膨胀 (
MORPH_DILATE
):- 膨胀运算使得图像中的高亮区域变大,黑色区域变小,通常用于填补物体中的小孔。
-
开运算 (
MORPH_OPEN
):- 先腐蚀再膨胀,通常用于去除小噪声。
-
闭运算 (
MORPH_CLOSE
):- 先膨胀再腐蚀,通常用于填充小孔和连接物体。
-
形态学梯度 (
MORPH_GRADIENT
):- 膨胀减腐蚀。通常用于提取物体的边缘。
-
顶帽运算 (
MORPH_TOPHAT
):- 原图减开运算图。提取比其邻域亮的部分,通常用于光照不均匀的图像。
-
黑帽运算 (
MORPH_BLACKHAT
):- 闭运算图减原图。提取比其邻域暗的部分,通常用于背景光亮、物体较暗的场景。
4. 应用场景
cv::morphologyEx()
适用于图像预处理,比如去除噪声、增强边缘、分割物体等。形态学运算在模式识别、计算机视觉、医学图像分析等领域有广泛应用。