0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

OpenCV4笔记之连通域分析

OpenCV学堂 来源:OpenCV学堂 2023-12-25 17:16 次阅读

Part11. 图像的连通域以及连通域分析

在该系列第六篇文章中,曾经介绍过连通的概念,下面再来回顾一下。

连通:若 S 是图像中的一个像素子集,对于任意的 。如果存在一条由 S 中像素组成的从 p 到 q 的通路,则称 p 在像素集 S 中与 q 连通

连通域是指具有相同属性的连通集合。例如,在一个二值图像中,具有相同像素值的区域构成一个连通域。

所以,连通连通域是两个不同的概念,连通域连通的子集。连通域具有以下特性:

一个连通域中的所有像素都具有相同的性质。

一个连通域中的任意两个像素都可以通过连续的路径连接起来。

一个连通域可以是单连通的,也可以是多连通的。

连通域分析是指在图像中查找标记连通域的算法。这是一种常用的图像处理技术,可以用于目标检测、图像分割和形状识别等等。本文是基于二值图像进行连通域的分析。

Part22. 连通域分析的算法

连通域分析的算法可以分为以下几类:

基于标记的算法:该类算法首先将每个像素分配一个唯一的标记,然后使用某种策略将具有相同标记的像素连接起来。基于标记的算法包括两遍扫描法、种子填充法和快速连通域查找法。

基于邻域查找的算法:该类算法从图像中的一个起始像素开始,逐个检查其邻域像素,如果邻域像素具有相同像素值,则将其加入到当前连通域中。基于邻域查找的算法包括深度优先搜索(DFS)和广度优先搜索(BFS)。

基于分割的算法:该类算法将图像分割成多个区域,每个区域都具有相同的像素值。基于分割的算法包括图论方法和区域生长法。

其中,基于标记的算法是比较常用的连通域分析的算法。

12.1 两遍扫描法

两遍扫描算法的步骤如下

第一遍扫描

从左到右,从上到下遍历图像。

将每个有效像素赋予一个唯一的标记。

第二遍扫描

再次从左到右,从上到下遍历图像。

检查两个相邻像素是否具有相同的标记。

如果两个相邻像素具有相同的标记,则将它们连接起来。

6852f152-a304-11ee-8b88-92fbcf53809c.giftwo-pass.gif

22.2 种子填充法

种子填充算法的步骤如下:

初始化:将图像中的所有像素标记为未访问。

选择一个起始像素作为种子。

将种子像素标记为已访问。

检查种子像素的邻域像素。

如果邻域像素具有相同的像素值,则将其标记为已访问。

如果邻域像素具有不同的像素值,则忽略。

重复步骤 4,直到图像中的所有像素都被标记为已访问或直到没有未访问的邻域像素为止。

68707b8c-a304-11ee-8b88-92fbcf53809c.gifseed-filling.gif

Part33. OpenCV 自带的连通域函数

OpenCV 提供了两个函数:connectedComponents()、connectedComponentsWithStats() 在二值图像中查找连通域。

下面的例子,在图中找到连通域并标记不同的颜色。

#include
#include
#include"opencv2/imgproc.hpp"
#include"opencv2/highgui.hpp"

usingnamespacestd;
usingnamespacecv;

voidlabelColor(Mat&labelImg,Mat&dst)
{
mapcolors;

intwidth=labelImg.cols;
intheight=labelImg.rows;

dst=Mat::zeros(labelImg.size(),CV_8UC3);

ucharr=255*(rand()/(1.0+RAND_MAX));
ucharg=255*(rand()/(1.0+RAND_MAX));
ucharb=255*(rand()/(1.0+RAND_MAX));

for(inti=0;i< height; i++)
    {
        int* data_src = (int*)labelImg.ptr(i);
uchar*data_dst=dst.ptr(i);

for(intj=0;j< width; j++)
        {
            int pixelValue = data_src[j];
            if (pixelValue >=1)
{
if(colors.count(pixelValue)==0)
{
colors[pixelValue]=Scalar(b,g,r);
r=255*(rand()/(1.0+RAND_MAX));
g=255*(rand()/(1.0+RAND_MAX));
b=255*(rand()/(1.0+RAND_MAX));
}

Scalarcolor=colors[pixelValue];
*data_dst++=color[0];
*data_dst++=color[1];
*data_dst++=color[2];
}
else
{
data_dst++;
data_dst++;
data_dst++;
}
}
}
}

