千家信息网

C++中Opencv的imfill孔洞填充函数怎么用

发表于:2025-11-12 作者:千家信息网编辑
千家信息网最后更新 2025年11月12日,这篇文章主要为大家展示了"C++中Opencv的imfill孔洞填充函数怎么用",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"C++中Opencv的imfi
千家信息网最后更新 2025年11月12日C++中Opencv的imfill孔洞填充函数怎么用

这篇文章主要为大家展示了"C++中Opencv的imfill孔洞填充函数怎么用",内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下"C++中Opencv的imfill孔洞填充函数怎么用"这篇文章吧。

函数实现的中心思想

二值图

此程序针对于二值图,寻找二值图中 像素值为0的连通域,将所有连通域的像素点分别保存下来,将符合条件的连通域的像素值 置为255;

寻找连通域的关键

针对填洞功能的实现,也就是0置为255过程,我们需要以四连通为基本点进行寻找。

种子点的确定

寻找种子点,其实就是寻找二值图中像素值为0的点,我们可以直接采取 遍历 二值图 中的像素,将第一个遇见的像素值为0的点确定为 第一个连通域的种子点。这时候,有一些朋友可能会疑惑,因为按照我的说法,在遍历 的过程中,遇见的第n个像素值为0的点 就是第n个连通域的种子点,进一步说,在整个遍历过程中,遇见像素值为0的像素点的个数,就是连通域的个数。
是的!

当然,如果要实现这一点,那我们就需要在各个连通域的寻找的过程中,将找到的点全部立即置为255,(此处不一定非得是255,只要不是0即可)这样在寻找结束后,我们再遍历二值图时,已经找到的连通域中的所有像素点的值均为255,当再次找到像素值为0 的像素点时,此像素点必是下一个待寻找的连通域的种子点

连通域的寻找过程

首先创建四连通的向量,vector upp;用来存储上下前后四个点,创建vector>> lenm;用来存储所有的连通域,至于为什么要创建三维Point数组,大家可以先看看关于这个三维数组的注释,(下面的公式就是,程序中也有相应的注释),了解清楚每一维代表的意义,再结合一下程序,我感觉大家应该可以明白,再简要赘述一下,lenm.size()为连通域的个数。

如图所示;函数为第i个连通域像素点个数的求和。

条件设定

在经过以上的寻找过程后,得到的结果必然是全白的图像,而我们只想要填充孔洞,所以我们需要去除不符合的连通域。所谓孔洞,其实就是周围被像素值为255的点包围起来的连通域,但是,有一些连通域,直接和图像的边界相连,而这并不是我们想要的, 至少不是我想要的,(如果大家有不同的需求,程序也是很容易改过去的)。所以,我需要一个标志位,当这个连通域中的像素点接触到边界后,给这个连通域一个标记。在下面的程序中,我用vector> Flag;来存储标记点,其中Flag[i]表示第i个连通域的标记点。在程序中,找到种子点后,首先将第i个连通域的Flag[i][0] = 1;,如果在此连通域中出现边界点,再Flag[i][0] = 0;(在程序中,此处貌似有一个小BUG,我就先不改了[?])

最后赋值

在寻找到的所有连通域中,Flag[i][0] == 1; {其中 i 属于 [0,Flag.size()) }的连通域为符合要求的连通域,因此将lenm[i];中的所有像素点赋值255即可。

话不多说 直接上函数代码

输入二值图;

返回二值图;

