OpenCV C++ 形态学分析:从基础操作到高级应用

发布于:2025-09-09 ⋅ 阅读:(21) ⋅ 点赞:(0)

形态学分析是基于形状的图像处理方法,通过预设的结构元素对图像进行操作,实现对目标形态的调整与特征提取。本章将系统讲解形态学的核心操作 —— 腐蚀与膨胀,以及由它们组合而成的开操作、闭操作、形态学梯度、顶帽与黑帽等高级应用,结合实例展示这些技术在噪声去除、边缘提取、形状分析等场景的实用价值。

一、腐蚀与膨胀

腐蚀与膨胀是形态学分析的基础操作,二者互为对偶,通过与结构元素的相互作用改变图像中前景物体的形态。

1.1 腐蚀操作 (Erosion)

腐蚀操作的核心是缩小前景物体,它会消除物体边缘的像素,使物体边界向内收缩,常用于去除小噪声、分离粘连物体。

原理:对于图像中的每个像素,当结构元素完全包含于前景区域时,该像素保留为前景,否则变为背景。

#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;

// 自定义腐蚀操作(4连通)
Mat erodeCustom(const Mat& binary, int ksize = 3) {
    CV_Assert(binary.type() == CV_8UC1);
    
    int rows = binary.rows;
    int cols = binary.cols;
    Mat result = Mat::zeros(rows, cols, CV_8UC1);
    int center = ksize / 2;
    
    // 创建矩形结构元素
    Mat kernel = Mat::ones(ksize, ksize, CV_8UC1);
    
    // 遍历图像(边界不处理)
    for (int i = center; i < rows - center; ++i) {
        for (int j = center; j < cols - center; ++j) {
            if (binary.at<uchar>(i, j) == 255) {
                bool allForeground = true;
                
                // 检查结构元素覆盖的所有像素
                for (int m = 0; m < ksize; ++m) {
                    for (int n = 0; n < ksize; ++n) {
                        if (kernel.at<uchar>(m, n) == 1) {
                            int x = i + m - center;
                            int y = j + n - center;
                            if (binary.at<uchar>(x, y) == 0) {
                                allForeground = false;
                                break;
                            }
                        }
                    }
                    if (!allForeground) break;
                }
                
                if (allForeground) {
                    result.at<uchar>(i, j) = 255;
                }
            }
        }
    }
    
    return result;
}

// 使用OpenCV内置腐蚀函数
Mat erodeOpenCV(const Mat& binary, int ksize = 3, int iterations = 1) {
    Mat result;
    // 创建结构元素(矩形、椭圆或十字形)
    Mat kernel = getStructuringElement(MORPH_RECT, Size(ksize, ksize));
    // 应用腐蚀操作
    erode(binary, result, kernel, Point(-1, -1), iterations);
    return result;
}

1.2 膨胀操作 (Dilation)

膨胀操作与腐蚀相反,它会扩大前景物体,使物体边界向外扩张,常用于填补物体内部的小空洞、连接断裂的物体。

原理:对于图像中的每个像素,当结构元素与前景区域有交集时,该像素变为前景,否则保持背景。

// 自定义膨胀操作(4连通)
Mat dilateCustom(const Mat& binary, int ksize = 3) {
    CV_Assert(binary.type() == CV_8UC1);
    
    int rows = binary.rows;
    int cols = binary.cols;
    Mat result = Mat::zeros(rows, cols, CV_8UC1);
    int center = ksize / 2;
    
    Mat kernel = Mat::ones(ksize, ksize, CV_8UC1);
    
    for (int i = center; i < rows - center; ++i) {
        for (int j = center; j < cols - center; ++j) {
            if (binary.at<uchar>(i, j) == 0) {
                bool hasForeground = false;
                
                // 检查结构元素覆盖的区域是否有前景像素
                for (int m = 0; m < ksize; ++m) {
                    for (int n = 0; n < ksize; ++n) {
                        if (kernel.at<uchar>(m, n) == 1) {
                            int x = i + m - center;
                            int y = j + n - center;
                            if (binary.at<uchar>(x, y) == 255) {
                                hasForeground = true;
                                break;
                            }
                        }
                    }
                    if (hasFo

网站公告

今日签到

点亮在社区的每一天
去签到