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()  // 边界值
);

参数:

  1. src:

    • 输入图像,可以是灰度图像或二值图像。它的类型通常是 CV_8UC1(单通道 8 位)或者 CV_8UC3(多通道彩色图像)。
  2. dst:

    • 输出图像,尺寸和类型与输入图像相同。形态学运算结果会存储在这里。
  3. op:

    • 形态学运算类型,可以是以下几种:
      • MORPH_ERODE: 腐蚀运算,最小化局部像素值。
      • MORPH_DILATE: 膨胀运算,最大化局部像素值。
      • MORPH_OPEN: 开运算(先腐蚀后膨胀),用于去除小噪声点。
      • MORPH_CLOSE: 闭运算(先膨胀后腐蚀),用于填补小孔。
      • MORPH_GRADIENT: 形态学梯度,膨胀和腐蚀之差,突出物体边界。
      • MORPH_TOPHAT: 顶帽运算,输入图像与其开运算结果之差,提取比周围亮的区域。
      • MORPH_BLACKHAT: 黑帽运算,闭运算结果与输入图像之差,提取比周围暗的区域。
      • MORPH_HITMISS: 击中击不中运算,主要用于形态学模式匹配。
  4. kernel:

    • 结构元素(核),形态学运算的关键因素。核可以是矩形、椭圆或十字形,指定了像素邻域的形状。常见的核使用函数 cv::getStructuringElement() 生成。核的尺寸和形状直接影响形态学运算的效果。
  5. anchor:

    • 核的锚点,决定形态学运算时哪个点与源图像进行对齐。默认值为 (-1, -1),表示锚点在核的中心。
  6. iterations:

    • 运算重复的次数,默认值为 1。如果设置为更大的数值,则形态学运算将重复执行多次,这有助于增强效果。
  7. borderType:

    • 图像边界的处理方式,决定当核处理图像边界时如何扩展边界。常见值包括:
      • BORDER_CONSTANT: 边界填充为常数值。
      • BORDER_REPLICATE: 复制边界像素。
  8. borderValue:

    • borderTypeBORDER_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. 常见的形态学运算

  1. 腐蚀 (MORPH_ERODE):

    • 腐蚀运算使得图像中的高亮区域变小,黑色区域变大,通常用于去除噪点。
  2. 膨胀 (MORPH_DILATE):

    • 膨胀运算使得图像中的高亮区域变大,黑色区域变小,通常用于填补物体中的小孔。
  3. 开运算 (MORPH_OPEN):

    • 先腐蚀再膨胀,通常用于去除小噪声。
  4. 闭运算 (MORPH_CLOSE):

    • 先膨胀再腐蚀,通常用于填充小孔和连接物体。
  5. 形态学梯度 (MORPH_GRADIENT):

    • 膨胀减腐蚀。通常用于提取物体的边缘。
  6. 顶帽运算 (MORPH_TOPHAT):

    • 原图减开运算图。提取比其邻域亮的部分,通常用于光照不均匀的图像。
  7. 黑帽运算 (MORPH_BLACKHAT):

    • 闭运算图减原图。提取比其邻域暗的部分,通常用于背景光亮、物体较暗的场景。


4. 应用场景

cv::morphologyEx() 适用于图像预处理,比如去除噪声、增强边缘、分割物体等。形态学运算在模式识别、计算机视觉、医学图像分析等领域有广泛应用。



来自:https://zhaitianbao.blog.csdn.net/?type=blog

posted @ 2024-09-12 15:23  做梦当财神  阅读(295)  评论(0编辑  收藏  举报