intmain(intargc,char**argv){
Matsrc=imread(".../coins.jpg");
imshow("src",src);

Matgray,thresh;
cvtColor(src,gray,cv::COLOR_BGR2GRAY);//灰度化
imshow("gray",gray);

Matgauss;
GaussianBlur(gray,gauss,Size(15,15),0);//降噪

threshold(gauss,thresh,0,255,THRESH_BINARY|THRESH_OTSU);
imshow("thresh",thresh);

Matlabels,stats,centroids;
intnum_labels=connectedComponents(thresh,labels,8,CV_32S);
cout<< "num_labels = " << num_labels << endl;

    Mat result;
    labelColor(labels,result);
    imshow("Connected Components", result);

    waitKey(0);

    return 0;
}
原图和灰度化.png 二值化和标记连通域.png
intconnectedComponents(InputArrayimage,OutputArraylabels,intconnectivity,intltype,intccltype);

其各个参数的含义:

第一个参数 image:输入图像必须是二值图像1。第二个参数 labels:输出图像,其中每个像素值表示其所在连通域的标签。标签的值从 0 开始,依次递增。第三个参数 connectivity:标记连通域时使用的邻域种类。可选的是 4、8,默认值是 8。第四个参数 ltype:输出标签的类型。可以设置为 CV_32S 或 CV_16U,默认值是 CV_32S 。第五个参数 ccltype:标记连通域分析算法的类型。

参数类型 作用
CCL_WU 0 8 邻域和 4 邻域均用 SAUF 算法。
CCL_DEFAULT -1 8 邻域用 BBDT 算法,4 邻域用 SAUF 算法。
CCL_GRANA 1 8 邻域用 BBDT 算法,4 邻域用 SAUF 算法。

connectedComponentsWithStats() 函数除了返回每个连通域的标签之外,还返回每个连通域的其他信息,包括:

面积

外接矩形

中心坐标

intmain(intargc,char**argv){
Matsrc=imread(".../coins.jpg");
imshow("src",src);

Matgray,thresh;
cvtColor(src,gray,cv::COLOR_BGR2GRAY);//灰度化
imshow("gray",gray);

Matgauss;
GaussianBlur(gray,gauss,Size(15,15),0);//降噪

threshold(gauss,thresh,0,255,THRESH_BINARY|THRESH_OTSU);
imshow("thresh",thresh);

Matlabels,stats,centroids;
intnum_labels=connectedComponentsWithStats(thresh,labels,stats,centroids);
cout<< "num_labels = " << num_labels << endl;

    for (int i = 1; i < num_labels; i++)
    {
        int area = stats.at(i,CC_STAT_AREA);
intleft=stats.at(i,CC_STAT_LEFT);
inttop=stats.at(i,CC_STAT_TOP);
intwidth=stats.at(i,CC_STAT_WIDTH);
intheight=stats.at(i,CC_STAT_HEIGHT);
intcx=centroids.at(i,0);
intcy=centroids.at(i,1);

cout<< "Object " << i << ": " << "Area=" << area << ", Left=" << left << ", Top=" << top << ", Width=" << width << ", Height=" << height << ", Centroid=(" << cx << ", " << cy << ")" << endl;

        rectangle(src, Point(left, top), Point(left + width, top + height), Scalar(0,0,255), 2);
        circle(src, Point(cx, cy), 2, Scalar(0,0,255), 2);
    }
    imshow("Connected Components", src);
    waitKey(0);

    return 0;
}

执行结果:

num_labels=8
Object1:Area=17061,Left=344,Top=160,Width=144,Height=151,Centroid=(415,234)
Object2:Area=9655,Left=592,Top=411,Width=108,Height=114,Centroid=(645,467)
Object3:Area=9558,Left=776,Top=441,Width=108,Height=113,Centroid=(828,497)
Object4:Area=17874,Left=435,Top=517,Width=150,Height=152,Centroid=(509,592)
Object5:Area=17502,Left=660,Top=648,Width=148,Height=151,Centroid=(733,723)
Object6:Area=10420,Left=726,Top=864,Width=114,Height=117,Centroid=(782,922)
Object7:Area=15634,Left=628,Top=1075,Width=141,Height=143,Centroid=(698,1146)

Part44. 总结

连通域分析是图像处理中常用的算法之一,用于在二值图像中找到具有相同像素值且相互连接的区域。它在图像处理中具有广泛的应用场景。

审核编辑:汤梓红

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 算法
    +关注

    关注

    23

    文章

    4458

    浏览量

    90761
  • 图像
    +关注

    关注

    2

    文章

    1064

    浏览量

    40042
  • 函数
    +关注

    关注

    3

    文章

    3904

    浏览量

    61310
  • OpenCV
    +关注

    关注

    29

    文章

    611

    浏览量

    40790

