OpenCV学习笔记(十三)之连通组件标记

本文介绍了OpenCV中的连通组件标记算法,包括两步法的原理、8邻域概念以及OpenCV提供的API函数。通过实例展示了如何使用API函数进行连通域统计,并提供了代码实现。
摘要由CSDN通过智能技术生成
一、联通组件标记算法原理

  很长时间没更新了,今天开始继续更新OpenCV学习笔记相关内容。今天说的是图像处理中最常用的分析方法:连通组件标记算法。这里只介绍两步法,也就是OpenCV库中自带的那种。
  两步法的连通组件标记算法的实质是分两步扫描二值图像。第一步扫描图像的每个像素点,对于像素值相同的而且相互连通分为相同的组(group),标记为Label 1,持续进行扫描,最终得到图像中所有的像素连通组件。扫描的方式可以是从上到下,从左到右,对于一幅有N个像素的图像来说,如果以4邻域计算,最大连通组件个数为N/2。第一步完成以后会获得多个Label,有的Label与Label之间是有像素点连接在一起的,这些Label可以合并为一个Label,这就是第二步需要做的工作。
在正式讲解两步法前先回顾下邻域的概念:
如果一个像素P(x,y),它和它左边的像素、上边的像素、右边的像素、下边的像素相邻,那么我们称为4邻域,就像下面的图中黄色部分:
4邻域
如果一个像素P(x,y),它和它左边的像素、左上的像素、左下的像素、上边的像素、右上的像素、右边的像素、右下的像素、下边的像素相邻,那么我们称为8邻域,就像下面的图中黄色部分:
8邻域
  之所以再次介绍邻域是因为OpenCV中联通组件标记算法的API函数中默认是8邻域统计的。接下来以图片的形式展示两步法:

  1. 第一步:按照从左到右、从上到下的顺序扫描图像中所有像素点,给每个不同的连通域赋予不同的labels,如下图所示,在第一步执行完以后会出现总共10个labels。假如以左上顶点作为坐标原点(0、0),需要注意的是第三行,第六列的这个点P(2、5),该点被赋予label 4而不是label 6的原因是我们这里使用的是8邻域的查找方法,同时这里还会标记label 6 -> label 4,标签6隶属于标签4。这样在第二步的时候就会将具有从属关系的标签进行合并。
    第一步
    6 → 4 6\rightarrow4 64 9 → 8 9\rightarrow8 98

  2. 第二步:将第一步中统计出来的具有从属关系的label进行合并,合并完成以后再将标签重新排序,得到如下图所示结果:
    第二步
    这样就统计出来总共有8个不同的连通域存在。注:如果是4邻域统计的话,就会有12个不同的连通域。

二、OpenCV中的API函数

  下面是OpenCV中关于联通标记组件算法的API函数,总共有两种,一种是不带状态标记的,一种是带状态标记的。

//带状态标记的API函数
CV_EXPORTS_W int connectedComponentsWithStats(InputArray image, OutputArray labels,
                                              OutputArray stats, OutputArray centroids,
                                              int connectivity = 8, int ltype = CV_32S);
//不带状态标记的API函数
CV_EXPORTS_W int connectedComponents(InputArray image, OutputArray labels,
                                     int connectivity = 8, int ltype = CV_32S);

这里只介绍带状态标记的API函数
4. image:输入图像,格式必须是8位单通道图像,可以是灰度图,也可以是二值化图
5. labels:输出的标签图像,格式由最后一个参数ltype决定,一般是默认的CV_32S
6. stats:输出的统计信息,里面包含每个连通域的面积,最小外接矩形的x、y、width、height等;
7. centroids:每个连通域的质心坐标;
8. connectivity:决定连通域寻找方法,有4邻域和8邻域两种,默认是8邻域;
9. ltype:决定labels的图像格式,有CV_32S和CV_16U两种

三、代码实现

先将效果图展示出来,如下图所示:
图一
图二
图三
分别统计出了连通域个数、每个连通域的面积、质心坐标等参数。

// ConnectComponent.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include "pch.h"
#include <iostream>
#include "opencv2/opencv.hpp"

using namespace std;
using namespace cv;

RNG rng(12345);

//将RGB图片拆分成3个通道图像,转化为单通道灰度图
void SplitRGB2SingleGray(Mat Image, int i, Mat &Gray_Single_Image)
 {
   
	vector<Mat>RGB_Channels(3);
 	split(Image, RGB_Channels);
	Gray_Single_Image.create(Image.rows, Image.cols, CV_8UC1);
	for (int row = 0; row < Gray_Single_Image.rows
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值