connectedComponentsWithStats() 是一个非常好用的连通域分析函数,可以检测连通域,获取连通域的面积、宽度/高度、质心和左上角顶点坐标等。
1、函数用法
Mat labels; //CV_32F通道的标签矩阵,不同的连通域被赋予不同的标签值(int类型)
Mat stats; //包含连通域统计信息的矩阵
Mat centroids; //连通域的质心坐标矩阵
int num = connectedComponentsWithStats(src, labels, stats, centroids, 8, CV_16U);
2、参数说明
参数src //输入的检测图,一般为二值图,255为目标,0为背景
返回值num //连通域数量,第一个(i=0)连通域为黑色背景
int acreage = stats.at<int>(i, CC_STAT_AREA) //第i个连通域的面积(包含的像素点总数)
int left = stats.at<int>(i, CC_STAT_LEFT) //第i个连通域的bbox的最左边坐标值
int top = stats.at<int>(i, CC_STAT_TOP) //第i个连通域的bbox的最上边坐标值
int width= stats.at<int>(i, CC_STAT_WIDTH) //第i个连通域的宽度
int height stats.at<int>(i, CC_STAT_HEIGHT) //第i个连通域的高度
double center_x = centroids.at<double>(i, 0) //第i个连通域的质心x坐标(col)
double center_y = centroids.at<double>(i, 1) //第i个连通域的质心x坐标(row)
3、例子:只保留图中连通域面积较大的区域
如果我们只想保留二值图中连通域面积大于某个阈值(如100)的区域,有两种思路:
(1)在原图中将不满足条件的连通域的覆盖为黑色。
(2)将满足条件的连通域复制到一张全黑图像上。
具体实现见代码:
//筛选出面积大于100的区域,输入src,输出dst
Mat labels, stats, centroids;
sizet num = connectedComponentsWithStats(src, labels, stats, centroids, 8, CV_16U);
vector<Vec3b> colors(num);
colors[0] = Vec3b(0, 0, 0); //第一个连通域是黑色背景
for (sizet i = 1; i != num; i++)
{
if (stats.at<int>(i, CC_STAT_AREA) > 100)
colors[i] = Vec3b(255, 255, 255); //给连通域添加颜色
else
colors[i] = Vec3b(0, 0, 0);
}
Mat aimArea = Mat::zeros(src.size(), CV_8UC3); //注意需要是CV_8UC3的三通道图
for (sizet row = 0; row != src.rows; row++)
for (sizet col = 0; col != src.cols; col++)
{
//获取原图中每个点的label
sizet label = labels.at<uint16_t>(row, col);
aimArea.at<Vec3b>(row, col) = colors[label];
}
Mat dst;
cvtColor(aimArea , dst, COLOR_BGR2GRAY); //转换为单通道图