Mat imfill(Mat cop){        Mat fcop;        cop.copyTo(fcop);        vector upp;//定义四连通点集,有必要可以是八连通        upp.push_back(Point(-1, 0));        upp.push_back(Point(0, -1));        upp.push_back(Point(0, 1));        upp.push_back(Point(1, 0));        //upp.push_back(Point(1, 1));        //upp.push_back(Point(-1,-1));        //upp.push_back(Point(-1, 1));        //upp.push_back(Point(1, -1));        vector>> lenm;//三维point向量 lenm.size()是连通域的个数        /*        int impixel_sum = 0;        for (int j = 0,j> numim;        vector ssinum;        vector> Flag;        vector ce;        int nmss = 0;//连通域的个数;        int nums = 0;//中间变量 用来存储 lenm.size();即 在程序运行过程中 nums始终等于 lenm[i][j][k] 中的j 的 值的大小;        int s1 = 0;        //标志位 ,每次区域生长后 符合条件的像素个数,当第i个连通域,在经过第j次生长后,s1=lenm[i][j].size(),        //若s1==0,表示生长结束,不再有符合条件的点,第i连通域中的所有点都已经找到。        for (int row = 0; row < fcop.rows; row++)        {                for (int col = 0; col < fcop.cols; col++)                {                        if (fcop.at(row, col) == 0)                        {                                ce.push_back(1);                                Flag.push_back(ce);                                //vector> numim;                                //vector ssinum;                                ssinum.push_back(Point(col, row));                                numim.push_back(ssinum);                                fcop.at(row, col) = 255;                                ssinum.clear();                                s1 = 1;                                while (s1 > 0)                                {                                        //ce.push_back(1);                                        //Flag.push_back(ce);                                        //vector ssinum;                                        for (int i = 0; i < numim[nums].size(); i++)                                        {                                                for (int j = 0; j < upp.size(); j++)                                                {                                                        int X = numim[nums][i].x + upp[j].x;                                                        int Y = numim[nums][i].y + upp[j].y;                                                        if (X >= 0 && Y >= 0 && X < fcop.cols && Y < fcop.rows)                                                        {                                                                if (fcop.at(Y, X) == 0)                                                                {                                                                        ssinum.push_back(Point(X, Y));                                                                        fcop.at(Y, X) = 255;                                                                }                                                        }                                                        if (X == 0 || Y == 0 || X == fcop.cols - 1 || Y == fcop.rows - 1)                                                        {                                                                Flag[nmss][0] = 0;                                                        }                                                }                                        }                                        //Flag.push_back(ce);                                        numim.push_back(ssinum);                                        s1 = ssinum.size();                                        nums++;                                        ssinum.clear();                                        /*ce.clear();*/                                }                                nums = 0;                                lenm.push_back(numim);                                numim.clear();                                nmss++;                                ce.clear();                        }                }        }        //imshow("1",fcop);        Mat ffcop;        cop.copyTo(ffcop);        //ffcop = Mat::zeros(cop.size(),cop.type());        for (int i = 0; i < Flag.size(); i++)        {                if (Flag[i][0] == 1)                {                        for (int j = 0; j < lenm[i].size(); j++)                        {                                for (int k = 0; k < lenm[i][j].size(); k++)                                {                                        int X = lenm[i][j][k].x;                                        int Y = lenm[i][j][k].y;                                        ffcop.at(Y, X) = 255;                                }                        }                }        }        return ffcop;}

主函数代码

#include#include#include"imfill.h"using namespace std;using namespace cv;Mat src;vector>  lunk;vector level;//RNG rn;int main(){        src = imread("5.jpg");        //imshow("万丈高楼第一步",src);        Mat dst, gray, erzhi;        blur(src, dst, Size(3, 3), Point(-1, -1));        //imshow("均值滤波",dst);        cvtColor(dst, gray, COLOR_BGR2GRAY);        //imshow("灰度图",gray);        Canny(gray, erzhi, 100, 200, 3, false);        //imshow("边缘检测",erzhi);        Mat holef;        holef = imfill(erzhi);        imshow("填洞", holef);                waitKey(0);        return 0;}

代码框截图

实例图片

运行结果

以上是"C++中Opencv的imfill孔洞填充函数怎么用"这篇文章的所有内容,感谢各位的阅读!相信大家都有了一定的了解,希望分享的内容对大家有所帮助,如果还想学习更多知识,欢迎关注行业资讯频道!

像素 个数 程序 函数 过程 种子 孔洞 就是 条件 存储 C++ 代码 内容 标记 篇文章 边界 三维 向量 图像 数组 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 数据库每个表都要有业务主键嘛 关于网络安全教育的前言 数据库恢复主要的技术是什么 蟑螂数据库开启debug dell新品服务器 邯郸计算机应用软件开发价钱 东城区智能化网络技术服务系统 mac用于软件开发 数据库管理系统怎么导入数据 云柜网络技术有限公司 材料一 青少年网络安全 手机版本升级显示服务器不可用 保定维云网络技术上班时间 恐龙王兽数据库 浪潮服务器没有网络 程序员从事信息安全行业软件开发 重庆网络安全和信息化委员会 网络安全培训服务费用标准 软件开发后被抄袭 服务器两块硬盘分区总有一块脱机 sql数据库清理垃圾 电子商务网站数据库设计实例 省市区数据库设计几张表好 ftp后台的数据库 联想服务器远程授权管理器 图灵网络技术有限公司绍兴 网络安全与执法类公务员近视 宝塔创建数据库索引 网络安全我的故事500字 辽宁省林业数据库
0