ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

OpenCV 形态学变换进阶教程:Opening、Closing、Morphological Gradient、Top Hat 与 Black Hat 的 morphologyEx 实战解析

OpenCV 形态学变换进阶教程:Opening、Closing、Morphological Gradient、Top Hat 与 Black Hat 的 morphologyEx 实战解析 OpenCV 形态学变换进阶教程Opening、Closing、Morphological Gradient、Top Hat 与 Black Hat 的 morphologyEx 实战解析【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv本教程面向已掌握腐蚀erosion与膨胀dilation基础的开发者系统讲解 OpenCV 中基于cv::morphologyEx实现的五种高级形态学变换——开运算Opening、闭运算Closing、形态学梯度Morphological Gradient、顶帽Top Hat与黑帽Black Hat。结合当前仓库中 Morphology_2.cpp 交互式演示程序的完整源码与modules/imgproc/src/morph.dispatch.cpp底层实现你将掌握五种算子的数学定义、适用场景、核结构化元素选取技巧并能写出属于自己的可交互调试工具。本教程依据 OpenCV 官方文档 opening_closing_hats.markdown原作者 Ana Huamán适用于 OpenCV ≥ 3.0当前仓库以 5.x 代码为准整理并扩展。学习目标学完本教程你将能够使用 OpenCV 函数cv::morphologyEx完成以下五种形态学变换开运算 Opening闭运算 Closing形态学梯度 Morphological Gradient顶帽 Top Hat黑帽 Black Hat理解这五种变换与基础腐蚀/膨胀操作之间的推导关系明白各自的数学本质使用cv::getStructuringElement构造矩形、十字、椭圆等不同形状的结构化元素理解morph_operator、morph_elem、morph_size三类核心参数对结果的影响参考仓库中的 C / Python 交互式示例搭建带轨迹条Trackbar的实时预览程序。理论从腐蚀与膨胀出发的五种高级形态学算子上一教程Erosion 与 Dilation中我们已掌握两种最基本的形态学操作。在此基础上通过把腐蚀与膨胀进行组合或求差就能派生出功能更丰富的五种变换。下面逐一介绍理论表述源自 Bradski 与 Kaehler 所著《Learning OpenCV》。1. 开运算 Opening开运算由先腐蚀后膨胀得到dst open(src, element) dilate(erode(src, element))适用场景移除图像中的细小物体假设目标是亮背景上的亮色小目标。上图中左侧原图经开运算后右侧结果里的小点已经消失而主体较大目标的形状基本保持。2. 闭运算 Closing闭运算由先膨胀后腐蚀得到dst close(src, element) erode(dilate(src, element))适用场景移除目标内部细小的孔洞暗色区域。例如对二值分割结果中目标内部的空洞或字符笔画中的断点闭运算都有很好的连接与填补效果。3. 形态学梯度 Morphological Gradient形态学梯度定义为图像膨胀与腐蚀之差dst morph_grad(src, element) dilate(src, element) - erode(src, element)适用场景提取目标的轮廓outline。膨胀会把边界向外扩张腐蚀会把边界向内收缩两者之差恰好勾勒出目标边界带的宽度等价于一种与核形状相关的边缘检测手段。4. 顶帽 Top Hat顶帽变换定义为输入图像与其开运算之差dst tophat(src, element) src - open(src, element)适用场景由于开运算会移除比核小的亮目标原图减去开运算结果后剩下的恰好是这些被过滤掉的小而亮的结构。顶帽常用于不均匀光照背景下的亮细节提取。5. 黑帽 Black Hat黑帽变换定义为闭运算与输入图像之差dst blackhat(src, element) close(src, element) - src适用场景闭运算会填补暗色孔洞用闭运算结果减去原图即得到被填补的那些暗色细节。黑帽与顶帽互为补关系——前者突出暗特征后者突出亮特征。深入底层morphologyEx 如何组合这些算子cv::morphologyEx是执行上述全部五种变换的统一入口在头文件 imgproc.hpp 中定义了枚举类型MorphTypes枚举值数值含义MORPH_OPEN2开运算MORPH_CLOSE3闭运算MORPH_GRADIENT4形态学梯度MORPH_TOPHAT5顶帽MORPH_BLACKHAT6黑帽注意数值范围是 2–6这正是示例代码中要把轨迹条取值2的原因详见下文。而ElementShape枚举则定义了结构化元素的形状MORPH_RECT 0、MORPH_CROSS 1、MORPH_ELLIPSE 2、MORPH_DIAMOND 3钻石形按曼哈顿距离定义。从 morph.dispatch.cpp 的源码可以看出高级算子本质上都是基础腐蚀/膨胀的组合而非全新的算法内核MORPH_OPEN先用当前核完成一次MORPH_ERODE结果写入临时缓冲_temp再对_temp执行MORPH_DILATE得到输出MORPH_CLOSE顺序与开运算相反先MORPH_DILATE到临时缓冲再MORPH_ERODE得最终结果MORPH_GRADIENT先腐蚀得到临时结果temp再膨胀并在膨胀阶段利用MORPH_GRADIENT模式与临时结果做差MORPH_TOPHAT先完成一次开运算腐蚀 膨胀到_temp随后用MORPH_TOPHAT模式以原图_src减去该开运算结果MORPH_BLACKHAT先完成一次闭运算膨胀 腐蚀到_temp随后用MORPH_BLACKHAT模式让闭运算结果减去原图_src。可以看到OpenCV 在实现层面把 先 erode 再 dilate、两图求差 等公共步骤下沉到同一条 OpenCLocl_morphOp与 CPU 通用路径中不同的MorphTypes只决定了中间缓冲的编排次序和最终的加减方向。因此腐蚀/膨胀越熟练对这五种算子的掌控就越直接。示例程序逐段剖析官方文档在 C、Java、Python 三个语言分支下各提供了一份演示程序。本仓库中可确认的有 C 版 Morphology_2.cpp 与 Python 版 morphology_2.py。程序的整体结构是加载一张输入图像创建显示窗口创建三条轨迹条Trackbar分别控制算子类型 Operator、元素/核形状 Element、核尺寸 Kernel Size拖动任意滑块都会触发回调函数Morphology_Operations按当前参数重算形态学结果并刷新显示。主函数与轨迹条创建C#include opencv2/imgproc.hpp #include opencv2/imgcodecs.hpp #include opencv2/highgui.hpp #include iostream using namespace cv; Mat src, dst; int morph_elem 0; int morph_size 0; int morph_operator 0; int const max_operator 4; int const max_elem 3; int const max_kernel_size 21; const char* window_name Morphology Transformations Demo; int main( int argc, char** argv ) { CommandLineParser parser( argc, argv, {input | baboon.jpg | input image} ); src imread( samples::findFile( parser.getString( input ) ), IMREAD_COLOR ); if (src.empty()) { std::cout Could not open or find the image!\n std::endl; std::cout Usage: argv[0] Input image std::endl; return EXIT_FAILURE; } namedWindow( window_name, WINDOW_AUTOSIZE ); // 轨迹条1选择形态学算子0-4映射到 MORPH_OPEN..MORPH_BLACKHAT createTrackbar(Operator:\n 0: Opening - 1: Closing \n 2: Gradient - 3: Top Hat \n 4: Black Hat, window_name, morph_operator, max_operator, Morphology_Operations ); // 轨迹条2选择结构化元素形状0: Rect - 1: Cross - 2: Ellipse - 3: Diamond createTrackbar( Element:\n 0: Rect - 1: Cross - 2: Ellipse - 3: Diamond, window_name, morph_elem, max_elem, Morphology_Operations ); // 轨迹条3选择核尺寸滑块值 n实际核尺寸为 2n1上限 21 createTrackbar( Kernel size:\n 2n 1, window_name, morph_size, max_kernel_size, Morphology_Operations ); Morphology_Operations( 0, 0 ); // 默认参数先执行一次 waitKey(0); return 0; }三个轨迹条的含义与取值范围如下表轨迹条控制变量取值范围说明Operatormorph_operator0–40Opening1Closing2Gradient3Top Hat4Black HatElementmorph_elem0–30Rect1Cross2Ellipse3DiamondKernel Sizemorph_size0–21滑块值n对应实际边长2n1其中 C 分支把morph_elem直接作为getStructuringElement的shape参数传入支持到 DiamondPython 分支则用 if/elif 把轨迹条取值显式映射为cv.MORPH_RECT / MORPH_CROSS / MORPH_ELLIPSE / MORPH_DIAMOND。两条轨迹条结构高度一致体现同一套 UI 交互逻辑的多语言复刻。核心回调 Morphology_Operationsvoid Morphology_Operations( int, void* ) { // 由于 MORPH_X 的枚举值从 2 开始2,3,4,5,6滑块值需 2 int operation morph_operator 2; // 依据当前形状与尺寸构造结构化元素锚点放在核中心 Mat element getStructuringElement( morph_elem, Size( 2*morph_size 1, 2*morph_size 1 ), Point( morph_size, morph_size ) ); // 应用指定形态学操作 morphologyEx( src, dst, operation, element ); imshow( window_name, dst ); }回调里只显式传了四个参数src输入图像dst输出图像operation形态学变换类型。注意由于MorphTypes中开/闭/梯度/顶帽/黑帽的取值是 2–6因此这里将轨迹条值morph_operator加上偏移 (2) 再传入而不是直接用原始滑块值element参与运算的结构化元素核由getStructuringElement生成其余参数迭代次数、边界模式等均保持默认值。Python 等价实现仓库同样提供了 Python 版本 morphology_2.py。它先建立算子字典morph_op_dic {0: cv.MORPH_OPEN, 1: cv.MORPH_CLOSE, 2: cv.MORPH_GRADIENT, 3: cv.MORPH_TOPHAT, 4: cv.MORPH_BLACKHAT}回调函数读取三条轨迹条并执行一次形态学运算def morphology_operations(val): morph_operator cv.getTrackbarPos(title_trackbar_operator_type, title_window) morph_size cv.getTrackbarPos(title_trackbar_kernel_size, title_window) morph_elem 0 val_type cv.getTrackbarPos(title_trackbar_element_type, title_window) if val_type 0: morph_elem cv.MORPH_RECT elif val_type 1: morph_elem cv.MORPH_CROSS elif val_type 2: morph_elem cv.MORPH_ELLIPSE elif val_type 3: morph_elem cv.MORPH_DIAMOND element cv.getStructuringElement(morph_elem, (2*morph_size 1, 2*morph_size 1), (morph_size, morph_size)) operation morph_op_dic[morph_operator] dst cv.morphologyEx(src, operation, element) cv.imshow(title_window, dst)程序通过argparse接收--input参数默认LinuxLogo.jpg随后依次创建三个轨迹条并立即触发一次默认运算cv.namedWindow(title_window) cv.createTrackbar(title_trackbar_operator_type, title_window, 0, max_operator, morphology_operations) cv.createTrackbar(title_trackbar_element_type, title_window, 0, max_elem, morphology_operations) cv.createTrackbar(title_trackbar_kernel_size, title_window, 0, max_kernel_size, morphology_operations) morphology_operations(0) cv.waitKey()对比可见C 用整型全局变量 取地址被轨迹条直接绑定Python 则通过cv.getTrackbarPos在回调内读取滑块位置核尺寸换算2n1与锚点(n, n)两边完全一致。结构化元素详解getStructuringElement五种算子都依赖核来定义邻域作用范围核由getStructuringElement(shape, ksize, anchor)生成shape元素形状。示例中可取MORPH_RECT矩形全部邻域参与、MORPH_CROSS十字形仅轴向邻域参与、MORPH_ELLIPSE椭圆/近似圆形、MORPH_DIAMOND按曼哈顿距离定义的菱形ksize核尺寸。示例中为(2*morph_size1, 2*morph_size1)保证核边长为奇数锚点能落在正中心anchor锚点位置。示例传入Point(morph_size, morph_size)即核中心。实际调参时可以记住核越大过滤或变形的尺度越大。矩形核作用最钝完全邻域取 min/max十字核只在水平/垂直方向作用椭圆核更接近各向同性的圆适合处理圆形目标不同形状会影响边界平滑程度与方向敏感性。运行与效果解读编译 C 示例后传入一张图像路径即可启动./Morphology_2 input imagePython 示例的启动方式为python morphology_2.py --input input image在出现的结果窗口中拖动三条轨迹条即可实时观察五种算子、四种核形状与 1×1 到 21×21 核尺寸的叠加效果。官方文档结果图即来自该交互式窗口的抓屏结合原图Morphology_2_Tutorial_Original_Image.jpg可以直观看到十字形核进行开运算时按轴向结构筛选目标椭圆核进行黑帽变换时提取的是闭运算补上的暗色小结构。建议在调试时固定一张图只改变一个滑块体会单一参数变化带来的差异。应用场景与调参小结把五种算子放入实际图像处理流程中它们的分工大致是算子典型用途Opening 开运算去噪点、分离细小粘连、去掉比核小的亮目标Closing 闭运算填补目标内部小洞、连接断裂笔画、平滑暗色凹陷Morphological Gradient提取目标轮廓/边界比单纯差分对噪声更稳健Top Hat不均匀光照下提取亮色细节如文字、细小亮斑Black Hat提取暗色细节常配合顶帽做形态学重建的前处理实践中注意三点先降噪再选算子形态学对椒盐类噪声敏感必要时先用高斯模糊或中值滤波预处理核尺寸需匹配目标尺度开/闭运算本质上是以核尺寸为标尺筛选结构核应略大于要剔除/填补的特征尺度顶帽/黑帽对光照补偿友好它们是减法型算子在分块处理前用于消除缓变背景很有价值可与阈值化cv::threshold配合完成不均匀光照下的二值化。小结本教程沿着腐蚀/膨胀 → 五种高级形态学算子 →morphologyEx底层组合逻辑 → 可交互示例程序 → 实际调参的脉络完整演示了MORPH_OPEN、MORPH_CLOSE、MORPH_GRADIENT、MORPH_TOPHAT、MORPH_BLACKHAT五种变换。核心要点是它们都是腐蚀与膨胀在时序与减法上的组合算子枚举值从 2 起跳核形状与核尺寸决定作用的尺度与方向。读者可直接运行 Morphology_2.cpp 或 morphology_2.py 亲手验证并结合 morph.dispatch.cpp 的源码理解其内部编排为后续学习击中/击不中变换Hit-or-Miss等进阶形态学内容打好基础。【免费下载链接】opencvOpen Source Computer Vision Library项目地址: https://gitcode.com/GitHub_Trending/opencv31/opencv创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表