原文标题:OpenCV4笔记 之 连通域分析

文章出处:【微信号:CVSCHOOL,微信公众号:OpenCV学堂】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    OpenCV4.8 CUDA编程代码教程

    OpenCV4支持通过GPU实现CUDA加速执行,实现对OpenCV图像处理程序的加速运行,当前支持加速的模块包括如下。
    的头像 发表于 12-05 09:56 454次阅读
    <b class='flag-5'>OpenCV</b>4.8 CUDA编程代码教程

    ACER 370笔记本电脑主板电路图

    本帖最后由 gk320830 于 2015-3-9 03:41 编辑 ACER 370笔记本电脑主板电路图
    发表于 08-16 20:45

    爱鼓捣stm32笔记

    爱鼓捣stm32笔记1-4
    发表于 06-16 17:37

    matlab连通的数字标记

    在matlab中对二值图像不同的连通进行标写序号该用什么语句函数啊?
    发表于 10-13 20:26

    【坛友经验分享】嵌入式STM32 深入浅出(五篇)

    之三:让它跑起来,基本硬件功能的建立STM32笔记四:工作工作,PWM输出 STM32笔记五:恶搞,两只看门狗
    发表于 08-31 17:29

    xilinx系统生成器版本14.2可以在Windows 8.1笔记本电脑上运行吗?

    xilinx系统生成器版本14.2可以在我的Windows 8.1笔记本电脑上运行吗???请帮助
    发表于 04-21 06:15

    STM32笔记 EXIT(外部中断)精选资料分享

    /O映像三、中断服务四、配置流程(代码解析)五、中断函数处理在上一篇STM32笔记 GPIO引脚中,有用到 EXIT外部中断作为 Key输入触发,所以本篇来...
    发表于 08-05 06:10

    联想YOGA 13笔记本电源适配器修理相关资料下载

    联想YOGA 13笔记本电源适配器修理分类: 兴趣 |标签:开关电源yoga笔记本电源(转自网易博客)  我的YOGA是联想第一批出厂的,2012年9月份从联想商场网站预订,10月底收到货,一直用到
    发表于 12-27 06:20

    鲁班猫0 -安装opencv

    ON OPENCV_GENERATE_PKGCONFIG 因为opencv4默认不生成.pc文件,所以加上这句用于生成opencv4.pc文件,支持pkg-config功能。opencv4
    发表于 04-09 13:29

    CMake在Linux 6.1.1-1.0.0中搜索包opencv损坏了吗?

    imx-image-multimedia 的 SDK,我收到以下错误: sysroots/armv8a-poky-linux/usr/lib/cmake/opencv4/OpenCVModules.cmake
    发表于 05-09 11:32

    在AN-683笔记中,将AD8221更换为AD8429是否会更好?

    在AN-683笔记(使用交流激励进行应变计测量)中,将AD8221更换为AD8429是否会更好?工作温度为-40~125。
    发表于 11-27 06:55

    opencv编译安装笔记(Linux、Ubuntu )

    本文介绍了两种opencv编译安装笔记:Linux下编译安装OpenCV和Ubuntu 下安装 OpenCV。有需要的小伙伴可以看看。
    发表于 12-03 10:33 4941次阅读
    <b class='flag-5'>opencv</b>编译安装<b class='flag-5'>笔记</b>(Linux、Ubuntu )

    基于opencv4和Yolo-Fastest,实现PC和单片机通信,控制步进电机捕获目标

    效果视频 基于opencv4和yolo,实现PC和单片机通信,控制步进电机捕获目标
    发表于 11-23 17:36 15次下载
    基于<b class='flag-5'>opencv4</b>和Yolo-Fastest,实现PC和单片机通信,控制步进电机捕获目标

    如何在Raspberry Pi 3上安装OpenCV4

    今天我们将学习如何在 Raspberry Pi 3 上安装 OpenCV4 库,以便我们可以将其用于计算机视觉应用程序。这将允许 OpenCV 在像 Pi 这样的便携式设备上运行,从而打开许多可能性的大门。所以让我们开始吧
    的头像 发表于 09-08 16:09 1370次阅读
    如何在Raspberry Pi 3上安装<b class='flag-5'>OpenCV4</b>库

    学习OpenCV4的系统化路线图

    OpenCV4发布测试版本开始,作者就一直关注!根据自己近十年图像处理OpenCV开发相关工作经验,花了七个月的时间,针对OpenCV4、精心选择OpenCV中常用模块与知识点,构建
    的头像 发表于 07-05 11:30 371次阅读
    学习<b class='flag-5'>OpenCV4</b>的系统化路线图