c/c++的opencv开闭操作
OpenCV 中的形态学开运算与闭运算 (C++)
在计算机视觉和图像处理领域,形态学操作是用于分析和处理图像形状的一系列非线性操作。OpenCV 作为一个强大的开源计算机视觉库,提供了丰富的形态学转换函数。其中,“开运算”(Opening)和“闭运算”(Closing)是最基础且应用广泛的两种形态学操作,它们能够有效地去除噪声、分离/连接图像中的元素。
本文将详细介绍 OpenCV 中开运算和闭运算的原理、使用 cv::morphologyEx
函数的方式、关键参数、注意事项、典型应用场景以及它们在实际项目中的应用。
什么是形态学变换?
形态学变换主要应用于二值图像,但也可以扩展到灰度图像。它们通过一个称为结构元素 (Structuring Element) 或核 (Kernel) 的小型预定义形状来探测输入图像,并根据结构元素与图像相应区域的匹配情况来修改像素值。
开运算 (Morphological Opening)
定义:开运算是先对图像进行腐蚀 (Erosion) 操作,然后对结果进行膨胀 (Dilation) 操作。
Opening ( A , B ) = ( A ⊖ B ) ⊕ B \text{Opening}(A, B) = (A \ominus B) \oplus B Opening(A,B)=(A⊖B)⊕B
其中, A A A 是输入图像, B B B 是结构元素, o m i n u s \\ominus ominus 代表腐蚀, o p l u s \\oplus oplus 代表膨胀。
视觉效果与作用:
- 去除小的明亮物体/噪声:能够消除图像中尺寸小于结构元素的孤立亮点或细小连接(“盐”噪声)。
- 平滑物体轮廓:可以使物体的轮廓变得更加平滑。
- 断开细窄的连接:如果物体之间有非常细微的连接,开运算可以将其断开,从而分离物体。
- 打开裂缝或间隙:可以使物体内部的小裂缝变大。
- 开运算通常不会显著改变较大物体的整体尺寸。
闭运算 (Morphological Closing)
定义:闭运算是先对图像进行膨胀 (Dilation) 操作,然后对结果进行腐蚀 (Erosion) 操作。
Closing ( A , B ) = ( A ⊕ B ) ⊖ B \text{Closing}(A, B) = (A \oplus B) \ominus B Closing(A,B)=(A⊕B)⊖B
其中, A A A 是输入图像, B B B 是结构元素。
视觉效果与作用:
- 填充物体内的小孔洞/间隙:能够填充物体内部尺寸小于结构元素的暗区或小孔(“胡椒”噪声)。
- 连接邻近的物体:可以将空间上非常接近但有细小断裂的物体连接起来。
- 平滑物体轮廓:同样可以平滑轮廓,但与开运算侧重点不同,它倾向于填充轮廓的凹陷部分。
- 闭运算通常不会显著改变较大物体的整体尺寸。
OpenCV核心函数:cv::morphologyEx()
OpenCV 中执行开运算和闭运算的主要函数是 cv::morphologyEx()
。
void cv::morphologyEx(cv::InputArray src, // 输入图像cv::OutputArray dst, // 输出图像,可以与 src 相同 (in-place)int op, // 形态学操作的类型cv::InputArray kernel, // 结构元素 (核)cv::Point anchor = cv::Point(-1,-1), // 核的锚点位置,默认是核中心int iterations = 1, // 操作迭代次数int borderType = cv::BORDER_CONSTANT, // 边界填充模式const cv::Scalar& borderValue = cv::morphologyDefaultBorderValue() // 边界填充值
);
关键参数解释:
src
: 输入图像,可以是单通道或多通道。如果为多通道,则对每个通道独立处理。通常在二值图或灰度图上效果最直观。dst
: 输出图像,与src
具有相同的大小和类型。op
: 指定要执行的形态学操作:cv::MORPH_OPEN
: 执行开运算。cv::MORPH_CLOSE
: 执行闭运算。- (还有
cv::MORPH_ERODE
,cv::MORPH_DILATE
,cv::MORPH_GRADIENT
,cv::MORPH_TOPHAT
,cv::MORPH_BLACKHAT
等其他操作类型。)
kernel
: 结构元素。这是一个小的二值(或灰度)矩阵,定义了操作的邻域形状。可以使用cv::getStructuringElement()
函数来创建。anchor
: 结构元素内锚点的位置。默认值cv::Point(-1, -1)
表示锚点位于核的中心。iterations
: 操作执行的次数。增加迭代次数会增强效果。例如,迭代两次开运算相当于Open(Open(src, kernel), kernel)
。borderType
: 用于推断图像外部像素的边界模式。默认cv::BORDER_CONSTANT
。borderValue
: 当borderType
为cv::BORDER_CONSTANT
时使用的边界值。
创建结构元素 (Kernel)
使用 cv::getStructuringElement()
函数可以方便地创建常见的结构元素形状:
cv::Mat cv::getStructuringElement(int shape, // 结构元素的形状cv::Size ksize, // 结构元素的大小cv::Point anchor = cv::Point(-1,-1) // 锚点位置,默认中心
);
shape
:cv::MORPH_RECT
: 矩形结构元素。cv::MORPH_ELLIPSE
: 椭圆形结构元素。cv::MORPH_CROSS
: 十字形结构元素。
ksize
: 结构元素的尺寸,例如cv::Size(5, 5)
表示一个 5 t i m e s 5 5 \\times 5 5times5 的核。
C++ 代码示例
以下示例展示了如何使用 OpenCV 在 C++ 中执行开运算和闭运算。
#include <opencv2/opencv.hpp> // 包含OpenCV主头文件
#include <opencv2/imgproc.hpp> // 图像处理模块int main() {// 1. 加载图像// 请将 "input.png" 替换为你的图像路径// 为演示形态学效果,通常使用二值图或灰度图,这里我们加载后转为灰度图cv::Mat srcImage = cv::imread("input.png", cv::IMREAD_GRAYSCALE);if (srcImage.empty()) {std::cerr << "Error: Could not load image!" << std::endl;return -1;}// (可选) 如果图像不是二值的,可以先进行二值化处理// cv::Mat binaryImage;// cv::threshold(srcImage, binaryImage, 127, 255, cv::THRESH_BINARY);// cv::Mat targetImage = binaryImage; // 处理二值图cv::Mat targetImage = srcImage; // 或者直接处理灰度图// 2. 定义结构元素 (Kernel)int kernelSize = 5; // 核大小,可以调整cv::Mat kernel = cv::getStructuringElement(cv::MORPH_RECT, // 或者 cv::MORPH_ELLIPSE, cv::MORPH_CROSScv::Size(kernelSize, kernelSize));// 对于椭圆或十字形,(2*n+1, 2*n+1) 确保对称性,如 cv::Size(2*2+1, 2*2+1) 即 5x5// 3. 执行开运算cv::Mat openedImage;cv::morphologyEx(targetImage, openedImage, cv::MORPH_OPEN, kernel);// 4. 执行闭运算cv::Mat closedImage;cv::morphologyEx(targetImage, closedImage, cv::MORPH_CLOSE, kernel);// 5. (可选) 增加迭代次数以增强效果cv::Mat openedImage_iter2;cv::morphologyEx(targetImage, openedImage_iter2, cv::MORPH_OPEN, kernel, cv::Point(-1,-1), 2); // 迭代2次cv::Mat closedImage_iter2;cv::morphologyEx(targetImage, closedImage_iter2, cv::MORPH_CLOSE, kernel, cv::Point(-1,-1), 2); // 迭代2次// 6. 显示结果cv::imshow("Original Image", targetImage);cv::imshow("Opened Image (1 iter)", openedImage);cv::imshow("Closed Image (1 iter)", closedImage);cv::imshow("Opened Image (2 iter)", openedImage_iter2);cv::imshow("Closed Image (2 iter)", closedImage_iter2);// (可选) 保存结果// cv::imwrite("opened_image.png", openedImage);// cv::imwrite("closed_image.png", closedImage);cv::waitKey(0); // 等待按键cv::destroyAllWindows(); // 关闭所有窗口return 0;
}
编译命令示例 (g++):
g++ your_code_file.cpp -o morphological_ops `pkg-config --cflags --libs opencv4`
(如果你的 pkg-config
配置的是 opencv
而不是 opencv4
,请相应修改。)
关键参数及其影响
-
结构元素 (Kernel) 的大小和形状:
- 大小:核越大,影响范围越大。开运算会移除更大的物体,闭运算会填充更大的孔洞或连接更远的物体。过大的核可能会过度平滑或扭曲重要特征。
- 形状:核的形状决定了操作的“方向性”和效果。例如,水平线状的核在去除垂直噪声时比方形核更有效。选择与待处理特征形状相似的核通常效果更好。
-
迭代次数 (Iterations):
- 多次迭代会增强操作的效果。例如,迭代两次的开运算比迭代一次的开运算去除噪声的能力更强,平滑效果也更明显。但同样,过多迭代可能导致细节丢失。
重要注意事项
-
输入图像类型:
- 形态学操作在二值图像上定义最清晰,效果也最直观。
- 对于灰度图像,腐蚀操作会将像素值替换为其邻域内的最小值,膨胀则替换为最大值。开闭运算也相应基于此。
- 对于彩色图像,
cv::morphologyEx
会独立应用于每个颜色通道。这有时可能不是期望的效果。通常,处理彩色图像的形态学问题时,会先将其转换为灰度图或提取特定通道进行处理。
-
核的选择:选择合适的核大小和形状对结果至关重要,需要根据具体问题和图像特征进行实验和调整。
-
边界处理 (
borderType
):默认的cv::BORDER_CONSTANT
(用0填充)在大多数情况下是合适的。但在某些特殊应用中,可能需要考虑其他边界处理方式。 -
性能:对于大图像或大核以及多次迭代,形态学操作可能会比较耗时。
典型应用场景
开运算 (MORPH_OPEN)
- 去除椒盐噪声中的“盐”部分(小的亮斑):尤其当噪声点小于结构元素时。
- 分离物体:断开两个物体之间细微的连接处,使得它们在后续处理中被识别为独立个体。
- 平滑轮廓:去除物体轮廓上的小的突出部分。
- 获取背景:在某些情况下,用一个非常大的结构元素进行开运算可以估计图像的背景(如文本去除)。
闭运算 (MORPH_CLOSE)
- 去除椒盐噪声中的“胡椒”部分(小的暗斑或孔洞)。
- 连接断裂的轮廓:弥合物体轮廓上的小缺口。
- 填充物体内部的小孔。
- 合并邻近的区域:将一些小的、分离的区域连接成一个更大的区域。
开源项目中的应用
OpenCV 的形态学开闭运算作为基础的图像预处理和后处理步骤,广泛应用于各种计算机视觉相关的开源项目中:
-
物体检测与分割:
- 在得到初步的物体掩码 (mask) 后,使用闭运算填充掩码内部的小孔,使用开运算去除掩码外的孤立小噪点,使掩码更完整平滑。
- 例如,在行人检测或车辆检测后,对检测框内的像素区域进行形态学处理以优化形状。
-
光学字符识别 (OCR):
- 对扫描的文档图像进行预处理,使用闭运算连接字符中断裂的部分,使用开运算去除墨迹污点或背景噪声,从而提高字符识别的准确率。
-
医学图像分析:
- 在细胞计数或组织分析中,使用开运算分离粘连的细胞,使用闭运算填充细胞内部的空隙或修复细胞膜的断裂。
- 去除X光片、MRI图像中的噪声或伪影。
-
工业自动化与缺陷检测:
- 在产品表面缺陷检测中,使用形态学操作增强缺陷区域(如划痕、孔洞),或去除背景纹理的干扰。
- 对传送带上的物体进行分割和计数,形态学操作可用于改善分割效果。
-
文档扫描与增强:
- 类似OCR场景,用于清理扫描文档,去除背景斑点,增强文字对比度等。
-
机器人视觉与导航:
- 在基于视觉的路径规划中,对环境感知得到的地图或障碍物信息进行形态学处理,如闭运算填充感知盲区,开运算去除传感器噪声。
这些项目中,开闭运算往往不是单独使用,而是作为更复杂算法流程中的一个或多个步骤,与其他图像处理技术(如滤波、边缘检测、阈值化)结合,以达到最终的目标。
结论
OpenCV 中的形态学开运算和闭运算是强大且灵活的图像处理工具。通过精心选择结构元素和操作参数,它们能够有效地改善图像质量、提取有用特征、简化后续分析任务。理解其原理并熟练运用 cv::morphologyEx
函数,对于任何使用 C++ 和 OpenCV 进行图像处理的开发者来说都至关重要。
相关文章:
c/c++的opencv开闭操作
OpenCV 中的形态学开运算与闭运算 (C) 在计算机视觉和图像处理领域,形态学操作是用于分析和处理图像形状的一系列非线性操作。OpenCV 作为一个强大的开源计算机视觉库,提供了丰富的形态学转换函数。其中,“开运算”(Opening&…...

【物联网】 ubantu20.04 搭建L2TP服务器
部署篇 序言 为了是两个客户端在同一个网络内,需要找一台服务器,搭建一个L2TP服务器,通过L2TP使两个客户端在同一个网络内,为什么要搭建,主要是解决例如员工出差后,还需要连接公司内网资源的问题,本文主要…...
winrar 工具测试 下载 与安装
https://zhuanlan.zhihu.com/p/680852417 https://www.angusj.com/resourcehacker/#download 点击String Table,在展开列表中找到80:2052展开,删除1277行。点击右上方编译按钮,并保存。...
PLC组网的方法、要点及实施全解析
一、PLC组网方法 1.1 基于以太网的组网 - 适用场景:适用于数据传输量大、通信距离长、对实时性要求相对不苛刻的场景,如大型工厂的车间级数据交互、跨区域设备协同控制 。 - 实现方式:利用工业以太网交换机,将支持以太网接口的…...
网络安全深度解析:21种常见网站漏洞及防御指南
一、高危漏洞TOP 10 1. SQL注入(SQLi) 原理:通过构造恶意SQL语句突破系统过滤机制 典型场景: - 联合查询注入: union select 1,version(),3--+ - 布尔盲注:and (select substr(user(),1,1)=r) - 时间盲注:;if(now()=sysdate(),sleep(5),0)/ 防御方案: - 严格参数化查…...
【FAQ】HarmonyOS SDK 闭源开放能力 —Vision Kit (3)
1.问题描述: 通过CardRecognition识别身份证拍照拿到的照片地址,使用该方法获取不到图片文件,请问如何解决? 解决方案: //卡证识别实现页,文件名为CardDemoPage,需被引入至入口页 import { …...
Java大厂面试实战:Spring Boot与微服务场景中的技术点解析
Java大厂面试实战:Spring Boot与微服务场景中的技术点解析 第一轮:基础技术了解 面试官:谢飞机,你好。从简历上看,你熟悉Spring Boot,那我们来聊聊它的核心功能吧。Spring Boot有哪些主要的特性ÿ…...

从零启动 Elasticsearch
elastic 有弹力的 ElaticSearch (ES)是一个基于 Lucene 的分布式全文检索引擎。可以做到近乎实时地存储、检索数据,并且本身具有良好的扩展性,可以扩展到上百台服务器,处理PB级别(1 Petabyte 1024TB&…...
比较两个用于手写体识别的卷积神经网络(CNN)模型
要比较两个用于手写体识别的卷积神经网络(CNN)模型,可以从以下 6个核心维度 进行系统性评估,并直接给出对比结论: 一、基础性能对比(核心指标) 准确率 直接比较两个模型在 相同测试集 上的分类准确率(如MNIST测试集的错误率是否低于0.5%)若准确率接近…...
Linux利用多线程和线程同步实现一个简单的聊天服务器
1. 概述 本文实现一个基于TCP/IP的简单多人聊天室程序。它包含一个服务器端和一个客户端:服务器能够接收多个客户端的连接,并将任何一个客户端发来的消息广播给所有其他连接的客户端;客户端则可以连接到服务器,发送消息并接收来自…...
【计网】作业5
待补充 212.56.132.0/24 212.56.1000 0100.0 212.56.133.0/24 212.56.1000 0101.0 212.56.134.0/24 212.56.1000 0110.0 212.56.135.0/24 212.56.1000 0111.0 最小的212.56.1000 0100.0 四个,2^2 212.56.132.0/22 1111 1111.1111 1111.1111 1100.0000 0000 255.255.…...
15、Python布尔逻辑全解析:运算符优先级、短路特性与实战避坑指南
适合人群:零基础自学者 | 编程小白快速入门 阅读时长:约6分钟 文章目录 一、问题:Python布尔值的底层原理?1、例子1:电路开关模型解析布尔本质2、例子2:特殊的布尔类型值为False3、答案:(1&…...

Nginx基础知识
Nginx是什么? Nginx 是一款高性能的 Web 服务器、反向代理服务器和负载均衡器,以其高并发处理能力和低内存消耗著称。以下是 Nginx 的基础知识和常见配置示例: 1. 核心概念 • 配置文件位置:通常为 /etc/nginx/nginx.conf 或 /us…...

Vue-监听属性
监听属性 简单监听 点击切换名字,来回变更Tom/Jerry,输出 你好,Tom/Jerry 代码 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /><title>监听属性</title><!-- …...

python fastapi + react, 写一个图片 app
1. 起因, 目的: 上厕所的时候,想用手机查看电脑上的图片,但是又不想点击下载。此app 应运而生。 2. 先看效果 单击图片,能放大图片 3. 过程: 过程很枯燥。有时候, 有一堆新的想法。 但是做起来太麻烦,…...
nginx集成防火墙ngx_waf的docker版
由于公网的环境越来与严峻,所以想找一个nginx带防火墙的版本 调研过openresty,大部分集成redis了,感觉还是太重了,有一个不那么重的https://github.com/unixhot/waf 但是维护没有那么勤,最后维护是5年前,倒…...

vscode c++编译onnxruntime cuda 出现的问题
问题描述 将onnx的dll文件和lib文件copy到可执行文件所在文件夹下后,现象: 双击可执行文件能正常运行 在vscode中点击cmake插件的运行按钮出现报错为 c [ONNXRuntimeError] : 1 : FAIL : LoadLibrary failed with error 126 “” when trying to load尝试…...
sts下载安装
windows下STS(Spring Tools Suite,自带spring插件的eclipse)的下载与安装_sts下载-CSDN博客Spring Boot安装与配置教程_spring boot安装配置-CSDN博客...

中服云生产线自动化智能化调度生产系统:打造智能制造新标杆
前言 在当今制造业竞争日益激烈的背景下,实现生产线的自动化与智能化已成为企业提升竞争力的关键。作为国内技术领先的工业物联网平台、数字孪生、自动控制技术厂商,中服云凭借其深厚的技术积累和创新能力,打造了一套完整的生产线自动化智能…...
next.js实现项目搭建
一、创建 Next.js 项目的步骤 1、安装 npx create-next-applatest # 或 yarn create next-app # 或 pnpm create next-app 按照交互式提示配置你的项目: 输入项目名称 选择是否使用 TypeScript 选择是否启用 ESLint 选择是否启用 Tailwind CSS 选择是否使用 s…...
Redisson 四大核心机制实现原理详解
一、可重入锁(Reentrant Lock) 可重入锁是什么? 通俗定义 可重入锁类似于一把“智能锁”,它能识别当前的锁持有者是否是当前线程: 如果是,则允许线程重复获取锁(重入),并…...

云鼎入鼎系统:一站式电商管理解决方案
个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119qq.com] 📱个人微信&a…...

Leetcode134加油站
题目链接 134 题意图解: 题目给了n个节点,这些节点呈现环状,每次到一个低点要消耗cost[i]的油量。 从中我们可以得出一个结论:看一个点能不能到下一个点,就要用当前的油量减去消耗的量,那么gas[i] - cost…...

关于Android Studio for Platform的使用记录
文章目录 简单介绍如何使用配置导入aosp工程配置文件asfp-config.json 简单介绍 Android Studio for Platform是google最新开发,用来阅读aosp源码的工具 详细的资料介绍: https://developer.android.google.cn/studio/platform 将工具下载下来直接点击…...
Linux的内存泄漏问题及排查方法
内存泄漏是指在计算机程序中,已不再被使用的内存未被正确释放,导致内存占用随时间累积,进而引发系统内存不足、性能下降甚至崩溃的问题。在Linux系统中,开发者和运维人员可通过以下方法排查和解决内存泄漏问题: 1. 使…...

uniapp 微信小程序 获取openId
嗨,我是小路。今天主要和大家分享的主题是“uniapp 微信小程序 获取openId”。 一、主要属性 1.uni.login 二、实例代码 1、前端代码 uni.login({provider: weixin,success: (res) > {uni.showLoading({title: 登录中...,mask: true})let code res.…...

隧道结构安全在线监测系统解决方案
一、方案背景 隧道是地下隐蔽工程,会受到潜在、无法预知的地质因素影响。随着我国公路交通建设的发展,隧道占新建公路里程的比例越来越大。隧道属于线状工程,有的规模较大,可长达几公里或数十公里,往往穿越许多不同环境…...

Docker 运维管理
Docker 运维管理 一、Swarm集群管理1.1 Swarm的核心概念1.1.1 集群1.1.2 节点1.1.3 服务和任务1.1.4 负载均衡 1.2 Swarm安装准备工作创建集群添加工作节点到集群发布服务到集群扩展一个或多个服务从集群中删除服务ssh免密登录 二、Docker Compose与 Swarm 一起使用 Compose 三…...
【Redis】快速列表结构
目录 1、背景2、压缩列表【1】底层结构【2】特性【3】优缺点 1、背景 redis的quicklist(快速列表)是一个双向链表,其中每个节点都是一个ziplist(压缩列表)。这中结构结合了双向链表和压缩列表的优点,在内存…...
阿里巴巴 1688 数据接口开发指南:构建自动化商品详情采集系统
在电商行业数据驱动决策的趋势下,高效获取商品详情数据成为企业洞察市场、优化运营的关键。通过阿里巴巴 1688 数据接口构建自动化商品详情采集系统,能够快速、精准地采集海量商品信息。本文将从开发准备、接口分析、代码实现等方面,详细介绍…...