目录

引言

形态学基础

结构元素(Structuring Element)

基本形态学操作

腐蚀(Erosion)

膨胀(Dilation)

开运算(Opening)

闭运算(Closing)

高级形态学操作

形态学梯度(Morphological Gradient)

顶帽(Top Hat)

黑帽(Black Hat)

​编辑

结论


引言

图像形态学是一种基于数学形态学的理论和技术,广泛应用于数字图像处理、计算机视觉和模式识别等领域。它主要通过对图像中的形状和结构元素(也称为内核或模板)进行操作,来实现图像的增强、去噪、特征提取等目的。本文将详细介绍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:当borderTypeBORDER_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:当borderTypeBORDER_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提供的形态学操作功能强大且灵活,能够处理各种复杂的图像处理任务。通过合理使用腐蚀、膨胀、开运算、闭运算、形态学梯度、顶帽和黑帽等操作,我们可以有效地对图像进行去噪、增强、特征提取等处理。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